src/video/win32/SDL_win32window.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 May 2010 20:47:22 -0700
changeset 4465 3e69e077cb95
parent 3697 f7b03b6838cb
child 4486 237b1eb53e4d
child 4746 0c39b36dd104
permissions -rw-r--r--
Removed multi-mouse / multi-keyboard support in anticipation of a real multi-mouse and multi-touch API.

Plus, this lets me start implementing cursor support.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /* we need to define it, so that raw input is included */
    24 
    25 #if (_WIN32_WINNT < 0x0501)
    26 #undef _WIN32_WINNT
    27 #define _WIN32_WINNT 0x0501
    28 #endif
    29 
    30 #include "SDL_config.h"
    31 
    32 #include "../SDL_sysvideo.h"
    33 #include "../SDL_pixels_c.h"
    34 #include "../../events/SDL_keyboard_c.h"
    35 
    36 #include "SDL_win32video.h"
    37 
    38 /* This is included after SDL_win32video.h, which includes windows.h */
    39 #include "SDL_syswm.h"
    40 
    41 
    42 #define SHFS_SHOWTASKBAR            0x0001
    43 #define SHFS_HIDETASKBAR            0x0002
    44 #define SHFS_SHOWSIPBUTTON          0x0004
    45 #define SHFS_HIDESIPBUTTON          0x0008
    46 #define SHFS_SHOWSTARTICON          0x0010
    47 #define SHFS_HIDESTARTICON          0x0020
    48 
    49 #ifdef _WIN32_WCE
    50 // dynamically load aygshell dll because we want SDL to work on HPC and be300
    51 int aygshell_loaded = 0;
    52 BOOL(WINAPI * SHFullScreen) (HWND hwndRequester, DWORD dwState) = 0;
    53 
    54 
    55 static BOOL
    56 CE_SHFullScreen(HWND hwndRequester, DWORD dwState)
    57 {
    58     if (SHFullScreen == 0 && aygshell_loaded == 0) {
    59         aygshell_loaded = 0;
    60         void *lib = SDL_LoadObject("aygshell.dll");
    61         if (lib) {
    62             SHFullScreen =
    63                 (BOOL(WINAPI *) (HWND, DWORD)) SDL_LoadFunction(lib,
    64                                                                 "SHFullScreen");
    65         }
    66     }
    67 
    68     if (SHFullScreen) {
    69         SHFullScreen(hwndRequester, dwState);
    70         //printf("SHFullscreen(%i)\n",dwState);
    71     }
    72 }
    73 
    74 #endif
    75 
    76 /* Fake window to help with DirectInput events. */
    77 HWND SDL_HelperWindow = NULL;
    78 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
    79 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
    80 static ATOM SDL_HelperWindowClass = 0;
    81 
    82 static int
    83 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
    84 {
    85     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    86     SDL_VideoDisplay *display = window->display;
    87     SDL_WindowData *data;
    88 
    89     /* Allocate the window data */
    90     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
    91     if (!data) {
    92         SDL_OutOfMemory();
    93         return -1;
    94     }
    95     data->window = window;
    96     data->hwnd = hwnd;
    97     data->hdc = GetDC(hwnd);
    98     data->created = created;
    99     data->mouse_pressed = SDL_FALSE;
   100     data->videodata = videodata;
   101 
   102     /* Associate the data with the window */
   103     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
   104         ReleaseDC(hwnd, data->hdc);
   105         SDL_free(data);
   106         WIN_SetError("SetProp() failed");
   107         return -1;
   108     }
   109 
   110     /* Set up the window proc function */
   111     data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
   112     if (data->wndproc == DefWindowProc) {
   113         data->wndproc = NULL;
   114     }
   115     SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
   116 
   117     /* Fill in the SDL window with the window data */
   118     {
   119         POINT point;
   120         point.x = 0;
   121         point.y = 0;
   122         if (ClientToScreen(hwnd, &point)) {
   123             SDL_Rect bounds;
   124             WIN_GetDisplayBounds(_this, display, &bounds);
   125             window->x = point.x - bounds.x;
   126             window->y = point.y - bounds.y;
   127         }
   128     }
   129     {
   130         RECT rect;
   131         if (GetClientRect(hwnd, &rect)) {
   132             window->w = rect.right;
   133             window->h = rect.bottom;
   134         }
   135     }
   136     {
   137         DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   138         if (style & WS_VISIBLE) {
   139             window->flags |= SDL_WINDOW_SHOWN;
   140         } else {
   141             window->flags &= ~SDL_WINDOW_SHOWN;
   142         }
   143         if (style & (WS_BORDER | WS_THICKFRAME)) {
   144             window->flags &= ~SDL_WINDOW_BORDERLESS;
   145         } else {
   146             window->flags |= SDL_WINDOW_BORDERLESS;
   147         }
   148         if (style & WS_THICKFRAME) {
   149             window->flags |= SDL_WINDOW_RESIZABLE;
   150         } else {
   151             window->flags &= ~SDL_WINDOW_RESIZABLE;
   152         }
   153         if (style & WS_MAXIMIZE) {
   154             window->flags |= SDL_WINDOW_MAXIMIZED;
   155         } else {
   156             window->flags &= ~SDL_WINDOW_MAXIMIZED;
   157         }
   158         if (style & WS_MINIMIZE) {
   159             window->flags |= SDL_WINDOW_MINIMIZED;
   160         } else {
   161             window->flags &= ~SDL_WINDOW_MINIMIZED;
   162         }
   163     }
   164     if (GetFocus() == hwnd) {
   165         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   166         SDL_SetKeyboardFocus(data->window);
   167 
   168         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   169             RECT rect;
   170             GetClientRect(hwnd, &rect);
   171             ClientToScreen(hwnd, (LPPOINT) & rect);
   172             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   173             ClipCursor(&rect);
   174         }
   175     }
   176 
   177     /* All done! */
   178     window->driverdata = data;
   179     return 0;
   180 }
   181 
   182 int
   183 WIN_CreateWindow(_THIS, SDL_Window * window)
   184 {
   185     SDL_VideoDisplay *display = window->display;
   186     HWND hwnd;
   187     HWND top;
   188     RECT rect;
   189     SDL_Rect bounds;
   190     DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
   191     int x, y;
   192     int w, h;
   193 
   194     if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) {
   195         style |= WS_POPUP;
   196     } else {
   197         style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
   198     }
   199     if ((window->flags & SDL_WINDOW_RESIZABLE)
   200         && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
   201         style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
   202     }
   203 
   204     /* Figure out what the window area will be */
   205     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   206         top = HWND_TOPMOST;
   207     } else {
   208         top = HWND_NOTOPMOST;
   209     }
   210     rect.left = 0;
   211     rect.top = 0;
   212     rect.right = window->w;
   213     rect.bottom = window->h;
   214     AdjustWindowRectEx(&rect, style, FALSE, 0);
   215     w = (rect.right - rect.left);
   216     h = (rect.bottom - rect.top);
   217 
   218     WIN_GetDisplayBounds(_this, display, &bounds);
   219     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   220         || window->x == SDL_WINDOWPOS_CENTERED) {
   221         x = bounds.x + (bounds.w - window->w) / 2;
   222     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   223         if (bounds.x == 0) {
   224             x = CW_USEDEFAULT;
   225         } else {
   226             x = bounds.x;
   227         }
   228     } else {
   229         x = bounds.x + window->x + rect.left;
   230     }
   231     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   232         || window->y == SDL_WINDOWPOS_CENTERED) {
   233         y = bounds.y + (bounds.h - window->h) / 2;
   234     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   235         if (bounds.x == 0) {
   236             y = CW_USEDEFAULT;
   237         } else {
   238             y = bounds.y;
   239         }
   240     } else {
   241         y = bounds.y + window->y + rect.top;
   242     }
   243 
   244     hwnd =
   245         CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
   246                      SDL_Instance, NULL);
   247     if (!hwnd) {
   248         WIN_SetError("Couldn't create window");
   249         return -1;
   250     }
   251 
   252     WIN_PumpEvents(_this);
   253 
   254     if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
   255         DestroyWindow(hwnd);
   256         return -1;
   257     }
   258 #ifdef SDL_VIDEO_OPENGL_WGL
   259     if (window->flags & SDL_WINDOW_OPENGL) {
   260         if (WIN_GL_SetupWindow(_this, window) < 0) {
   261             WIN_DestroyWindow(_this, window);
   262             return -1;
   263         }
   264     }
   265 #endif
   266     return 0;
   267 }
   268 
   269 int
   270 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   271 {
   272     HWND hwnd = (HWND) data;
   273     LPTSTR title;
   274     int titleLen;
   275 
   276     /* Query the title from the existing window */
   277     titleLen = GetWindowTextLength(hwnd);
   278     title = SDL_stack_alloc(TCHAR, titleLen + 1);
   279     if (title) {
   280         titleLen = GetWindowText(hwnd, title, titleLen);
   281     } else {
   282         titleLen = 0;
   283     }
   284     if (titleLen > 0) {
   285         window->title = WIN_StringToUTF8(title);
   286     }
   287     if (title) {
   288         SDL_stack_free(title);
   289     }
   290 
   291     if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
   292         return -1;
   293     }
   294     return 0;
   295 }
   296 
   297 void
   298 WIN_SetWindowTitle(_THIS, SDL_Window * window)
   299 {
   300     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   301     LPTSTR title;
   302 
   303     if (window->title) {
   304         title = WIN_UTF8ToString(window->title);
   305     } else {
   306         title = NULL;
   307     }
   308     SetWindowText(hwnd, title ? title : TEXT(""));
   309     if (title) {
   310         SDL_free(title);
   311     }
   312 }
   313 
   314 void
   315 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   316 {
   317     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   318     HICON hicon = NULL;
   319 
   320     if (icon) {
   321         BYTE *icon_bmp;
   322         int icon_len;
   323         SDL_RWops *dst;
   324         SDL_PixelFormat format;
   325         SDL_Surface *surface;
   326 
   327         /* Create temporary bitmap buffer */
   328         icon_len = 40 + icon->h * icon->w * 4;
   329         icon_bmp = SDL_stack_alloc(BYTE, icon_len);
   330         dst = SDL_RWFromMem(icon_bmp, icon_len);
   331         if (!dst) {
   332             SDL_stack_free(icon_bmp);
   333             return;
   334         }
   335 
   336         /* Write the BITMAPINFO header */
   337         SDL_WriteLE32(dst, 40);
   338         SDL_WriteLE32(dst, icon->w);
   339         SDL_WriteLE32(dst, icon->h * 2);
   340         SDL_WriteLE16(dst, 1);
   341         SDL_WriteLE16(dst, 32);
   342         SDL_WriteLE32(dst, BI_RGB);
   343         SDL_WriteLE32(dst, icon->h * icon->w * 4);
   344         SDL_WriteLE32(dst, 0);
   345         SDL_WriteLE32(dst, 0);
   346         SDL_WriteLE32(dst, 0);
   347         SDL_WriteLE32(dst, 0);
   348 
   349         /* Convert the icon to a 32-bit surface with alpha channel */
   350         SDL_InitFormat(&format, 32,
   351                        0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
   352         surface = SDL_ConvertSurface(icon, &format, 0);
   353         if (surface) {
   354             /* Write the pixels upside down into the bitmap buffer */
   355             int y = surface->h;
   356             while (y--) {
   357                 Uint8 *src = (Uint8 *) surface->pixels + y * surface->pitch;
   358                 SDL_RWwrite(dst, src, surface->pitch, 1);
   359             }
   360             SDL_FreeSurface(surface);
   361 
   362 /* TODO: create the icon in WinCE (CreateIconFromResource isn't available) */
   363 #ifndef _WIN32_WCE
   364             hicon =
   365                 CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
   366 #endif
   367         }
   368         SDL_RWclose(dst);
   369         SDL_stack_free(icon_bmp);
   370     }
   371 
   372     /* Set the icon for the window */
   373     SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
   374 
   375     /* Set the icon in the task manager (should we do this?) */
   376     SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
   377 }
   378 
   379 void
   380 WIN_SetWindowPosition(_THIS, SDL_Window * window)
   381 {
   382     SDL_VideoDisplay *display = window->display;
   383     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   384     RECT rect;
   385     SDL_Rect bounds;
   386     DWORD style;
   387     HWND top;
   388     BOOL menu;
   389     int x, y;
   390 
   391     /* Figure out what the window area will be */
   392     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   393         top = HWND_TOPMOST;
   394     } else {
   395         top = HWND_NOTOPMOST;
   396     }
   397     style = GetWindowLong(hwnd, GWL_STYLE);
   398     rect.left = 0;
   399     rect.top = 0;
   400     rect.right = window->w;
   401     rect.bottom = window->h;
   402 #ifdef _WIN32_WCE
   403     menu = FALSE;
   404 #else
   405     menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   406 #endif
   407     AdjustWindowRectEx(&rect, style, menu, 0);
   408 
   409     WIN_GetDisplayBounds(_this, display, &bounds);
   410     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   411         || window->x == SDL_WINDOWPOS_CENTERED) {
   412         x = bounds.x + (bounds.w - window->w) / 2;
   413     } else {
   414         x = bounds.x + window->x + rect.left;
   415     }
   416     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   417         || window->y == SDL_WINDOWPOS_CENTERED) {
   418         y = bounds.y + (bounds.h - window->h) / 2;
   419     } else {
   420         y = bounds.y + window->y + rect.top;
   421     }
   422 
   423     SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE));
   424 }
   425 
   426 void
   427 WIN_SetWindowSize(_THIS, SDL_Window * window)
   428 {
   429     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   430     RECT rect;
   431     DWORD style;
   432     HWND top;
   433     BOOL menu;
   434     int w, h;
   435 
   436     /* Figure out what the window area will be */
   437     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   438         top = HWND_TOPMOST;
   439     } else {
   440         top = HWND_NOTOPMOST;
   441     }
   442     style = GetWindowLong(hwnd, GWL_STYLE);
   443     rect.left = 0;
   444     rect.top = 0;
   445     rect.right = window->w;
   446     rect.bottom = window->h;
   447 #ifdef _WIN32_WCE
   448     menu = FALSE;
   449 #else
   450     menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   451 #endif
   452     AdjustWindowRectEx(&rect, style, menu, 0);
   453     w = (rect.right - rect.left);
   454     h = (rect.bottom - rect.top);
   455 
   456     SetWindowPos(hwnd, top, 0, 0, w, h, (SWP_NOCOPYBITS | SWP_NOMOVE));
   457 }
   458 
   459 void
   460 WIN_ShowWindow(_THIS, SDL_Window * window)
   461 {
   462     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   463 
   464     ShowWindow(hwnd, SW_SHOW);
   465 
   466 #ifdef _WIN32_WCE
   467     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   468         CE_SHFullScreen(hwnd,
   469                         SHFS_HIDESTARTICON | SHFS_HIDETASKBAR |
   470                         SHFS_HIDESIPBUTTON);
   471     }
   472 #endif
   473 }
   474 
   475 void
   476 WIN_HideWindow(_THIS, SDL_Window * window)
   477 {
   478     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   479 
   480     ShowWindow(hwnd, SW_HIDE);
   481 
   482 #ifdef _WIN32_WCE
   483     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   484         CE_SHFullScreen(hwnd,
   485                         SHFS_SHOWSTARTICON | SHFS_SHOWTASKBAR |
   486                         SHFS_SHOWSIPBUTTON);
   487     }
   488 #endif
   489 }
   490 
   491 void
   492 WIN_RaiseWindow(_THIS, SDL_Window * window)
   493 {
   494     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   495     HWND top;
   496 
   497     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   498         top = HWND_TOPMOST;
   499     } else {
   500         top = HWND_NOTOPMOST;
   501     }
   502     SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
   503 
   504 #ifdef _WIN32_WCE
   505     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   506         CE_SHFullScreen(hwnd,
   507                         SHFS_HIDESTARTICON | SHFS_HIDETASKBAR |
   508                         SHFS_HIDESIPBUTTON);
   509     }
   510 #endif
   511 }
   512 
   513 void
   514 WIN_MaximizeWindow(_THIS, SDL_Window * window)
   515 {
   516     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   517 
   518     ShowWindow(hwnd, SW_MAXIMIZE);
   519 
   520 #ifdef _WIN32_WCE
   521     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   522         CE_SHFullScreen(hwnd,
   523                         SHFS_HIDESTARTICON | SHFS_HIDETASKBAR |
   524                         SHFS_HIDESIPBUTTON);
   525     }
   526 #endif
   527 }
   528 
   529 void
   530 WIN_MinimizeWindow(_THIS, SDL_Window * window)
   531 {
   532     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   533 
   534     ShowWindow(hwnd, SW_MINIMIZE);
   535 
   536 #ifdef _WIN32_WCE
   537     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   538         CE_SHFullScreen(hwnd,
   539                         SHFS_SHOWSTARTICON | SHFS_SHOWTASKBAR |
   540                         SHFS_SHOWSIPBUTTON);
   541     }
   542 #endif
   543 }
   544 
   545 void
   546 WIN_RestoreWindow(_THIS, SDL_Window * window)
   547 {
   548     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   549 
   550     ShowWindow(hwnd, SW_RESTORE);
   551 }
   552 
   553 void
   554 WIN_SetWindowGrab(_THIS, SDL_Window * window)
   555 {
   556     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   557 
   558     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
   559         && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   560         RECT rect;
   561         GetClientRect(hwnd, &rect);
   562         ClientToScreen(hwnd, (LPPOINT) & rect);
   563         ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   564         ClipCursor(&rect);
   565     } else {
   566         ClipCursor(NULL);
   567     }
   568 }
   569 
   570 void
   571 WIN_DestroyWindow(_THIS, SDL_Window * window)
   572 {
   573     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   574 
   575     if (data) {
   576         ReleaseDC(data->hwnd, data->hdc);
   577         if (data->created) {
   578             DestroyWindow(data->hwnd);
   579         }
   580         SDL_free(data);
   581     }
   582 }
   583 
   584 SDL_bool
   585 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   586 {
   587     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   588     if (info->version.major <= SDL_MAJOR_VERSION) {
   589         info->window = hwnd;
   590         return SDL_TRUE;
   591     } else {
   592         SDL_SetError("Application not compiled with SDL %d.%d\n",
   593                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   594         return SDL_FALSE;
   595     }
   596 }
   597 
   598 
   599 /*
   600  * Creates a HelperWindow used for DirectInput events.
   601  */
   602 int
   603 SDL_HelperWindowCreate(void)
   604 {
   605     HINSTANCE hInstance = GetModuleHandle(NULL);
   606     WNDCLASS wce;
   607     HWND hWndParent = NULL;
   608 
   609     /* Make sure window isn't created twice. */
   610     if (SDL_HelperWindow != NULL) {
   611         return 0;
   612     }
   613 
   614     /* Create the class. */
   615     SDL_zero(wce);
   616     wce.lpfnWndProc = DefWindowProc;
   617     wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
   618     wce.hInstance = hInstance;
   619 
   620     /* Register the class. */
   621     SDL_HelperWindowClass = RegisterClass(&wce);
   622     if (SDL_HelperWindowClass == 0) {
   623         SDL_SetError("Unable to create Helper Window Class: error %d.",
   624                      GetLastError());
   625         return -1;
   626     }
   627 
   628 #ifndef _WIN32_WCE
   629     /* WinCE doesn't have HWND_MESSAGE */
   630     hWndParent = HWND_MESSAGE;
   631 #endif
   632 
   633     /* Create the window. */
   634     SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
   635                                       SDL_HelperWindowName,
   636                                       WS_OVERLAPPED, CW_USEDEFAULT,
   637                                       CW_USEDEFAULT, CW_USEDEFAULT,
   638                                       CW_USEDEFAULT, hWndParent, NULL,
   639                                       hInstance, NULL);
   640     if (SDL_HelperWindow == NULL) {
   641         UnregisterClass(SDL_HelperWindowClassName, hInstance);
   642         SDL_SetError("Unable to create Helper Window: error %d.",
   643                      GetLastError());
   644         return -1;
   645     }
   646 
   647     return 0;
   648 }
   649 
   650 
   651 /*
   652  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
   653  */
   654 void
   655 SDL_HelperWindowDestroy(void)
   656 {
   657     HINSTANCE hInstance = GetModuleHandle(NULL);
   658 
   659     /* Destroy the window. */
   660     if (SDL_HelperWindow != NULL) {
   661         if (DestroyWindow(SDL_HelperWindow) == 0) {
   662             SDL_SetError("Unable to destroy Helper Window: error %d.",
   663                          GetLastError());
   664             return;
   665         }
   666         SDL_HelperWindow = NULL;
   667     }
   668 
   669     /* Unregister the class. */
   670     if (SDL_HelperWindowClass != 0) {
   671         if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
   672             SDL_SetError("Unable to destroy Helper Window Class: error %d.",
   673                          GetLastError());
   674             return;
   675         }
   676         SDL_HelperWindowClass = 0;
   677     }
   678 }
   679 
   680 
   681 /* vi: set ts=4 sw=4 expandtab: */