- Main Page
- Namespaces
- Classes
- Files

- File List

# WindowImplWin32.cpp

    00001
    00002 //
    00003 // SFML - Simple and Fast Multimedia Library
    00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
    00005 //
    00006 // This software is provided 'as-is', without any express or implied warranty.
    00007 // In no event will the authors be held liable for any damages arising from the use of this software.
    00008 //
    00009 // Permission is granted to anyone to use this software for any purpose,
    00010 // including commercial applications, and to alter it and redistribute it freely,
    00011 // subject to the following restrictions:
    00012 //
    00013 // 1. The origin of this software must not be misrepresented;
    00014 //    you must not claim that you wrote the original software.
    00015 //    If you use this software in a product, an acknowledgment
    00016 //    in the product documentation would be appreciated but is not required.
    00017 //
    00018 // 2. Altered source versions must be plainly marked as such,
    00019 //    and must not be misrepresented as being the original software.
    00020 //
    00021 // 3. This notice may not be removed or altered from any source distribution.
    00022 //
    00024
    00026 // Headers
    00028 #define _WIN32_WINDOWS 0x0501
    00029 #define _WIN32_WINNT   0x0501
    00030 #include <SFML/Window/Win32/WindowImplWin32.hpp>
    00031 #include <SFML/Window/WindowSettings.hpp>
    00032 #include <SFML/Window/WindowStyle.hpp>
    00033 #include <GL/gl.h>
    00034 #include <SFML/Window/glext/wglext.h>
    00035 #include <SFML/Window/glext/glext.h>
    00036 #include <iostream>
    00037 #include <vector>
    00038
    00039 // MinGW lacks the definition of some Win32 constants
    00040 #ifndef XBUTTON1
    00041     #define XBUTTON1 0x0001
    00042 #endif
    00043 #ifndef XBUTTON2
    00044     #define XBUTTON2 0x0002
    00045 #endif
    00046 #ifndef MAPVK_VK_TO_VSC
    00047     #define MAPVK_VK_TO_VSC (0)
    00048 #endif
    00049
    00050
    00051 namespace sf
    00052 {
    00053 namespace priv
    00054 {
    00056 // Static member data
    00058 unsigned int     WindowImplWin32::ourWindowCount      = 0;
    00059 const char*      WindowImplWin32::ourClassNameA       = "SFML_Window";
    00060 const wchar_t*   WindowImplWin32::ourClassNameW       = L"SFML_Window";
    00061 WindowImplWin32* WindowImplWin32::ourFullscreenWindow = NULL;
    00062
    00063
    00068 WindowImplWin32::WindowImplWin32() :
    00069 myHandle          (NULL),
    00070 myCallback        (0),
    00071 myCursor          (NULL),
    00072 myIcon            (NULL),
    00073 myKeyRepeatEnabled(true),
    00074 myIsCursorIn      (false)
    00075 {
    00076     // Register the window class at first call
    00077     if (ourWindowCount == 0)
    00078         RegisterWindowClass();
    00079
    00080     // Use small dimensions
    00081     myWidth  = 1;
    00082     myHeight = 1;
    00083
    00084     // Create a dummy window (disabled and hidden)
    00085     if (HasUnicodeSupport())
    00086     {
    00087         myHandle = CreateWindowW(ourClassNameW, L"", WS_POPUP | WS_DISABLED, 0, 0, myWidth, myHeight, NULL, NULL, GetModuleHandle(NULL), NULL);
    00088     }
    00089     else
    00090     {
    00091         myHandle = CreateWindowA(ourClassNameA, "", WS_POPUP | WS_DISABLED, 0, 0, myWidth, myHeight, NULL, NULL, GetModuleHandle(NULL), NULL);
    00092     }
    00093     ShowWindow(myHandle, SW_HIDE);
    00094
    00095     // Create the rendering context
    00096     if (myHandle)
    00097     {
    00098         WindowSettings Params(0, 0, 0);
    00099         CreateContext(VideoMode(myWidth, myHeight, 32), Params);
    00100
    00101         // Don't activate by default
    00102         SetActive(false);
    00103     }
    00104 }
    00105
    00106
    00110 WindowImplWin32::WindowImplWin32(WindowHandle Handle, WindowSettings& Params) :
    00111 myHandle          (NULL),
    00112 myCallback        (0),
    00113 myCursor          (NULL),
    00114 myIcon            (NULL),
    00115 myKeyRepeatEnabled(true),
    00116 myIsCursorIn      (false)
    00117 {
    00118     // Save window handle
    00119     myHandle = static_cast<HWND>(Handle);
    00120
    00121     if (myHandle)
    00122     {
    00123         // Get window client size
    00124         RECT Rect;
    00125         GetClientRect(myHandle, &Rect);
    00126         myWidth  = Rect.right - Rect.left;
    00127         myHeight = Rect.bottom - Rect.top;
    00128
    00129         // Create the rendering context
    00130         VideoMode Mode(myWidth, myHeight, VideoMode::GetDesktopMode().BitsPerPixel);
    00131         CreateContext(Mode, Params);
    00132
    00133         // We change the event procedure of the control (it is important to save the old one)
    00134         SetWindowLongPtr(myHandle, GWLP_USERDATA, reinterpret_cast<long>(this));
    00135         myCallback = SetWindowLongPtr(myHandle, GWLP_WNDPROC, reinterpret_cast<long>(&WindowImplWin32::GlobalOnEvent));
    00136     }
    00137 }
    00138
    00139
    00143 WindowImplWin32::WindowImplWin32(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) :
    00144 myHandle          (NULL),
    00145 myCallback        (0),
    00146 myCursor          (NULL),
    00147 myIcon            (NULL),
    00148 myKeyRepeatEnabled(true),
    00149 myIsCursorIn      (false)
    00150 {
    00151     // Register the window class at first call
    00152     if (ourWindowCount == 0)
    00153         RegisterWindowClass();
    00154
    00155     // Compute position and size
    00156     HDC ScreenDC = GetDC(NULL);
    00157     int Left   = (GetDeviceCaps(ScreenDC, HORZRES) - Mode.Width)  / 2;
    00158     int Top    = (GetDeviceCaps(ScreenDC, VERTRES) - Mode.Height) / 2;
    00159     int Width  = myWidth  = Mode.Width;
    00160     int Height = myHeight = Mode.Height;
    00161     ReleaseDC(NULL, ScreenDC);
    00162
    00163     // Choose the window style according to the Style parameter
    00164     DWORD Win32Style = WS_VISIBLE;
    00165     if (WindowStyle == Style::None)
    00166     {
    00167         Win32Style |= WS_POPUP;
    00168     }
    00169     else
    00170     {
    00171         if (WindowStyle & Style::Titlebar) Win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
    00172         if (WindowStyle & Style::Resize)   Win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
    00173         if (WindowStyle & Style::Close)    Win32Style |= WS_SYSMENU;
    00174     }
    00175
    00176     // In windowed mode, adjust width and height so that window will have the requested client area
    00177     bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0;
    00178     if (!Fullscreen)
    00179     {
    00180         RECT Rect = {0, 0, Width, Height};
    00181         AdjustWindowRect(&Rect, Win32Style, false);
    00182         Width  = Rect.right - Rect.left;
    00183         Height = Rect.bottom - Rect.top;
    00184     }
    00185
    00186     // Create the window
    00187     if (HasUnicodeSupport())
    00188     {
    00189         wchar_t WTitle[256];
    00190         int NbChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Title.c_str(), static_cast<int>(Title.size()), WTitle, sizeof(WTitle) / sizeof(*WTitle));
    00191         WTitle[NbChars] = L'\0';
    00192         myHandle = CreateWindowW(ourClassNameW, WTitle, Win32Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
    00193     }
    00194     else
    00195     {
    00196         myHandle = CreateWindowA(ourClassNameA, Title.c_str(), Win32Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
    00197     }
    00198
    00199     // Switch to fullscreen if requested
    00200     if (Fullscreen)
    00201         SwitchToFullscreen(Mode);
    00202
    00203     // Create the rendering context
    00204     if (myHandle)
    00205         CreateContext(Mode, Params);
    00206
    00207     // Increment window count
    00208     ourWindowCount++;
    00209
    00210     // Get the actual size of the window, which can be smaller even after the call to AdjustWindowRect
    00211     // This happens when the window is bigger than the desktop
    00212     RECT ActualRect;
    00213     GetClientRect(myHandle, &ActualRect);
    00214     myWidth  = ActualRect.right - ActualRect.left;
    00215     myHeight = ActualRect.bottom - ActualRect.top;
    00216 }
    00217
    00218
    00222 WindowImplWin32::~WindowImplWin32()
    00223 {
    00224     // Destroy the custom icon, if any
    00225     if (myIcon)
    00226         DestroyIcon(myIcon);
    00227
    00228     if (!myCallback)
    00229     {
    00230         // Destroy the window
    00231         if (myHandle)
    00232             DestroyWindow(myHandle);
    00233
    00234         // Decrement the window count
    00235         ourWindowCount--;
    00236
    00237         // Unregister window class if we were the last window
    00238         if (ourWindowCount == 0)
    00239         {
    00240             if (HasUnicodeSupport())
    00241             {
    00242                 UnregisterClassW(ourClassNameW, GetModuleHandle(NULL));
    00243             }
    00244             else
    00245             {
    00246                 UnregisterClassA(ourClassNameA, GetModuleHandle(NULL));
    00247             }
    00248         }
    00249     }
    00250     else
    00251     {
    00252         // The window is external : remove the hook on its message callback
    00253         SetWindowLongPtr(myHandle, GWLP_WNDPROC, myCallback);
    00254     }
    00255 }
    00256
    00257
    00261 bool WindowImplWin32::IsContextActive()
    00262 {
    00263     return wglGetCurrentContext() != NULL;
    00264 }
    00265
    00266
    00270 void WindowImplWin32::ProcessEvents()
    00271 {
    00272     // We update the window only if we own it
    00273     if (!myCallback)
    00274     {
    00275         MSG Message;
    00276         while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
    00277         {
    00278             TranslateMessage(&Message);
    00279             DispatchMessage(&Message);
    00280         }
    00281     }
    00282 }
    00283
    00284
    00288 void WindowImplWin32::Display()
    00289 {
    00290     if (myDeviceContext && myGLContext)
    00291         SwapBuffers(myDeviceContext);
    00292 }
    00293
    00294
    00298 void WindowImplWin32::SetActive(bool Active) const
    00299 {
    00300     if (Active)
    00301     {
    00302         if (myDeviceContext && myGLContext && (wglGetCurrentContext() != myGLContext))
    00303             wglMakeCurrent(myDeviceContext, myGLContext);
    00304     }
    00305     else
    00306     {
    00307         if (wglGetCurrentContext() == myGLContext)
    00308             wglMakeCurrent(NULL, NULL);
    00309     }
    00310 }
    00311
    00312
    00316 void WindowImplWin32::UseVerticalSync(bool Enabled)
    00317 {
    00318     PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT"));
    00319     if (wglSwapIntervalEXT)
    00320         wglSwapIntervalEXT(Enabled ? 1 : 0);
    00321 }
    00322
    00323
    00327 void WindowImplWin32::ShowMouseCursor(bool Show)
    00328 {
    00329     if (Show)
    00330         myCursor = LoadCursor(NULL, IDC_ARROW);
    00331     else
    00332         myCursor = NULL;
    00333
    00334     SetCursor(myCursor);
    00335 }
    00336
    00337
    00341 void WindowImplWin32::SetCursorPosition(unsigned int Left, unsigned int Top)
    00342 {
    00343     POINT Pos = {Left, Top};
    00344     ClientToScreen(myHandle, &Pos);
    00345     SetCursorPos(Pos.x, Pos.y);
    00346 }
    00347
    00348
    00352 void WindowImplWin32::SetPosition(int Left, int Top)
    00353 {
    00354     SetWindowPos(myHandle, NULL, Left, Top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    00355 }
    00356
    00357
    00361 void WindowImplWin32::SetSize(unsigned int Width, unsigned int Height)
    00362 {
    00363     // SetWindowPos wants the total size of the window (including title bar and borders),
    00364     // so we have to compute it
    00365     RECT Rect = {0, 0, Width, Height};
    00366     AdjustWindowRect(&Rect, GetWindowLong(myHandle, GWL_STYLE), false);
    00367     Width  = Rect.right - Rect.left;
    00368     Height = Rect.bottom - Rect.top;
    00369
    00370     SetWindowPos(myHandle, NULL, 0, 0, Width, Height, SWP_NOMOVE | SWP_NOZORDER);
    00371 }
    00372
    00373
    00377 void WindowImplWin32::Show(bool State)
    00378 {
    00379     ShowWindow(myHandle, State ? SW_SHOW : SW_HIDE);
    00380 }
    00381
    00382
    00386 void WindowImplWin32::EnableKeyRepeat(bool Enabled)
    00387 {
    00388     myKeyRepeatEnabled = Enabled;
    00389 }
    00390
    00391
    00395 void WindowImplWin32::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
    00396 {
    00397     // First destroy the previous one
    00398     if (myIcon)
    00399         DestroyIcon(myIcon);
    00400
    00401     // Windows wants BGRA pixels : swap red and blue channels
    00402     std::vector<Uint8> IconPixels(Width * Height * 4);
    00403     for (std::size_t i = 0; i < IconPixels.size() / 4; ++i)
    00404     {
    00405         IconPixels[i * 4 + 0] = Pixels[i * 4 + 2];
    00406         IconPixels[i * 4 + 1] = Pixels[i * 4 + 1];
    00407         IconPixels[i * 4 + 2] = Pixels[i * 4 + 0];
    00408         IconPixels[i * 4 + 3] = Pixels[i * 4 + 3];
    00409     }
    00410
    00411     // Create the icon from the pixels array
    00412     myIcon = CreateIcon(GetModuleHandle(NULL), Width, Height, 1, 32, NULL, &IconPixels[0]);
    00413
    00414     // Set it as both big and small icon of the window
    00415     if (myIcon)
    00416     {
    00417         SendMessage(myHandle, WM_SETICON, ICON_BIG,   (LPARAM)myIcon);
    00418         SendMessage(myHandle, WM_SETICON, ICON_SMALL, (LPARAM)myIcon);
    00419     }
    00420     else
    00421     {
    00422         std::cerr << "Failed to set the window's icon" << std::endl;
    00423     }
    00424 }
    00425
    00426
    00430 void WindowImplWin32::RegisterWindowClass()
    00431 {
    00432     if (HasUnicodeSupport())
    00433     {
    00434         WNDCLASSW WindowClass;
    00435         WindowClass.style         = 0;
    00436         WindowClass.lpfnWndProc   = &WindowImplWin32::GlobalOnEvent;
    00437         WindowClass.cbClsExtra    = 0;
    00438         WindowClass.cbWndExtra    = 0;
    00439         WindowClass.hInstance     = GetModuleHandle(NULL);
    00440         WindowClass.hIcon         = NULL;
    00441         WindowClass.hCursor       = 0;
    00442         WindowClass.hbrBackground = 0;
    00443         WindowClass.lpszMenuName  = NULL;
    00444         WindowClass.lpszClassName = ourClassNameW;
    00445         RegisterClassW(&WindowClass);
    00446     }
    00447     else
    00448     {
    00449         WNDCLASSA WindowClass;
    00450         WindowClass.style         = 0;
    00451         WindowClass.lpfnWndProc   = &WindowImplWin32::GlobalOnEvent;
    00452         WindowClass.cbClsExtra    = 0;
    00453         WindowClass.cbWndExtra    = 0;
    00454         WindowClass.hInstance     = GetModuleHandle(NULL);
    00455         WindowClass.hIcon         = NULL;
    00456         WindowClass.hCursor       = 0;
    00457         WindowClass.hbrBackground = 0;
    00458         WindowClass.lpszMenuName  = NULL;
    00459         WindowClass.lpszClassName = ourClassNameA;
    00460         RegisterClassA(&WindowClass);
    00461     }
    00462 }
    00463
    00464
    00468 void WindowImplWin32::SwitchToFullscreen(const VideoMode& Mode)
    00469 {
    00470     DEVMODE DevMode;
    00471     DevMode.dmSize       = sizeof(DEVMODE);
    00472     DevMode.dmPelsWidth  = Mode.Width;
    00473     DevMode.dmPelsHeight = Mode.Height;
    00474     DevMode.dmBitsPerPel = Mode.BitsPerPixel;
    00475     DevMode.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
    00476
    00477     // Apply fullscreen mode
    00478     if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
    00479     {
    00480         std::cerr << "Failed to change display mode for fullscreen" << std::endl;
    00481         return;
    00482     }
    00483
    00484     // Make the window flags compatible with fullscreen mode
    00485     SetWindowLong(myHandle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
    00486     SetWindowLong(myHandle, GWL_EXSTYLE, WS_EX_APPWINDOW);
    00487
    00488     // Resize the window so that it fits the entire screen
    00489     SetWindowPos(myHandle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
    00490     ShowWindow(myHandle, SW_SHOW);
    00491
    00492     // Set "this" as the current fullscreen window
    00493     ourFullscreenWindow = this;
    00494 }
    00495
    00496
    00500 void WindowImplWin32::CreateContext(const VideoMode& Mode, WindowSettings& Params)
    00501 {
    00502     // Get the device context attached to the window
    00503     myDeviceContext = GetDC(myHandle);
    00504     if (myDeviceContext == NULL)
    00505     {
    00506         std::cerr << "Failed to get device context of window -- cannot create OpenGL context" << std::endl;
    00507         return;
    00508     }
    00509
    00510     // Let's find a suitable pixel format -- first try with antialiasing
    00511     int BestFormat = 0;
    00512     if (Params.AntialiasingLevel > 0)
    00513     {
    00514         // Get the wglChoosePixelFormatARB function (it is an extension)
    00515         PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
    00516         if (wglChoosePixelFormatARB)
    00517         {
    00518             // Define the basic attributes we want for our window
    00519             int IntAttributes[] =
    00520             {
    00521                 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
    00522                 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
    00523                 WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
    00524                 WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
    00525                 WGL_SAMPLE_BUFFERS_ARB, (Params.AntialiasingLevel ? GL_TRUE : GL_FALSE),
    00526                 WGL_SAMPLES_ARB,        Params.AntialiasingLevel,
    00527                 0,                      0
    00528             };
    00529
    00530             // Let's check how many formats are supporting our requirements
    00531             int   Formats[128];
    00532             UINT  NbFormats;
    00533             float FloatAttributes[] = {0, 0};
    00534             bool  IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
    00535             if (!IsValid || (NbFormats == 0))
    00536             {
    00537                 if (Params.AntialiasingLevel > 2)
    00538                 {
    00539                     // No format matching our needs : reduce the multisampling level
    00540                     std::cerr << "Failed to find a pixel format supporting "
    00541                               << Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
    00542
    00543                     Params.AntialiasingLevel = IntAttributes[11] = 2;
    00544                     IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
    00545                 }
    00546
    00547                 if (!IsValid || (NbFormats == 0))
    00548                 {
    00549                     // Cannot find any pixel format supporting multisampling ; disabling antialiasing
    00550                     std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
    00551                     Params.AntialiasingLevel = 0;
    00552                 }
    00553             }
    00554
    00555             // Get the best format among the returned ones
    00556             if (IsValid && (NbFormats > 0))
    00557             {
    00558                 int BestScore = 0xFFFF;
    00559                 for (UINT i = 0; i < NbFormats; ++i)
    00560                 {
    00561                     // Get the current format's attributes
    00562                     PIXELFORMATDESCRIPTOR Attribs;
    00563                     Attribs.nSize    = sizeof(PIXELFORMATDESCRIPTOR);
    00564                     Attribs.nVersion = 1;
    00565                     DescribePixelFormat(myDeviceContext, Formats[i], sizeof(PIXELFORMATDESCRIPTOR), &Attribs);
    00566
    00567                     // Evaluate the current configuration
    00568                     int Color = Attribs.cRedBits + Attribs.cGreenBits + Attribs.cBlueBits + Attribs.cAlphaBits;
    00569                     int Score = EvaluateConfig(Mode, Params, Color, Attribs.cDepthBits, Attribs.cStencilBits, Params.AntialiasingLevel);
    00570
    00571                     // Keep it if it's better than the current best
    00572                     if (Score < BestScore)
    00573                     {
    00574                         BestScore  = Score;
    00575                         BestFormat = Formats[i];
    00576                     }
    00577                 }
    00578             }
    00579         }
    00580         else
    00581         {
    00582             // wglChoosePixelFormatARB not supported ; disabling antialiasing
    00583             std::cerr << "Antialiasing is not supported ; it will be disabled" << std::endl;
    00584             Params.AntialiasingLevel = 0;
    00585         }
    00586     }
    00587
    00588     // Find a pixel format with no antialiasing, if not needed or not supported
    00589     if (BestFormat == 0)
    00590     {
    00591         // Setup a pixel format descriptor from the rendering settings
    00592         PIXELFORMATDESCRIPTOR PixelDescriptor;
    00593         ZeroMemory(&PixelDescriptor, sizeof(PIXELFORMATDESCRIPTOR));
    00594         PixelDescriptor.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
    00595         PixelDescriptor.nVersion     = 1;
    00596         PixelDescriptor.iLayerType   = PFD_MAIN_PLANE;
    00597         PixelDescriptor.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    00598         PixelDescriptor.iPixelType   = PFD_TYPE_RGBA;
    00599         PixelDescriptor.cColorBits   = static_cast<BYTE>(Mode.BitsPerPixel);
    00600         PixelDescriptor.cDepthBits   = static_cast<BYTE>(Params.DepthBits);
    00601         PixelDescriptor.cStencilBits = static_cast<BYTE>(Params.StencilBits);
    00602         PixelDescriptor.cAlphaBits   = Mode.BitsPerPixel == 32 ? 8 : 0;
    00603
    00604         // Get the pixel format that best matches our requirements
    00605         BestFormat = ChoosePixelFormat(myDeviceContext, &PixelDescriptor);
    00606         if (BestFormat == 0)
    00607         {
    00608             std::cerr << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl;
    00609             return;
    00610         }
    00611     }
    00612
    00613     // Extract the depth and stencil bits from the chosen format
    00614     PIXELFORMATDESCRIPTOR ActualFormat;
    00615     ActualFormat.nSize    = sizeof(PIXELFORMATDESCRIPTOR);
    00616     ActualFormat.nVersion = 1;
    00617     DescribePixelFormat(myDeviceContext, BestFormat, sizeof(PIXELFORMATDESCRIPTOR), &ActualFormat);
    00618     Params.DepthBits   = ActualFormat.cDepthBits;
    00619     Params.StencilBits = ActualFormat.cStencilBits;
    00620
    00621     // Set the chosen pixel format
    00622     if (!SetPixelFormat(myDeviceContext, BestFormat, &ActualFormat))
    00623     {
    00624         std::cerr << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl;
    00625         return;
    00626     }
    00627
    00628     // Create the OpenGL context from the device context
    00629     myGLContext = wglCreateContext(myDeviceContext);
    00630     if (myGLContext == NULL)
    00631     {
    00632         std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
    00633         return;
    00634     }
    00635
    00636     // Share display lists with other contexts
    00637     HGLRC CurrentContext = wglGetCurrentContext();
    00638     if (CurrentContext)
    00639         wglShareLists(CurrentContext, myGLContext);
    00640
    00641     // Activate the context
    00642     SetActive(true);
    00643
    00644     // Enable multisampling
    00645     if (Params.AntialiasingLevel > 0)
    00646         glEnable(GL_MULTISAMPLE_ARB);
    00647 }
    00648
    00649
    00653 void WindowImplWin32::Cleanup()
    00654 {
    00655     // Restore the previous video mode (in case we were running in fullscreen)
    00656     if (ourFullscreenWindow == this)
    00657     {
    00658         ChangeDisplaySettings(NULL, 0);
    00659         ourFullscreenWindow = NULL;
    00660     }
    00661
    00662     // Unhide the mouse cursor (in case it was hidden)
    00663     ShowMouseCursor(true);
    00664
    00665     // Destroy the OpenGL context
    00666     if (myGLContext)
    00667     {
    00668         // Unbind the context before destroying it
    00669         SetActive(false);
    00670
    00671         wglDeleteContext(myGLContext);
    00672         myGLContext = NULL;
    00673     }
    00674     if (myDeviceContext)
    00675     {
    00676         ReleaseDC(myHandle, myDeviceContext);
    00677         myDeviceContext = NULL;
    00678     }
    00679 }
    00680
    00681
    00685 void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
    00686 {
    00687     // Don't process any message until window is created
    00688     if (myHandle == NULL)
    00689         return;
    00690
    00691     switch (Message)
    00692     {
    00693         // Destroy event
    00694         case WM_DESTROY :
    00695         {
    00696             // Here we must cleanup resources !
    00697             Cleanup();
    00698             break;
    00699         }
    00700
    00701         // Set cursor event
    00702         case WM_SETCURSOR :
    00703         {
    00704             // The mouse has moved, if the cursor is in our window we must refresh the cursor
    00705             if (LOWORD(LParam) == HTCLIENT)
    00706                 SetCursor(myCursor);
    00707
    00708             break;
    00709         }
    00710
    00711         // Close event
    00712         case WM_CLOSE :
    00713         {
    00714             Event Evt;
    00715             Evt.Type = Event::Closed;
    00716             SendEvent(Evt);
    00717             break;
    00718         }
    00719
    00720         // Resize event
    00721         case WM_SIZE :
    00722         {
    00723             // Update window size
    00724             RECT Rect;
    00725             GetClientRect(myHandle, &Rect);
    00726             myWidth  = Rect.right - Rect.left;
    00727             myHeight = Rect.bottom - Rect.top;
    00728
    00729             Event Evt;
    00730             Evt.Type        = Event::Resized;
    00731             Evt.Size.Width  = myWidth;
    00732             Evt.Size.Height = myHeight;
    00733             SendEvent(Evt);
    00734             break;
    00735         }
    00736
    00737         // Gain focus event
    00738         case WM_SETFOCUS :
    00739         {
    00740             Event Evt;
    00741             Evt.Type = Event::GainedFocus;
    00742             SendEvent(Evt);
    00743             break;
    00744         }
    00745
    00746         // Lost focus event
    00747         case WM_KILLFOCUS :
    00748         {
    00749             Event Evt;
    00750             Evt.Type = Event::LostFocus;
    00751             SendEvent(Evt);
    00752             break;
    00753         }
    00754
    00755         // Text event
    00756         case WM_CHAR :
    00757         {
    00758             if (myKeyRepeatEnabled || ((LParam & (1 << 30)) == 0))
    00759             {
    00760                 Event Evt;
    00761                 Evt.Type = Event::TextEntered;
    00762                 Evt.Text.Unicode = static_cast<Uint32>(WParam);
    00763                 SendEvent(Evt);
    00764             }
    00765             break;
    00766         }
    00767
    00768         // Keydown event
    00769         case WM_KEYDOWN :
    00770         case WM_SYSKEYDOWN :
    00771         {
    00772             if (myKeyRepeatEnabled || ((HIWORD(LParam) & KF_REPEAT) == 0))
    00773             {
    00774                 Event Evt;
    00775                 Evt.Type        = Event::KeyPressed;
    00776                 Evt.Key.Alt     = HIWORD(GetAsyncKeyState(VK_MENU))    != 0;
    00777                 Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
    00778                 Evt.Key.Shift   = HIWORD(GetAsyncKeyState(VK_SHIFT))   != 0;
    00779                 Evt.Key.Code    = VirtualKeyCodeToSF(WParam, LParam);
    00780                 SendEvent(Evt);
    00781             }
    00782             break;
    00783         }
    00784
    00785         // Keyup event
    00786         case WM_KEYUP :
    00787         case WM_SYSKEYUP :
    00788         {
    00789             Event Evt;
    00790             Evt.Type        = Event::KeyReleased;
    00791             Evt.Key.Alt     = HIWORD(GetAsyncKeyState(VK_MENU))    != 0;
    00792             Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
    00793             Evt.Key.Shift   = HIWORD(GetAsyncKeyState(VK_SHIFT))   != 0;
    00794             Evt.Key.Code    = VirtualKeyCodeToSF(WParam, LParam);
    00795             SendEvent(Evt);
    00796
    00797             break;
    00798         }
    00799
    00800         // Mouse wheel event
    00801         case WM_MOUSEWHEEL :
    00802         {
    00803             Event Evt;
    00804             Evt.Type = Event::MouseWheelMoved;
    00805             Evt.MouseWheel.Delta = static_cast<Int16>(HIWORD(WParam)) / 120;
    00806             SendEvent(Evt);
    00807             break;
    00808         }
    00809
    00810         // Mouse left button down event
    00811         case WM_LBUTTONDOWN :
    00812         {
    00813             Event Evt;
    00814             Evt.Type               = Event::MouseButtonPressed;
    00815             Evt.MouseButton.Button = Mouse::Left;
    00816             Evt.MouseButton.X      = LOWORD(LParam);
    00817             Evt.MouseButton.Y      = HIWORD(LParam);
    00818             SendEvent(Evt);
    00819             break;
    00820         }
    00821
    00822         // Mouse left button up event
    00823         case WM_LBUTTONUP :
    00824         {
    00825             Event Evt;
    00826             Evt.Type               = Event::MouseButtonReleased;
    00827             Evt.MouseButton.Button = Mouse::Left;
    00828             Evt.MouseButton.X      = LOWORD(LParam);
    00829             Evt.MouseButton.Y      = HIWORD(LParam);
    00830             SendEvent(Evt);
    00831             break;
    00832         }
    00833
    00834         // Mouse right button down event
    00835         case WM_RBUTTONDOWN :
    00836         {
    00837             Event Evt;
    00838             Evt.Type               = Event::MouseButtonPressed;
    00839             Evt.MouseButton.Button = Mouse::Right;
    00840             Evt.MouseButton.X      = LOWORD(LParam);
    00841             Evt.MouseButton.Y      = HIWORD(LParam);
    00842             SendEvent(Evt);
    00843             break;
    00844         }
    00845
    00846         // Mouse right button up event
    00847         case WM_RBUTTONUP :
    00848         {
    00849             Event Evt;
    00850             Evt.Type               = Event::MouseButtonReleased;
    00851             Evt.MouseButton.Button = Mouse::Right;
    00852             Evt.MouseButton.X      = LOWORD(LParam);
    00853             Evt.MouseButton.Y      = HIWORD(LParam);
    00854             SendEvent(Evt);
    00855             break;
    00856         }
    00857
    00858         // Mouse wheel button down event
    00859         case WM_MBUTTONDOWN :
    00860         {
    00861             Event Evt;
    00862             Evt.Type               = Event::MouseButtonPressed;
    00863             Evt.MouseButton.Button = Mouse::Middle;
    00864             Evt.MouseButton.X      = LOWORD(LParam);
    00865             Evt.MouseButton.Y      = HIWORD(LParam);
    00866             SendEvent(Evt);
    00867             break;
    00868         }
    00869
    00870         // Mouse wheel button up event
    00871         case WM_MBUTTONUP :
    00872         {
    00873             Event Evt;
    00874             Evt.Type               = Event::MouseButtonReleased;
    00875             Evt.MouseButton.Button = Mouse::Middle;
    00876             Evt.MouseButton.X      = LOWORD(LParam);
    00877             Evt.MouseButton.Y      = HIWORD(LParam);
    00878             SendEvent(Evt);
    00879             break;
    00880         }
    00881
    00882         // Mouse X button down event
    00883         case WM_XBUTTONDOWN :
    00884         {
    00885             Event Evt;
    00886             Evt.Type               = Event::MouseButtonPressed;
    00887             Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
    00888             Evt.MouseButton.X      = LOWORD(LParam);
    00889             Evt.MouseButton.Y      = HIWORD(LParam);
    00890             SendEvent(Evt);
    00891             break;
    00892         }
    00893
    00894         // Mouse X button up event
    00895         case WM_XBUTTONUP :
    00896         {
    00897             Event Evt;
    00898             Evt.Type               = Event::MouseButtonReleased;
    00899             Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
    00900             Evt.MouseButton.X      = LOWORD(LParam);
    00901             Evt.MouseButton.Y      = HIWORD(LParam);
    00902             SendEvent(Evt);
    00903             break;
    00904         }
    00905
    00906         // Mouse move event
    00907         case WM_MOUSEMOVE :
    00908         {
    00909             // Check if we need to generate a MouseEntered event
    00910             if (!myIsCursorIn)
    00911             {
    00912                 TRACKMOUSEEVENT MouseEvent;
    00913                 MouseEvent.cbSize    = sizeof(TRACKMOUSEEVENT);
    00914                 MouseEvent.hwndTrack = myHandle;
    00915                 MouseEvent.dwFlags   = TME_LEAVE;
    00916                 TrackMouseEvent(&MouseEvent);
    00917
    00918                 myIsCursorIn = true;
    00919
    00920                 Event Evt;
    00921                 Evt.Type = Event::MouseEntered;
    00922                 SendEvent(Evt);
    00923             }
    00924
    00925             Event Evt;
    00926             Evt.Type        = Event::MouseMoved;
    00927             Evt.MouseMove.X = LOWORD(LParam);
    00928             Evt.MouseMove.Y = HIWORD(LParam);
    00929             SendEvent(Evt);
    00930             break;
    00931         }
    00932
    00933         // Mouse leave event
    00934         case WM_MOUSELEAVE :
    00935         {
    00936             myIsCursorIn = false;
    00937
    00938             Event Evt;
    00939             Evt.Type = Event::MouseLeft;
    00940             SendEvent(Evt);
    00941             break;
    00942         }
    00943     }
    00944 }
    00945
    00946
    00950 Key::Code WindowImplWin32::VirtualKeyCodeToSF(WPARAM VirtualKey, LPARAM Flags)
    00951 {
    00952     switch (VirtualKey)
    00953     {
    00954         // Check the scancode to distinguish between left and right shift
    00955         case VK_SHIFT :
    00956         {
    00957             static UINT LShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
    00958             UINT scancode = (Flags & (0xFF << 16)) >> 16;
    00959             return scancode == LShift ? Key::LShift : Key::RShift;
    00960         }
    00961
    00962         // Check the "extended" flag to distinguish between left and right alt
    00963         case VK_MENU : return (HIWORD(Flags) & KF_EXTENDED) ? Key::RAlt : Key::LAlt;
    00964
    00965         // Check the "extended" flag to distinguish between left and right control
    00966         case VK_CONTROL : return (HIWORD(Flags) & KF_EXTENDED) ? Key::RControl : Key::LControl;
    00967
    00968         // Other keys are reported properly
    00969         case VK_LWIN :       return Key::LSystem;
    00970         case VK_RWIN :       return Key::RSystem;
    00971         case VK_APPS :       return Key::Menu;
    00972         case VK_OEM_1 :      return Key::SemiColon;
    00973         case VK_OEM_2 :      return Key::Slash;
    00974         case VK_OEM_PLUS :   return Key::Equal;
    00975         case VK_OEM_MINUS :  return Key::Dash;
    00976         case VK_OEM_4 :      return Key::LBracket;
    00977         case VK_OEM_6 :      return Key::RBracket;
    00978         case VK_OEM_COMMA :  return Key::Comma;
    00979         case VK_OEM_PERIOD : return Key::Period;
    00980         case VK_OEM_7 :      return Key::Quote;
    00981         case VK_OEM_5 :      return Key::BackSlash;
    00982         case VK_OEM_3 :      return Key::Tilde;
    00983         case VK_ESCAPE :     return Key::Escape;
    00984         case VK_SPACE :      return Key::Space;
    00985         case VK_RETURN :     return Key::Return;
    00986         case VK_BACK :       return Key::Back;
    00987         case VK_TAB :        return Key::Tab;
    00988         case VK_PRIOR :      return Key::PageUp;
    00989         case VK_NEXT :       return Key::PageDown;
    00990         case VK_END :        return Key::End;
    00991         case VK_HOME :       return Key::Home;
    00992         case VK_INSERT :     return Key::Insert;
    00993         case VK_DELETE :     return Key::Delete;
    00994         case VK_ADD :        return Key::Add;
    00995         case VK_SUBTRACT :   return Key::Subtract;
    00996         case VK_MULTIPLY :   return Key::Multiply;
    00997         case VK_DIVIDE :     return Key::Divide;
    00998         case VK_PAUSE :      return Key::Pause;
    00999         case VK_F1 :         return Key::F1;
    01000         case VK_F2 :         return Key::F2;
    01001         case VK_F3 :         return Key::F3;
    01002         case VK_F4 :         return Key::F4;
    01003         case VK_F5 :         return Key::F5;
    01004         case VK_F6 :         return Key::F6;
    01005         case VK_F7 :         return Key::F7;
    01006         case VK_F8 :         return Key::F8;
    01007         case VK_F9 :         return Key::F9;
    01008         case VK_F10 :        return Key::F10;
    01009         case VK_F11 :        return Key::F11;
    01010         case VK_F12 :        return Key::F12;
    01011         case VK_F13 :        return Key::F13;
    01012         case VK_F14 :        return Key::F14;
    01013         case VK_F15 :        return Key::F15;
    01014         case VK_LEFT :       return Key::Left;
    01015         case VK_RIGHT :      return Key::Right;
    01016         case VK_UP :         return Key::Up;
    01017         case VK_DOWN :       return Key::Down;
    01018         case VK_NUMPAD0 :    return Key::Numpad0;
    01019         case VK_NUMPAD1 :    return Key::Numpad1;
    01020         case VK_NUMPAD2 :    return Key::Numpad2;
    01021         case VK_NUMPAD3 :    return Key::Numpad3;
    01022         case VK_NUMPAD4 :    return Key::Numpad4;
    01023         case VK_NUMPAD5 :    return Key::Numpad5;
    01024         case VK_NUMPAD6 :    return Key::Numpad6;
    01025         case VK_NUMPAD7 :    return Key::Numpad7;
    01026         case VK_NUMPAD8 :    return Key::Numpad8;
    01027         case VK_NUMPAD9 :    return Key::Numpad9;
    01028         case 'A' :           return Key::A;
    01029         case 'Z' :           return Key::Z;
    01030         case 'E' :           return Key::E;
    01031         case 'R' :           return Key::R;
    01032         case 'T' :           return Key::T;
    01033         case 'Y' :           return Key::Y;
    01034         case 'U' :           return Key::U;
    01035         case 'I' :           return Key::I;
    01036         case 'O' :           return Key::O;
    01037         case 'P' :           return Key::P;
    01038         case 'Q' :           return Key::Q;
    01039         case 'S' :           return Key::S;
    01040         case 'D' :           return Key::D;
    01041         case 'F' :           return Key::F;
    01042         case 'G' :           return Key::G;
    01043         case 'H' :           return Key::H;
    01044         case 'J' :           return Key::J;
    01045         case 'K' :           return Key::K;
    01046         case 'L' :           return Key::L;
    01047         case 'M' :           return Key::M;
    01048         case 'W' :           return Key::W;
    01049         case 'X' :           return Key::X;
    01050         case 'C' :           return Key::C;
    01051         case 'V' :           return Key::V;
    01052         case 'B' :           return Key::B;
    01053         case 'N' :           return Key::N;
    01054         case '0' :           return Key::Num0;
    01055         case '1' :           return Key::Num1;
    01056         case '2' :           return Key::Num2;
    01057         case '3' :           return Key::Num3;
    01058         case '4' :           return Key::Num4;
    01059         case '5' :           return Key::Num5;
    01060         case '6' :           return Key::Num6;
    01061         case '7' :           return Key::Num7;
    01062         case '8' :           return Key::Num8;
    01063         case '9' :           return Key::Num9;
    01064     }
    01065
    01066     return Key::Code(0);
    01067 }
    01068
    01069
    01075 bool WindowImplWin32::HasUnicodeSupport()
    01076 {
    01077     OSVERSIONINFO VersionInfo;
    01078     ZeroMemory(&VersionInfo, sizeof(VersionInfo));
    01079     VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
    01080
    01081     if (GetVersionEx(&VersionInfo))
    01082     {
    01083         return VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
    01084     }
    01085     else
    01086     {
    01087         return false;
    01088     }
    01089 }
    01090
    01091
    01095 LRESULT CALLBACK WindowImplWin32::GlobalOnEvent(HWND Handle, UINT Message, WPARAM WParam, LPARAM LParam)
    01096 {
    01097     // Associate handle and Window instance when the creation message is received
    01098     if (Message == WM_CREATE)
    01099     {
    01100         // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow)
    01101         long This = reinterpret_cast<long>(reinterpret_cast<CREATESTRUCT*>(LParam)->lpCreateParams);
    01102
    01103         // Set as the "user data" parameter of the window
    01104         SetWindowLongPtr(Handle, GWLP_USERDATA, This);
    01105     }
    01106
    01107     // Get the WindowImpl instance corresponding to the window handle
    01108     WindowImplWin32* Window = reinterpret_cast<WindowImplWin32*>(GetWindowLongPtr(Handle, GWLP_USERDATA));
    01109
    01110     // Forward the event to the appropriate function
    01111     if (Window)
    01112     {
    01113         Window->ProcessEvent(Message, WParam, LParam);
    01114
    01115         if (Window->myCallback)
    01116             return CallWindowProc(reinterpret_cast<WNDPROC>(Window->myCallback), Handle, Message, WParam, LParam);
    01117     }
    01118
    01119     // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window
    01120     if (Message == WM_CLOSE)
    01121         return 0;
    01122
    01123     static const bool HasUnicode = HasUnicodeSupport();
    01124     return HasUnicode ? DefWindowProcW(Handle, Message, WParam, LParam) :
    01125                         DefWindowProcA(Handle, Message, WParam, LParam);
    01126 }
    01127
    01128 } // namespace priv
    01129
    01130 } // namespace sf

:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::