4 * Copyright 1995 Bernd Schmidt
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/winestring.h"
17 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(dialog
)
22 #define MSGBOX_IDICON 1088
23 #define MSGBOX_IDTEXT 100
25 static HFONT
MSGBOX_OnInit(HWND hwnd
, LPMSGBOXPARAMSA lpmb
)
27 static HFONT hFont
= 0, hPrevFont
= 0;
32 int bspace
, bw
, bh
, theight
, tleft
, wwidth
, wheight
, bpos
;
33 int borheight
, borwidth
, iheight
, ileft
, iwidth
, twidth
, tiheight
;
37 if (TWEAK_WineLook
>= WIN95_LOOK
) {
38 NONCLIENTMETRICSA nclm
;
39 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
40 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
41 hFont
= CreateFontIndirectA (&nclm
.lfMessageFont
);
44 SendDlgItemMessageA (hwnd
, i
, WM_SETFONT
, (WPARAM
)hFont
, 0);
46 SendDlgItemMessageA (hwnd
, MSGBOX_IDTEXT
, WM_SETFONT
, (WPARAM
)hFont
, 0);
48 if (HIWORD(lpmb
->lpszCaption
)) {
49 SetWindowTextA(hwnd
, lpmb
->lpszCaption
);
51 if (LoadStringA(lpmb
->hInstance
, LOWORD(lpmb
->lpszCaption
), buf
, sizeof(buf
)))
52 SetWindowTextA(hwnd
, buf
);
54 if (HIWORD(lpmb
->lpszText
)) {
55 lpszText
= lpmb
->lpszText
;
58 if (!LoadStringA(lpmb
->hInstance
, LOWORD(lpmb
->lpszText
), buf
, sizeof(buf
)))
59 *buf
= 0; /* FIXME ?? */
61 SetWindowTextA(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), lpszText
);
63 /* Hide not selected buttons */
64 switch(lpmb
->dwStyle
& MB_TYPEMASK
) {
66 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
69 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
70 ShowWindow(GetDlgItem(hwnd
, IDRETRY
), SW_HIDE
);
71 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
72 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
73 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
75 case MB_ABORTRETRYIGNORE
:
76 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
77 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
78 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
79 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
82 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
85 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
86 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
87 ShowWindow(GetDlgItem(hwnd
, IDRETRY
), SW_HIDE
);
88 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
91 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
92 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
93 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
94 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
95 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
99 switch(lpmb
->dwStyle
& MB_ICONMASK
) {
100 case MB_ICONEXCLAMATION
:
101 SendDlgItemMessage16(hwnd
, stc1
, STM_SETICON16
,
102 (WPARAM16
)LoadIcon16(0, IDI_EXCLAMATION16
), 0);
104 case MB_ICONQUESTION
:
105 SendDlgItemMessage16(hwnd
, stc1
, STM_SETICON16
,
106 (WPARAM16
)LoadIcon16(0, IDI_QUESTION16
), 0);
108 case MB_ICONASTERISK
:
109 SendDlgItemMessage16(hwnd
, stc1
, STM_SETICON16
,
110 (WPARAM16
)LoadIcon16(0, IDI_ASTERISK16
), 0);
113 SendDlgItemMessage16(hwnd
, stc1
, STM_SETICON16
,
114 (WPARAM16
)LoadIcon16(0, IDI_HAND16
), 0);
117 /* By default, Windows 95/98/NT do not associate an icon to message boxes.
118 * So wine should do the same.
123 /* Position everything */
124 GetWindowRect(hwnd
, &rect
);
125 borheight
= rect
.bottom
- rect
.top
;
126 borwidth
= rect
.right
- rect
.left
;
127 GetClientRect(hwnd
, &rect
);
128 borheight
-= rect
.bottom
- rect
.top
;
129 borwidth
-= rect
.right
- rect
.left
;
131 /* Get the icon height */
132 GetWindowRect(GetDlgItem(hwnd
, MSGBOX_IDICON
), &rect
);
133 MapWindowPoints(0, hwnd
, (LPPOINT
)&rect
, 2);
134 iheight
= rect
.bottom
- rect
.top
;
136 iwidth
= rect
.right
- ileft
;
140 hPrevFont
= SelectObject(hdc
, hFont
);
142 /* Get the number of visible buttons and their size */
143 bh
= bw
= 1; /* Minimum button sizes */
144 for (buttons
= 0, i
= 1; i
< 8; i
++)
146 hItem
= GetDlgItem(hwnd
, i
);
147 if (GetWindowLongA(hItem
, GWL_STYLE
) & WS_VISIBLE
)
149 char buttonText
[1024];
152 if (GetWindowTextA(hItem
, buttonText
, sizeof buttonText
))
154 DrawTextA( hdc
, buttonText
, -1, &rect
, DT_LEFT
| DT_EXPANDTABS
| DT_CALCRECT
);
155 h
= rect
.bottom
- rect
.top
;
156 w
= rect
.right
- rect
.left
;
162 bw
= max(bw
, bh
* 2);
163 /* Button white space */
166 bspace
= bw
/3; /* Space between buttons */
168 /* Get the text size */
169 GetClientRect(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), &rect
);
170 rect
.top
= rect
.left
= rect
.bottom
= 0;
171 DrawTextA( hdc
, lpszText
, -1, &rect
,
172 DT_LEFT
| DT_EXPANDTABS
| DT_WORDBREAK
| DT_CALCRECT
);
173 /* Min text width corresponds to space for the buttons */
174 tleft
= 2 * ileft
+ iwidth
;
175 twidth
= max((bw
+ bspace
) * buttons
+ bspace
- tleft
, rect
.right
);
176 theight
= rect
.bottom
;
179 SelectObject(hdc
, hPrevFont
);
180 ReleaseDC(hItem
, hdc
);
182 tiheight
= 16 + max(iheight
, theight
);
183 wwidth
= tleft
+ twidth
+ ileft
+ borwidth
;
184 wheight
= 8 + tiheight
+ bh
+ borheight
;
186 /* Resize the window */
187 SetWindowPos(hwnd
, 0, 0, 0, wwidth
, wheight
,
188 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
190 /* Position the icon */
191 SetWindowPos(GetDlgItem(hwnd
, MSGBOX_IDICON
), 0, ileft
, (tiheight
- iheight
) / 2, 0, 0,
192 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
194 /* Position the text */
195 SetWindowPos(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), 0, tleft
, (tiheight
- theight
) / 2, twidth
, theight
,
196 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
198 /* Position the buttons */
199 bpos
= (wwidth
- (bw
+ bspace
) * buttons
+ bspace
) / 2;
200 for (buttons
= i
= 0; i
< 7; i
++) {
201 /* some arithmetic to get the right order for YesNoCancel windows */
202 hItem
= GetDlgItem(hwnd
, (i
+ 5) % 7 + 1);
203 if (GetWindowLongA(hItem
, GWL_STYLE
) & WS_VISIBLE
) {
204 if (buttons
++ == ((lpmb
->dwStyle
& MB_DEFMASK
) >> 8)) {
206 SendMessageA( hItem
, BM_SETSTYLE
, BS_DEFPUSHBUTTON
, TRUE
);
208 SetWindowPos(hItem
, 0, bpos
, tiheight
, bw
, bh
,
209 SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOREDRAW
);
217 /**************************************************************************
220 * Dialog procedure for message boxes.
222 static LRESULT CALLBACK
MSGBOX_DlgProc( HWND hwnd
, UINT message
,
223 WPARAM wParam
, LPARAM lParam
)
228 hFont
= MSGBOX_OnInit(hwnd
, (LPMSGBOXPARAMSA
)lParam
);
241 EndDialog(hwnd
, wParam
);
248 /* Ok. Ignore all the other messages */
249 TRACE("Message number %i is being ignored.\n", message
);
256 /**************************************************************************
257 * MessageBox16 (USER.1)
259 INT16 WINAPI
MessageBox16( HWND16 hwnd
, LPCSTR text
, LPCSTR title
, UINT16 type
)
261 WARN("Messagebox\n");
262 return MessageBoxA( hwnd
, text
, title
, type
);
266 /**************************************************************************
267 * MessageBoxA (USER32.391)
270 * The WARN is here to help debug erroneous MessageBoxes
271 * Use: -debugmsg warn+dialog,+relay
273 INT WINAPI
MessageBoxA(HWND hWnd
, LPCSTR text
, LPCSTR title
, UINT type
)
279 WARN("Messagebox\n");
281 if(!(hRes
= FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA
)))
283 if(!(template = (LPVOID
)LoadResource(GetModuleHandleA("USER32"), hRes
)))
286 if (!text
) text
="<WINE-NULL>";
289 mbox
.lpszCaption
= title
;
290 mbox
.lpszText
= text
;
292 return DialogBoxIndirectParamA( GetWindowLongA(hWnd
,GWL_HINSTANCE
), template,
293 hWnd
, (DLGPROC
)MSGBOX_DlgProc
, (LPARAM
)&mbox
);
297 /**************************************************************************
298 * MessageBoxW (USER32.396)
300 INT WINAPI
MessageBoxW( HWND hwnd
, LPCWSTR text
, LPCWSTR title
,
303 LPSTR titleA
= HEAP_strdupWtoA( GetProcessHeap(), 0, title
);
304 LPSTR textA
= HEAP_strdupWtoA( GetProcessHeap(), 0, text
);
307 WARN("Messagebox\n");
309 ret
= MessageBoxA( hwnd
, textA
, titleA
, type
);
310 HeapFree( GetProcessHeap(), 0, titleA
);
311 HeapFree( GetProcessHeap(), 0, textA
);
316 /**************************************************************************
317 * MessageBoxExA (USER32.392)
319 INT WINAPI
MessageBoxExA( HWND hWnd
, LPCSTR text
, LPCSTR title
,
320 UINT type
, WORD langid
)
322 WARN("Messagebox\n");
323 /* ignore language id for now */
324 return MessageBoxA(hWnd
,text
,title
,type
);
327 /**************************************************************************
328 * MessageBoxExW (USER32.393)
330 INT WINAPI
MessageBoxExW( HWND hWnd
, LPCWSTR text
, LPCWSTR title
,
331 UINT type
, WORD langid
)
333 WARN("Messagebox\n");
334 /* ignore language id for now */
335 return MessageBoxW(hWnd
,text
,title
,type
);
338 /**************************************************************************
339 * MessageBoxIndirect16 (USER.827)
341 INT16 WINAPI
MessageBoxIndirect16( LPMSGBOXPARAMS16 msgbox
)
345 MSGBOXPARAMSA msgbox32
;
347 WARN("Messagebox\n");
349 if(!(hRes
= FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA
)))
351 if(!(template = (LPVOID
)LoadResource(GetModuleHandleA("USER32"), hRes
)))
354 msgbox32
.cbSize
= msgbox
->cbSize
;
355 msgbox32
.hwndOwner
= msgbox
->hwndOwner
;
356 msgbox32
.hInstance
= msgbox
->hInstance
;
357 msgbox32
.lpszText
= PTR_SEG_TO_LIN(msgbox
->lpszText
);
358 msgbox32
.lpszCaption
= PTR_SEG_TO_LIN(msgbox
->lpszCaption
);
359 msgbox32
.dwStyle
= msgbox
->dwStyle
;
360 msgbox32
.lpszIcon
= PTR_SEG_TO_LIN(msgbox
->lpszIcon
);
361 msgbox32
.dwContextHelpId
= msgbox
->dwContextHelpId
;
362 msgbox32
.lpfnMsgBoxCallback
= msgbox
->lpfnMsgBoxCallback
;
363 msgbox32
.dwLanguageId
= msgbox
->dwLanguageId
;
365 return DialogBoxIndirectParamA( msgbox32
.hInstance
, template,
366 msgbox32
.hwndOwner
, (DLGPROC
)MSGBOX_DlgProc
,
370 /**************************************************************************
371 * MessageBoxIndirectA (USER32.394)
373 INT WINAPI
MessageBoxIndirectA( LPMSGBOXPARAMSA msgbox
)
378 WARN("Messagebox\n");
380 if(!(hRes
= FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA
)))
382 if(!(template = (LPVOID
)LoadResource(GetModuleHandleA("USER32"), hRes
)))
385 return DialogBoxIndirectParamA( msgbox
->hInstance
, template,
386 msgbox
->hwndOwner
, (DLGPROC
)MSGBOX_DlgProc
,
390 /**************************************************************************
391 * MessageBoxIndirectW (USER32.395)
393 INT WINAPI
MessageBoxIndirectW( LPMSGBOXPARAMSW msgbox
)
395 MSGBOXPARAMSA msgboxa
;
396 WARN("Messagebox\n");
398 memcpy(&msgboxa
,msgbox
,sizeof(msgboxa
));
399 if (msgbox
->lpszCaption
)
400 lstrcpyWtoA((LPSTR
)msgboxa
.lpszCaption
,msgbox
->lpszCaption
);
401 if (msgbox
->lpszText
)
402 lstrcpyWtoA((LPSTR
)msgboxa
.lpszText
,msgbox
->lpszText
);
404 return MessageBoxIndirectA(&msgboxa
);