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

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