src/video/windows/SDL_windowswindow.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Oct 2012 18:59:56 -0700
changeset 6620 62fe18dc6841
parent 6535 b117349cc8aa
child 6662 698c2e533a7e
permissions -rw-r--r--
Added Windows message box implementation, but it needs a little work on layout.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINDOWS
    24 
    25 #include "../SDL_sysvideo.h"
    26 #include "../SDL_pixels_c.h"
    27 #include "../../events/SDL_keyboard_c.h"
    28 
    29 #include "SDL_windowsvideo.h"
    30 #include "SDL_windowswindow.h"
    31 
    32 /* Dropfile support */
    33 #include <shellapi.h>
    34 
    35 /* This is included after SDL_windowsvideo.h, which includes windows.h */
    36 #include "SDL_syswm.h"
    37 
    38 /* Windows CE compatibility */
    39 #ifndef SWP_NOCOPYBITS
    40 #define SWP_NOCOPYBITS 0
    41 #endif
    42 
    43 /* Fake window to help with DirectInput events. */
    44 HWND SDL_HelperWindow = NULL;
    45 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
    46 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
    47 static ATOM SDL_HelperWindowClass = 0;
    48 
    49 #define STYLE_BASIC         (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
    50 #define STYLE_FULLSCREEN    (WS_POPUP)
    51 #define STYLE_BORDERLESS    (WS_POPUP)
    52 #define STYLE_NORMAL        (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
    53 #define STYLE_RESIZABLE     (WS_THICKFRAME | WS_MAXIMIZEBOX)
    54 #define STYLE_MASK          (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
    55 
    56 static DWORD
    57 GetWindowStyle(SDL_Window * window)
    58 {
    59     DWORD style = 0;
    60 
    61     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    62         style |= STYLE_FULLSCREEN;
    63     } else {
    64         if (window->flags & SDL_WINDOW_BORDERLESS) {
    65             style |= STYLE_BORDERLESS;
    66         } else {
    67             style |= STYLE_NORMAL;
    68         }
    69         if (window->flags & SDL_WINDOW_RESIZABLE) {
    70             style |= STYLE_RESIZABLE;
    71         }
    72     }
    73     return style;
    74 }
    75 
    76 static int
    77 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
    78 {
    79     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    80     SDL_WindowData *data;
    81 
    82     /* Allocate the window data */
    83     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
    84     if (!data) {
    85         SDL_OutOfMemory();
    86         return -1;
    87     }
    88     data->window = window;
    89     data->hwnd = hwnd;
    90     data->hdc = GetDC(hwnd);
    91     data->created = created;
    92     data->mouse_pressed = SDL_FALSE;
    93     data->videodata = videodata;
    94 
    95     window->driverdata = data;
    96 
    97     /* Associate the data with the window */
    98     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
    99         ReleaseDC(hwnd, data->hdc);
   100         SDL_free(data);
   101         WIN_SetError("SetProp() failed");
   102         return -1;
   103     }
   104 
   105     /* Set up the window proc function */
   106 #ifdef GWLP_WNDPROC
   107     data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
   108     if (data->wndproc == WIN_WindowProc) {
   109         data->wndproc = NULL;
   110     } else {
   111         SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
   112     }
   113 #else
   114     data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
   115     if (data->wndproc == WIN_WindowProc) {
   116         data->wndproc = NULL;
   117     } else {
   118         SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
   119     }
   120 #endif
   121 
   122     /* Fill in the SDL window with the window data */
   123     {
   124         POINT point;
   125         point.x = 0;
   126         point.y = 0;
   127         if (ClientToScreen(hwnd, &point)) {
   128             window->x = point.x;
   129             window->y = point.y;
   130         }
   131     }
   132     {
   133         RECT rect;
   134         if (GetClientRect(hwnd, &rect)) {
   135             window->w = rect.right;
   136             window->h = rect.bottom;
   137         }
   138     }
   139     {
   140         DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   141         if (style & WS_VISIBLE) {
   142             window->flags |= SDL_WINDOW_SHOWN;
   143         } else {
   144             window->flags &= ~SDL_WINDOW_SHOWN;
   145         }
   146         if (style & (WS_BORDER | WS_THICKFRAME)) {
   147             window->flags &= ~SDL_WINDOW_BORDERLESS;
   148         } else {
   149             window->flags |= SDL_WINDOW_BORDERLESS;
   150         }
   151         if (style & WS_THICKFRAME) {
   152             window->flags |= SDL_WINDOW_RESIZABLE;
   153         } else {
   154             window->flags &= ~SDL_WINDOW_RESIZABLE;
   155         }
   156 #ifdef WS_MAXIMIZE
   157         if (style & WS_MAXIMIZE) {
   158             window->flags |= SDL_WINDOW_MAXIMIZED;
   159         } else
   160 #endif
   161         {
   162             window->flags &= ~SDL_WINDOW_MAXIMIZED;
   163         }
   164 #ifdef WS_MINIMIZE
   165         if (style & WS_MINIMIZE) {
   166             window->flags |= SDL_WINDOW_MINIMIZED;
   167         } else
   168 #endif
   169         {
   170             window->flags &= ~SDL_WINDOW_MINIMIZED;
   171         }
   172     }
   173     if (GetFocus() == hwnd) {
   174         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   175         SDL_SetKeyboardFocus(data->window);
   176 
   177         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   178             RECT rect;
   179             GetClientRect(hwnd, &rect);
   180             ClientToScreen(hwnd, (LPPOINT) & rect);
   181             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   182             ClipCursor(&rect);
   183         }
   184     }
   185 
   186     /* Enable multi-touch */
   187     if (videodata->RegisterTouchWindow) {
   188         videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
   189     }
   190 
   191     /* Enable dropping files */
   192     DragAcceptFiles(hwnd, TRUE);
   193 
   194     /* All done! */
   195     return 0;
   196 }
   197 
   198 int
   199 WIN_CreateWindow(_THIS, SDL_Window * window)
   200 {
   201     HWND hwnd;
   202     RECT rect;
   203     DWORD style = STYLE_BASIC;
   204     int x, y;
   205     int w, h;
   206     
   207     style |= GetWindowStyle(window);
   208 
   209     /* Figure out what the window area will be */
   210     rect.left = window->x;
   211     rect.top = window->y;
   212     rect.right = window->x + window->w;
   213     rect.bottom = window->y + window->h;
   214     AdjustWindowRectEx(&rect, style, FALSE, 0);
   215     x = rect.left;
   216     y = rect.top;
   217     w = (rect.right - rect.left);
   218     h = (rect.bottom - rect.top);
   219 
   220     hwnd =
   221         CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
   222                      SDL_Instance, NULL);
   223     if (!hwnd) {
   224         WIN_SetError("Couldn't create window");
   225         return -1;
   226     }
   227 
   228     WIN_PumpEvents(_this);
   229 
   230     if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
   231         DestroyWindow(hwnd);
   232         return -1;
   233     }
   234 #if SDL_VIDEO_OPENGL_WGL
   235     if (window->flags & SDL_WINDOW_OPENGL) {
   236         if (WIN_GL_SetupWindow(_this, window) < 0) {
   237             WIN_DestroyWindow(_this, window);
   238             return -1;
   239         }
   240     }
   241 #endif
   242     return 0;
   243 }
   244 
   245 int
   246 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   247 {
   248     HWND hwnd = (HWND) data;
   249     LPTSTR title;
   250     int titleLen;
   251 
   252     /* Query the title from the existing window */
   253     titleLen = GetWindowTextLength(hwnd);
   254     title = SDL_stack_alloc(TCHAR, titleLen + 1);
   255     if (title) {
   256         titleLen = GetWindowText(hwnd, title, titleLen);
   257     } else {
   258         titleLen = 0;
   259     }
   260     if (titleLen > 0) {
   261         window->title = WIN_StringToUTF8(title);
   262     }
   263     if (title) {
   264         SDL_stack_free(title);
   265     }
   266 
   267     if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
   268         return -1;
   269     }
   270     return 0;
   271 }
   272 
   273 void
   274 WIN_SetWindowTitle(_THIS, SDL_Window * window)
   275 {
   276     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   277     LPTSTR title;
   278 
   279     if (window->title) {
   280         title = WIN_UTF8ToString(window->title);
   281     } else {
   282         title = NULL;
   283     }
   284     SetWindowText(hwnd, title ? title : TEXT(""));
   285     if (title) {
   286         SDL_free(title);
   287     }
   288 }
   289 
   290 void
   291 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   292 {
   293     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   294     HICON hicon = NULL;
   295     BYTE *icon_bmp;
   296     int icon_len;
   297     SDL_RWops *dst;
   298     SDL_Surface *surface;
   299 
   300     /* Create temporary bitmap buffer */
   301     icon_len = 40 + icon->h * icon->w * 4;
   302     icon_bmp = SDL_stack_alloc(BYTE, icon_len);
   303     dst = SDL_RWFromMem(icon_bmp, icon_len);
   304     if (!dst) {
   305         SDL_stack_free(icon_bmp);
   306         return;
   307     }
   308 
   309     /* Write the BITMAPINFO header */
   310     SDL_WriteLE32(dst, 40);
   311     SDL_WriteLE32(dst, icon->w);
   312     SDL_WriteLE32(dst, icon->h * 2);
   313     SDL_WriteLE16(dst, 1);
   314     SDL_WriteLE16(dst, 32);
   315     SDL_WriteLE32(dst, BI_RGB);
   316     SDL_WriteLE32(dst, icon->h * icon->w * 4);
   317     SDL_WriteLE32(dst, 0);
   318     SDL_WriteLE32(dst, 0);
   319     SDL_WriteLE32(dst, 0);
   320     SDL_WriteLE32(dst, 0);
   321 
   322     /* Convert the icon to a 32-bit surface with alpha channel */
   323     surface = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
   324     if (surface) {
   325         /* Write the pixels upside down into the bitmap buffer */
   326         int y = surface->h;
   327         while (y--) {
   328             Uint8 *src = (Uint8 *) surface->pixels + y * surface->pitch;
   329             SDL_RWwrite(dst, src, surface->pitch, 1);
   330         }
   331         SDL_FreeSurface(surface);
   332 
   333         hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
   334     }
   335     SDL_RWclose(dst);
   336     SDL_stack_free(icon_bmp);
   337 
   338     /* Set the icon for the window */
   339     SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
   340 
   341     /* Set the icon in the task manager (should we do this?) */
   342     SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
   343 }
   344 
   345 static void
   346 WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
   347 {
   348     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   349     RECT rect;
   350     DWORD style;
   351     HWND top;
   352     BOOL menu;
   353     int x, y;
   354     int w, h;
   355 
   356     /* Figure out what the window area will be */
   357     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   358         top = HWND_TOPMOST;
   359     } else {
   360         top = HWND_NOTOPMOST;
   361     }
   362     style = GetWindowLong(hwnd, GWL_STYLE);
   363     rect.left = 0;
   364     rect.top = 0;
   365     rect.right = window->w;
   366     rect.bottom = window->h;
   367     menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   368     AdjustWindowRectEx(&rect, style, menu, 0);
   369     w = (rect.right - rect.left);
   370     h = (rect.bottom - rect.top);
   371     x = window->x + rect.left;
   372     y = window->y + rect.top;
   373 
   374     SetWindowPos(hwnd, top, x, y, w, h, flags);
   375 }
   376 
   377 void
   378 WIN_SetWindowPosition(_THIS, SDL_Window * window)
   379 {
   380     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
   381 }
   382 
   383 void
   384 WIN_SetWindowSize(_THIS, SDL_Window * window)
   385 {
   386     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
   387 }
   388 
   389 void
   390 WIN_ShowWindow(_THIS, SDL_Window * window)
   391 {
   392     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   393     ShowWindow(hwnd, SW_SHOW);
   394 }
   395 
   396 void
   397 WIN_HideWindow(_THIS, SDL_Window * window)
   398 {
   399     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   400     ShowWindow(hwnd, SW_HIDE);
   401 }
   402 
   403 void
   404 WIN_RaiseWindow(_THIS, SDL_Window * window)
   405 {
   406     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   407     HWND top;
   408 
   409     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   410         top = HWND_TOPMOST;
   411     } else {
   412         top = HWND_NOTOPMOST;
   413     }
   414     SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
   415 }
   416 
   417 void
   418 WIN_MaximizeWindow(_THIS, SDL_Window * window)
   419 {
   420     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   421     ShowWindow(hwnd, SW_MAXIMIZE);
   422 }
   423 
   424 void
   425 WIN_MinimizeWindow(_THIS, SDL_Window * window)
   426 {
   427     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   428     ShowWindow(hwnd, SW_MINIMIZE);
   429 }
   430 
   431 void
   432 WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
   433 {
   434     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   435     DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   436 
   437     if (bordered) {
   438         style &= ~STYLE_BORDERLESS;
   439         style |= STYLE_NORMAL;
   440     } else {
   441         style &= ~STYLE_NORMAL;
   442         style |= STYLE_BORDERLESS;
   443     }
   444 
   445     SetWindowLong(hwnd, GWL_STYLE, style);
   446     SetWindowPos(hwnd, hwnd, window->x, window->y, window->w, window->h, SWP_FRAMECHANGED | SWP_NOREPOSITION | SWP_NOZORDER |SWP_NOACTIVATE | SWP_NOSENDCHANGING);
   447 }
   448 
   449 void
   450 WIN_RestoreWindow(_THIS, SDL_Window * window)
   451 {
   452     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   453 
   454     ShowWindow(hwnd, SW_RESTORE);
   455 }
   456 
   457 void
   458 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
   459 {
   460     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   461     HWND hwnd = data->hwnd;
   462     RECT rect;
   463     SDL_Rect bounds;
   464     DWORD style;
   465     HWND top;
   466     BOOL menu;
   467     int x, y;
   468     int w, h;
   469 
   470     if (fullscreen) {
   471         top = HWND_TOPMOST;
   472     } else {
   473         top = HWND_NOTOPMOST;
   474     }
   475     style = GetWindowLong(hwnd, GWL_STYLE);
   476     style &= ~STYLE_MASK;
   477     style |= GetWindowStyle(window);
   478 
   479     WIN_GetDisplayBounds(_this, display, &bounds);
   480 
   481     if (fullscreen) {
   482         x = bounds.x;
   483         y = bounds.y;
   484         w = bounds.w;
   485         h = bounds.h;
   486     } else {
   487         rect.left = 0;
   488         rect.top = 0;
   489         rect.right = window->windowed.w;
   490         rect.bottom = window->windowed.h;
   491         menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   492         AdjustWindowRectEx(&rect, style, menu, 0);
   493         w = (rect.right - rect.left);
   494         h = (rect.bottom - rect.top);
   495         x = window->windowed.x + rect.left;
   496         y = window->windowed.y + rect.top;
   497     }
   498     SetWindowLong(hwnd, GWL_STYLE, style);
   499     SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS);
   500 }
   501 
   502 int
   503 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
   504 {
   505     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   506     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   507     HDC hdc;
   508     BOOL succeeded = FALSE;
   509 
   510     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   511     if (hdc) {
   512         succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
   513         if (!succeeded) {
   514             WIN_SetError("SetDeviceGammaRamp()");
   515         }
   516         DeleteDC(hdc);
   517     }
   518     return succeeded ? 0 : -1;
   519 }
   520 
   521 int
   522 WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
   523 {
   524     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   525     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   526     HDC hdc;
   527     BOOL succeeded = FALSE;
   528 
   529     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   530     if (hdc) {
   531         succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
   532         if (!succeeded) {
   533             WIN_SetError("GetDeviceGammaRamp()");
   534         }
   535         DeleteDC(hdc);
   536     }
   537     return succeeded ? 0 : -1;
   538 }
   539 
   540 void
   541 WIN_SetWindowGrab(_THIS, SDL_Window * window)
   542 {
   543     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   544 
   545     if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
   546         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   547         RECT rect;
   548         GetClientRect(hwnd, &rect);
   549         ClientToScreen(hwnd, (LPPOINT) & rect);
   550         ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   551         ClipCursor(&rect);
   552     } else {
   553         ClipCursor(NULL);
   554     }
   555 }
   556 
   557 void
   558 WIN_DestroyWindow(_THIS, SDL_Window * window)
   559 {
   560     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   561 
   562     if (data) {
   563         ReleaseDC(data->hwnd, data->hdc);
   564         if (data->created) {
   565             DestroyWindow(data->hwnd);
   566         } else {
   567             /* Restore any original event handler... */
   568             if (data->wndproc != NULL) {
   569 #ifdef GWLP_WNDPROC
   570                 SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
   571                                  (LONG_PTR) data->wndproc);
   572 #else
   573                 SetWindowLong(data->hwnd, GWL_WNDPROC,
   574                               (LONG_PTR) data->wndproc);
   575 #endif
   576             }
   577         }
   578         SDL_free(data);
   579     }
   580 }
   581 
   582 SDL_bool
   583 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   584 {
   585     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   586     if (info->version.major <= SDL_MAJOR_VERSION) {
   587         info->subsystem = SDL_SYSWM_WINDOWS;
   588         info->info.win.window = hwnd;
   589         return SDL_TRUE;
   590     } else {
   591         SDL_SetError("Application not compiled with SDL %d.%d\n",
   592                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   593         return SDL_FALSE;
   594     }
   595 }
   596 
   597 
   598 /*
   599  * Creates a HelperWindow used for DirectInput events.
   600  */
   601 int
   602 SDL_HelperWindowCreate(void)
   603 {
   604     HINSTANCE hInstance = GetModuleHandle(NULL);
   605     WNDCLASS wce;
   606 
   607     /* Make sure window isn't created twice. */
   608     if (SDL_HelperWindow != NULL) {
   609         return 0;
   610     }
   611 
   612     /* Create the class. */
   613     SDL_zero(wce);
   614     wce.lpfnWndProc = DefWindowProc;
   615     wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
   616     wce.hInstance = hInstance;
   617 
   618     /* Register the class. */
   619     SDL_HelperWindowClass = RegisterClass(&wce);
   620     if (SDL_HelperWindowClass == 0) {
   621         WIN_SetError("Unable to create Helper Window Class");
   622         return -1;
   623     }
   624 
   625     /* Create the window. */
   626     SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
   627                                       SDL_HelperWindowName,
   628                                       WS_OVERLAPPED, CW_USEDEFAULT,
   629                                       CW_USEDEFAULT, CW_USEDEFAULT,
   630                                       CW_USEDEFAULT, HWND_MESSAGE, NULL,
   631                                       hInstance, NULL);
   632     if (SDL_HelperWindow == NULL) {
   633         UnregisterClass(SDL_HelperWindowClassName, hInstance);
   634         WIN_SetError("Unable to create Helper Window");
   635         return -1;
   636     }
   637 
   638     return 0;
   639 }
   640 
   641 
   642 /*
   643  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
   644  */
   645 void
   646 SDL_HelperWindowDestroy(void)
   647 {
   648     HINSTANCE hInstance = GetModuleHandle(NULL);
   649 
   650     /* Destroy the window. */
   651     if (SDL_HelperWindow != NULL) {
   652         if (DestroyWindow(SDL_HelperWindow) == 0) {
   653             WIN_SetError("Unable to destroy Helper Window");
   654             return;
   655         }
   656         SDL_HelperWindow = NULL;
   657     }
   658 
   659     /* Unregister the class. */
   660     if (SDL_HelperWindowClass != 0) {
   661         if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
   662             WIN_SetError("Unable to destroy Helper Window Class");
   663             return;
   664         }
   665         SDL_HelperWindowClass = 0;
   666     }
   667 }
   668 
   669 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   670 
   671 /* vi: set ts=4 sw=4 expandtab: */