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