Added Windows message box implementation, but it needs a little work on layout.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "SDL_config.h"
23 #if SDL_VIDEO_DRIVER_WINDOWS
25 #include "../SDL_sysvideo.h"
26 #include "../SDL_pixels_c.h"
27 #include "../../events/SDL_keyboard_c.h"
29 #include "SDL_windowsvideo.h"
30 #include "SDL_windowswindow.h"
32 /* Dropfile support */
35 /* This is included after SDL_windowsvideo.h, which includes windows.h */
36 #include "SDL_syswm.h"
38 /* Windows CE compatibility */
39 #ifndef SWP_NOCOPYBITS
40 #define SWP_NOCOPYBITS 0
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;
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)
57 GetWindowStyle(SDL_Window * window)
61 if (window->flags & SDL_WINDOW_FULLSCREEN) {
62 style |= STYLE_FULLSCREEN;
64 if (window->flags & SDL_WINDOW_BORDERLESS) {
65 style |= STYLE_BORDERLESS;
67 style |= STYLE_NORMAL;
69 if (window->flags & SDL_WINDOW_RESIZABLE) {
70 style |= STYLE_RESIZABLE;
77 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
79 SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
82 /* Allocate the window data */
83 data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
88 data->window = window;
90 data->hdc = GetDC(hwnd);
91 data->created = created;
92 data->mouse_pressed = SDL_FALSE;
93 data->videodata = videodata;
95 window->driverdata = data;
97 /* Associate the data with the window */
98 if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
99 ReleaseDC(hwnd, data->hdc);
101 WIN_SetError("SetProp() failed");
105 /* Set up the window proc function */
107 data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
108 if (data->wndproc == WIN_WindowProc) {
109 data->wndproc = NULL;
111 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
114 data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
115 if (data->wndproc == WIN_WindowProc) {
116 data->wndproc = NULL;
118 SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
122 /* Fill in the SDL window with the window data */
127 if (ClientToScreen(hwnd, &point)) {
134 if (GetClientRect(hwnd, &rect)) {
135 window->w = rect.right;
136 window->h = rect.bottom;
140 DWORD style = GetWindowLong(hwnd, GWL_STYLE);
141 if (style & WS_VISIBLE) {
142 window->flags |= SDL_WINDOW_SHOWN;
144 window->flags &= ~SDL_WINDOW_SHOWN;
146 if (style & (WS_BORDER | WS_THICKFRAME)) {
147 window->flags &= ~SDL_WINDOW_BORDERLESS;
149 window->flags |= SDL_WINDOW_BORDERLESS;
151 if (style & WS_THICKFRAME) {
152 window->flags |= SDL_WINDOW_RESIZABLE;
154 window->flags &= ~SDL_WINDOW_RESIZABLE;
157 if (style & WS_MAXIMIZE) {
158 window->flags |= SDL_WINDOW_MAXIMIZED;
162 window->flags &= ~SDL_WINDOW_MAXIMIZED;
165 if (style & WS_MINIMIZE) {
166 window->flags |= SDL_WINDOW_MINIMIZED;
170 window->flags &= ~SDL_WINDOW_MINIMIZED;
173 if (GetFocus() == hwnd) {
174 window->flags |= SDL_WINDOW_INPUT_FOCUS;
175 SDL_SetKeyboardFocus(data->window);
177 if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
179 GetClientRect(hwnd, &rect);
180 ClientToScreen(hwnd, (LPPOINT) & rect);
181 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
186 /* Enable multi-touch */
187 if (videodata->RegisterTouchWindow) {
188 videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
191 /* Enable dropping files */
192 DragAcceptFiles(hwnd, TRUE);
199 WIN_CreateWindow(_THIS, SDL_Window * window)
203 DWORD style = STYLE_BASIC;
207 style |= GetWindowStyle(window);
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);
217 w = (rect.right - rect.left);
218 h = (rect.bottom - rect.top);
221 CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
224 WIN_SetError("Couldn't create window");
228 WIN_PumpEvents(_this);
230 if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
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);
246 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
248 HWND hwnd = (HWND) data;
252 /* Query the title from the existing window */
253 titleLen = GetWindowTextLength(hwnd);
254 title = SDL_stack_alloc(TCHAR, titleLen + 1);
256 titleLen = GetWindowText(hwnd, title, titleLen);
261 window->title = WIN_StringToUTF8(title);
264 SDL_stack_free(title);
267 if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
274 WIN_SetWindowTitle(_THIS, SDL_Window * window)
276 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
280 title = WIN_UTF8ToString(window->title);
284 SetWindowText(hwnd, title ? title : TEXT(""));
291 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
293 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
298 SDL_Surface *surface;
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);
305 SDL_stack_free(icon_bmp);
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);
322 /* Convert the icon to a 32-bit surface with alpha channel */
323 surface = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
325 /* Write the pixels upside down into the bitmap buffer */
328 Uint8 *src = (Uint8 *) surface->pixels + y * surface->pitch;
329 SDL_RWwrite(dst, src, surface->pitch, 1);
331 SDL_FreeSurface(surface);
333 hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
336 SDL_stack_free(icon_bmp);
338 /* Set the icon for the window */
339 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
341 /* Set the icon in the task manager (should we do this?) */
342 SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
346 WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
348 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
356 /* Figure out what the window area will be */
357 if (window->flags & SDL_WINDOW_FULLSCREEN) {
360 top = HWND_NOTOPMOST;
362 style = GetWindowLong(hwnd, GWL_STYLE);
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;
374 SetWindowPos(hwnd, top, x, y, w, h, flags);
378 WIN_SetWindowPosition(_THIS, SDL_Window * window)
380 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
384 WIN_SetWindowSize(_THIS, SDL_Window * window)
386 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
390 WIN_ShowWindow(_THIS, SDL_Window * window)
392 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
393 ShowWindow(hwnd, SW_SHOW);
397 WIN_HideWindow(_THIS, SDL_Window * window)
399 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
400 ShowWindow(hwnd, SW_HIDE);
404 WIN_RaiseWindow(_THIS, SDL_Window * window)
406 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
409 if (window->flags & SDL_WINDOW_FULLSCREEN) {
412 top = HWND_NOTOPMOST;
414 SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
418 WIN_MaximizeWindow(_THIS, SDL_Window * window)
420 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
421 ShowWindow(hwnd, SW_MAXIMIZE);
425 WIN_MinimizeWindow(_THIS, SDL_Window * window)
427 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
428 ShowWindow(hwnd, SW_MINIMIZE);
432 WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
434 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
435 DWORD style = GetWindowLong(hwnd, GWL_STYLE);
438 style &= ~STYLE_BORDERLESS;
439 style |= STYLE_NORMAL;
441 style &= ~STYLE_NORMAL;
442 style |= STYLE_BORDERLESS;
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);
450 WIN_RestoreWindow(_THIS, SDL_Window * window)
452 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
454 ShowWindow(hwnd, SW_RESTORE);
458 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
460 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
461 HWND hwnd = data->hwnd;
473 top = HWND_NOTOPMOST;
475 style = GetWindowLong(hwnd, GWL_STYLE);
476 style &= ~STYLE_MASK;
477 style |= GetWindowStyle(window);
479 WIN_GetDisplayBounds(_this, display, &bounds);
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;
498 SetWindowLong(hwnd, GWL_STYLE, style);
499 SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS);
503 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
505 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
506 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
508 BOOL succeeded = FALSE;
510 hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
512 succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
514 WIN_SetError("SetDeviceGammaRamp()");
518 return succeeded ? 0 : -1;
522 WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
524 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
525 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
527 BOOL succeeded = FALSE;
529 hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
531 succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
533 WIN_SetError("GetDeviceGammaRamp()");
537 return succeeded ? 0 : -1;
541 WIN_SetWindowGrab(_THIS, SDL_Window * window)
543 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
545 if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
546 (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
548 GetClientRect(hwnd, &rect);
549 ClientToScreen(hwnd, (LPPOINT) & rect);
550 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
558 WIN_DestroyWindow(_THIS, SDL_Window * window)
560 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
563 ReleaseDC(data->hwnd, data->hdc);
565 DestroyWindow(data->hwnd);
567 /* Restore any original event handler... */
568 if (data->wndproc != NULL) {
570 SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
571 (LONG_PTR) data->wndproc);
573 SetWindowLong(data->hwnd, GWL_WNDPROC,
574 (LONG_PTR) data->wndproc);
583 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
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;
591 SDL_SetError("Application not compiled with SDL %d.%d\n",
592 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
599 * Creates a HelperWindow used for DirectInput events.
602 SDL_HelperWindowCreate(void)
604 HINSTANCE hInstance = GetModuleHandle(NULL);
607 /* Make sure window isn't created twice. */
608 if (SDL_HelperWindow != NULL) {
612 /* Create the class. */
614 wce.lpfnWndProc = DefWindowProc;
615 wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
616 wce.hInstance = hInstance;
618 /* Register the class. */
619 SDL_HelperWindowClass = RegisterClass(&wce);
620 if (SDL_HelperWindowClass == 0) {
621 WIN_SetError("Unable to create Helper Window Class");
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,
632 if (SDL_HelperWindow == NULL) {
633 UnregisterClass(SDL_HelperWindowClassName, hInstance);
634 WIN_SetError("Unable to create Helper Window");
643 * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
646 SDL_HelperWindowDestroy(void)
648 HINSTANCE hInstance = GetModuleHandle(NULL);
650 /* Destroy the window. */
651 if (SDL_HelperWindow != NULL) {
652 if (DestroyWindow(SDL_HelperWindow) == 0) {
653 WIN_SetError("Unable to destroy Helper Window");
656 SDL_HelperWindow = NULL;
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");
665 SDL_HelperWindowClass = 0;
669 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
671 /* vi: set ts=4 sw=4 expandtab: */