zenilib: zenilib/jni/external/sdl/src/video/windows/SDL_windowsmessagebox.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_windowsmessagebox.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 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.h"
26 #include "SDL_windowsvideo.h"
27
28
29 #ifndef SS_EDITCONTROL
30 #define SS_EDITCONTROL 0x2000
31 #endif
32
33 /* Display a Windows message box */
34
35 #pragma pack(push, 1)
36
37 typedef struct
38 {
39 WORD dlgVer;
40 WORD signature;
41 DWORD helpID;
42 DWORD exStyle;
43 DWORD style;
44 WORD cDlgItems;
45 short x;
46 short y;
47 short cx;
48 short cy;
49 } DLGTEMPLATEEX;
50
51 typedef struct
52 {
53 DWORD helpID;
54 DWORD exStyle;
55 DWORD style;
56 short x;
57 short y;
58 short cx;
59 short cy;
60 DWORD id;
61 } DLGITEMTEMPLATEEX;
62
63 #pragma pack(pop)
64
65 typedef struct
66 {
67 DLGTEMPLATEEX* lpDialog;
68 Uint8 *data;
69 size_t size;
70 size_t used;
71 } WIN_DialogData;
72
73
74 static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
75 {
76 switch ( iMessage ) {
77 case WM_COMMAND:
78 /* Return the ID of the button that was pushed */
79 EndDialog(hDlg, LOWORD(wParam));
80 return TRUE;
81
82 default:
83 break;
84 }
85 return FALSE;
86 }
87
88 static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space)
89 {
90 size_t size = dialog->size;
91
92 if (size == 0) {
93 size = space;
94 } else {
95 while ((dialog->used + space) > size) {
96 size *= 2;
97 }
98 }
99 if (size > dialog->size) {
100 void *data = SDL_realloc(dialog->data, size);
101 if (!data) {
102 SDL_OutOfMemory();
103 return SDL_FALSE;
104 }
105 dialog->data = data;
106 dialog->size = size;
107 dialog->lpDialog = (DLGTEMPLATEEX*)dialog->data;
108 }
109 return SDL_TRUE;
110 }
111
112 static SDL_bool AlignDialogData(WIN_DialogData *dialog, size_t size)
113 {
114 size_t padding = (dialog->used % size);
115
116 if (!ExpandDialogSpace(dialog, padding)) {
117 return SDL_FALSE;
118 }
119
120 dialog->used += padding;
121
122 return SDL_TRUE;
123 }
124
125 static SDL_bool AddDialogData(WIN_DialogData *dialog, const void *data, size_t size)
126 {
127 if (!ExpandDialogSpace(dialog, size)) {
128 return SDL_FALSE;
129 }
130
131 SDL_memcpy(dialog->data+dialog->used, data, size);
132 dialog->used += size;
133
134 return SDL_TRUE;
135 }
136
137 static SDL_bool AddDialogString(WIN_DialogData *dialog, const char *string)
138 {
139 WCHAR *wstring;
140 WCHAR *p;
141 size_t count;
142 SDL_bool status;
143
144 if (!string) {
145 string = "";
146 }
147
148 wstring = WIN_UTF8ToString(string);
149 if (!wstring) {
150 return SDL_FALSE;
151 }
152
153 /* Find out how many characters we have, including null terminator */
154 count = 0;
155 for (p = wstring; *p; ++p) {
156 ++count;
157 }
158 ++count;
159
160 status = AddDialogData(dialog, wstring, count*sizeof(WCHAR));
161 SDL_free(wstring);
162 return status;
163 }
164
165 static int s_BaseUnitsX;
166 static int s_BaseUnitsY;
167 static void Vec2ToDLU(short *x, short *y)
168 {
169 SDL_assert(s_BaseUnitsX != 0); /* we init in WIN_ShowMessageBox(), which is the only public function... */
170
171 *x = MulDiv(*x, 4, s_BaseUnitsX);
172 *y = MulDiv(*y, 8, s_BaseUnitsY);
173 }
174
175
176 static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, DWORD exStyle, int x, int y, int w, int h, int id, const char *caption)
177 {
178 DLGITEMTEMPLATEEX item;
179 WORD marker = 0xFFFF;
180 WORD extraData = 0;
181
182 SDL_zero(item);
183 item.style = style;
184 item.exStyle = exStyle;
185 item.x = x;
186 item.y = y;
187 item.cx = w;
188 item.cy = h;
189 item.id = id;
190
191 Vec2ToDLU(&item.x, &item.y);
192 Vec2ToDLU(&item.cx, &item.cy);
193
194 if (!AlignDialogData(dialog, sizeof(DWORD))) {
195 return SDL_FALSE;
196 }
197 if (!AddDialogData(dialog, &item, sizeof(item))) {
198 return SDL_FALSE;
199 }
200 if (!AddDialogData(dialog, &marker, sizeof(marker))) {
201 return SDL_FALSE;
202 }
203 if (!AddDialogData(dialog, &type, sizeof(type))) {
204 return SDL_FALSE;
205 }
206 if (!AddDialogString(dialog, caption)) {
207 return SDL_FALSE;
208 }
209 if (!AddDialogData(dialog, &extraData, sizeof(extraData))) {
210 return SDL_FALSE;
211 }
212 ++dialog->lpDialog->cDlgItems;
213
214 return SDL_TRUE;
215 }
216
217 static SDL_bool AddDialogStatic(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text)
218 {
219 DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX | SS_EDITCONTROL;
220 return AddDialogControl(dialog, 0x0082, style, 0, x, y, w, h, -1, text);
221 }
222
223 static SDL_bool AddDialogButton(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text, int id, SDL_bool isDefault)
224 {
225 DWORD style = WS_VISIBLE | WS_CHILD;
226 if (isDefault) {
227 style |= BS_DEFPUSHBUTTON;
228 } else {
229 style |= BS_PUSHBUTTON;
230 }
231 return AddDialogControl(dialog, 0x0080, style, 0, x, y, w, h, id, text);
232 }
233
234 static void FreeDialogData(WIN_DialogData *dialog)
235 {
236 SDL_free(dialog->data);
237 SDL_free(dialog);
238 }
239
240 static WIN_DialogData *CreateDialogData(int w, int h, const char *caption)
241 {
242 WIN_DialogData *dialog;
243 DLGTEMPLATEEX dialogTemplate;
244 WORD WordToPass;
245
246 SDL_zero(dialogTemplate);
247 dialogTemplate.dlgVer = 1;
248 dialogTemplate.signature = 0xffff;
249 dialogTemplate.style = (WS_CAPTION | DS_CENTER | DS_SHELLFONT);
250 dialogTemplate.x = 0;
251 dialogTemplate.y = 0;
252 dialogTemplate.cx = w;
253 dialogTemplate.cy = h;
254 Vec2ToDLU(&dialogTemplate.cx, &dialogTemplate.cy);
255
256 dialog = (WIN_DialogData *)SDL_calloc(1, sizeof(*dialog));
257 if (!dialog) {
258 return NULL;
259 }
260
261 if (!AddDialogData(dialog, &dialogTemplate, sizeof(dialogTemplate))) {
262 FreeDialogData(dialog);
263 return NULL;
264 }
265
266 /* No menu */
267 WordToPass = 0;
268 if (!AddDialogData(dialog, &WordToPass, 2)) {
269 FreeDialogData(dialog);
270 return NULL;
271 }
272
273 /* No custom class */
274 if (!AddDialogData(dialog, &WordToPass, 2)) {
275 FreeDialogData(dialog);
276 return NULL;
277 }
278
279 /* title */
280 if (!AddDialogString(dialog, caption)) {
281 FreeDialogData(dialog);
282 return NULL;
283 }
284
285 /* Font stuff */
286 {
287 /*
288 * We want to use the system messagebox font.
289 */
290 BYTE ToPass;
291
292 NONCLIENTMETRICSA NCM;
293 NCM.cbSize = sizeof(NCM);
294 SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
295
296 /* Font size - convert to logical font size for dialog parameter. */
297 {
298 HDC ScreenDC = GetDC(0);
299 WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / GetDeviceCaps(ScreenDC, LOGPIXELSY));
300 ReleaseDC(0, ScreenDC);
301 }
302
303 if (!AddDialogData(dialog, &WordToPass, 2)) {
304 FreeDialogData(dialog);
305 return NULL;
306 }
307
308 /* Font weight */
309 WordToPass = (WORD)NCM.lfMessageFont.lfWeight;
310 if (!AddDialogData(dialog, &WordToPass, 2)) {
311 FreeDialogData(dialog);
312 return NULL;
313 }
314
315 /* italic? */
316 ToPass = NCM.lfMessageFont.lfItalic;
317 if (!AddDialogData(dialog, &ToPass, 1)) {
318 FreeDialogData(dialog);
319 return NULL;
320 }
321
322 /* charset? */
323 ToPass = NCM.lfMessageFont.lfCharSet;
324 if (!AddDialogData(dialog, &ToPass, 1)) {
325 FreeDialogData(dialog);
326 return NULL;
327 }
328
329 /* font typeface. */
330 if (!AddDialogString(dialog, NCM.lfMessageFont.lfFaceName)) {
331 FreeDialogData(dialog);
332 return NULL;
333 }
334 }
335
336 return dialog;
337 }
338
339 int
340 WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
341 {
342 WIN_DialogData *dialog;
343 int i, x, y, which;
344 const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
345 HFONT DialogFont;
346 SIZE Size;
347 RECT TextSize;
348 wchar_t* wmessage;
349 TEXTMETRIC TM;
350
351
352 const int ButtonWidth = 88;
353 const int ButtonHeight = 26;
354 const int TextMargin = 16;
355 const int ButtonMargin = 12;
356
357
358 /* Jan 25th, 2013 - dant@fleetsa.com
359 *
360 *
361 * I've tried to make this more reasonable, but I've run in to a lot
362 * of nonsense.
363 *
364 * The original issue is the code was written in pixels and not
365 * dialog units (DLUs). All DialogBox functions use DLUs, which
366 * vary based on the selected font (yay).
367 *
368 * According to MSDN, the most reliable way to convert is via
369 * MapDialogUnits, which requires an HWND, which we don't have
370 * at time of template creation.
371 *
372 * We do however have:
373 * The system font (DLU width 8 for me)
374 * The font we select for the dialog (DLU width 6 for me)
375 *
376 * Based on experimentation, *neither* of these return the value
377 * actually used. Stepping in to MapDialogUnits(), the conversion
378 * is fairly clear, and uses 7 for me.
379 *
380 * As a result, some of this is hacky to ensure the sizing is
381 * somewhat correct.
382 *
383 * Honestly, a long term solution is to use CreateWindow, not CreateDialog.
384 *
385
386 *
387 * In order to get text dimensions we need to have a DC with the desired font.
388 * I'm assuming a dialog box in SDL is rare enough we can to the create.
389 */
390 HDC FontDC = CreateCompatibleDC(0);
391
392 {
393 /* Create a duplicate of the font used in system message boxes. */
394 LOGFONT lf;
395 NONCLIENTMETRICS NCM;
396 NCM.cbSize = sizeof(NCM);
397 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
398 lf = NCM.lfMessageFont;
399 DialogFont = CreateFontIndirect(&lf);
400 }
401
402 /* Select the font in to our DC */
403 SelectObject(FontDC, DialogFont);
404
405 {
406 /* Get the metrics to try and figure our DLU conversion. */
407 GetTextMetrics(FontDC, &TM);
408 s_BaseUnitsX = TM.tmAveCharWidth + 1;
409 s_BaseUnitsY = TM.tmHeight;
410 }
411
412 /* Measure the *pixel* size of the string. */
413 wmessage = WIN_UTF8ToString(messageboxdata->message);
414 SDL_zero(TextSize);
415 Size.cx = DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT);
416
417 /* Add some padding for hangs, etc. */
418 TextSize.right += 2;
419 TextSize.bottom += 2;
420
421 /* Done with the DC, and the string */
422 DeleteDC(FontDC);
423 SDL_free(wmessage);
424
425 /* Increase the size of the dialog by some border spacing around the text. */
426 Size.cx = TextSize.right - TextSize.left;
427 Size.cy = TextSize.bottom - TextSize.top;
428 Size.cx += TextMargin * 2;
429 Size.cy += TextMargin * 2;
430
431 /* Ensure the size is wide enough for all of the buttons. */
432 if (Size.cx < messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin)
433 Size.cx = messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin;
434
435 /* Add vertical space for the buttons and border. */
436 Size.cy += ButtonHeight + TextMargin;
437
438 dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->title);
439 if (!dialog) {
440 return -1;
441 }
442
443 if (!AddDialogStatic(dialog, TextMargin, TextMargin, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->message)) {
444 FreeDialogData(dialog);
445 return -1;
446 }
447
448 /* Align the buttons to the right/bottom. */
449 x = Size.cx - ButtonWidth - ButtonMargin;
450 y = Size.cy - ButtonHeight - ButtonMargin;
451 for (i = 0; i < messageboxdata->numbuttons; ++i) {
452 SDL_bool isDefault;
453
454 if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
455 isDefault = SDL_TRUE;
456 } else {
457 isDefault = SDL_FALSE;
458 }
459 if (!AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttons[i].text, i, isDefault)) {
460 FreeDialogData(dialog);
461 return -1;
462 }
463 x -= ButtonWidth + ButtonMargin;
464 }
465
466 /* FIXME: If we have a parent window, get the Instance and HWND for them */
467 which = DialogBoxIndirect(NULL, (DLGTEMPLATE*)dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc);
468 *buttonid = buttons[which].buttonid;
469
470 FreeDialogData(dialog);
471 return 0;
472 }
473
474 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
475
476 /* vi: set ts=4 sw=4 expandtab: */
SDL_MessageBoxData::message
const char * message
Definition: SDL_messagebox.h:97
WIN_UTF8ToString
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:42
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
type
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
marker
const GLchar * marker
Definition: gl2ext.h:1092
SDL_calloc
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
SDL_MessageBoxData::title
const char * title
Definition: SDL_messagebox.h:96
NULL
#define NULL
Definition: ftobjs.h:61
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:116
SDL_TRUE
Definition: SDL_stdinc.h:119
x
EGLSurface EGLint x
Definition: eglext.h:293
SDL_realloc
DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size)
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
UINT
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
if
if(!yyg->yy_init)
Definition: glslang_lex.cpp:1037
SDL_FALSE
Definition: SDL_stdinc.h:118
id
GLuint id
Definition: gl2ext.h:1142
SDL_config.h
HDC
typedef HDC(WINAPI *PFNWGLGETCURRENTREADDCARBPROC)(VOID)
SDL_MessageBoxButtonData
Individual button data.
Definition: SDL_messagebox.h:56
SDL_MessageBoxButtonData::buttonid
int buttonid
Definition: SDL_messagebox.h:59
SDL_MessageBoxData::numbuttons
int numbuttons
Definition: SDL_messagebox.h:99
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
count
GLint GLsizei count
Definition: gl2ext.h:1011
p
GLfloat GLfloat p
Definition: glew.h:14938
FALSE
#define FALSE
Definition: ftobjs.h:57
SDL_MessageBoxData::buttons
const SDL_MessageBoxButtonData * buttons
Definition: SDL_messagebox.h:100
SDL_MessageBoxData
MessageBox structure containing title, text, window, etc.
Definition: SDL_messagebox.h:92
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:159
y
EGLSurface EGLint EGLint y
Definition: eglext.h:293
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_memcpy
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
DWORD
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
w
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
i
int i
Definition: pngrutil.c:1377
SDL_windowsvideo.h
TRUE
#define TRUE
Definition: ftobjs.h:53
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT
Definition: SDL_messagebox.h:49
size
GLsizei size
Definition: gl2ext.h:1467