4 * Copyright 1995 Bernd Schmidt
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/winbase16.h"
26 #include "wine/winuser16.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dialog
);
34 #define MSGBOX_IDICON 1088
35 #define MSGBOX_IDTEXT 100
37 static HFONT
MSGBOX_OnInit(HWND hwnd
, LPMSGBOXPARAMSA lpmb
)
39 static HFONT hFont
= 0, hPrevFont
= 0;
44 int bspace
, bw
, bh
, theight
, tleft
, wwidth
, wheight
, bpos
;
45 int borheight
, borwidth
, iheight
, ileft
, iwidth
, twidth
, tiheight
;
49 if (TWEAK_WineLook
>= WIN95_LOOK
) {
50 NONCLIENTMETRICSA nclm
;
51 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
52 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
53 hFont
= CreateFontIndirectA (&nclm
.lfMessageFont
);
56 SendDlgItemMessageA (hwnd
, i
, WM_SETFONT
, (WPARAM
)hFont
, 0);
58 SendDlgItemMessageA (hwnd
, MSGBOX_IDTEXT
, WM_SETFONT
, (WPARAM
)hFont
, 0);
60 if (HIWORD(lpmb
->lpszCaption
)) {
61 SetWindowTextA(hwnd
, lpmb
->lpszCaption
);
63 if (LoadStringA(lpmb
->hInstance
, LOWORD(lpmb
->lpszCaption
), buf
, sizeof(buf
)))
64 SetWindowTextA(hwnd
, buf
);
66 if (HIWORD(lpmb
->lpszText
)) {
67 lpszText
= lpmb
->lpszText
;
70 if (!LoadStringA(lpmb
->hInstance
, LOWORD(lpmb
->lpszText
), buf
, sizeof(buf
)))
71 *buf
= 0; /* FIXME ?? */
73 SetWindowTextA(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), lpszText
);
75 /* Hide not selected buttons */
76 switch(lpmb
->dwStyle
& MB_TYPEMASK
) {
78 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
81 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
82 ShowWindow(GetDlgItem(hwnd
, IDRETRY
), SW_HIDE
);
83 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
84 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
85 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
87 case MB_ABORTRETRYIGNORE
:
88 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
89 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
90 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
91 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
94 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), SW_HIDE
);
97 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
98 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
99 ShowWindow(GetDlgItem(hwnd
, IDRETRY
), SW_HIDE
);
100 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
103 ShowWindow(GetDlgItem(hwnd
, IDOK
), SW_HIDE
);
104 ShowWindow(GetDlgItem(hwnd
, IDABORT
), SW_HIDE
);
105 ShowWindow(GetDlgItem(hwnd
, IDIGNORE
), SW_HIDE
);
106 ShowWindow(GetDlgItem(hwnd
, IDYES
), SW_HIDE
);
107 ShowWindow(GetDlgItem(hwnd
, IDNO
), SW_HIDE
);
111 switch(lpmb
->dwStyle
& MB_ICONMASK
) {
112 case MB_ICONEXCLAMATION
:
113 SendDlgItemMessageA(hwnd
, stc1
, STM_SETICON
,
114 (WPARAM
)LoadIconA(0, IDI_EXCLAMATIONA
), 0);
116 case MB_ICONQUESTION
:
117 SendDlgItemMessageA(hwnd
, stc1
, STM_SETICON
,
118 (WPARAM
)LoadIconA(0, IDI_QUESTIONA
), 0);
120 case MB_ICONASTERISK
:
121 SendDlgItemMessageA(hwnd
, stc1
, STM_SETICON
,
122 (WPARAM
)LoadIconA(0, IDI_ASTERISKA
), 0);
125 SendDlgItemMessageA(hwnd
, stc1
, STM_SETICON
,
126 (WPARAM
)LoadIconA(0, IDI_HANDA
), 0);
129 /* By default, Windows 95/98/NT do not associate an icon to message boxes.
130 * So wine should do the same.
135 /* Position everything */
136 GetWindowRect(hwnd
, &rect
);
137 borheight
= rect
.bottom
- rect
.top
;
138 borwidth
= rect
.right
- rect
.left
;
139 GetClientRect(hwnd
, &rect
);
140 borheight
-= rect
.bottom
- rect
.top
;
141 borwidth
-= rect
.right
- rect
.left
;
143 /* Get the icon height */
144 GetWindowRect(GetDlgItem(hwnd
, MSGBOX_IDICON
), &rect
);
145 MapWindowPoints(0, hwnd
, (LPPOINT
)&rect
, 2);
146 iheight
= rect
.bottom
- rect
.top
;
148 iwidth
= rect
.right
- ileft
;
152 hPrevFont
= SelectObject(hdc
, hFont
);
154 /* Get the number of visible buttons and their size */
155 bh
= bw
= 1; /* Minimum button sizes */
156 for (buttons
= 0, i
= 1; i
< 8; i
++)
158 hItem
= GetDlgItem(hwnd
, i
);
159 if (GetWindowLongA(hItem
, GWL_STYLE
) & WS_VISIBLE
)
161 char buttonText
[1024];
164 if (GetWindowTextA(hItem
, buttonText
, sizeof buttonText
))
166 DrawTextA( hdc
, buttonText
, -1, &rect
, DT_LEFT
| DT_EXPANDTABS
| DT_CALCRECT
);
167 h
= rect
.bottom
- rect
.top
;
168 w
= rect
.right
- rect
.left
;
174 bw
= max(bw
, bh
* 2);
175 /* Button white space */
178 bspace
= bw
/3; /* Space between buttons */
180 /* Get the text size */
181 GetClientRect(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), &rect
);
182 rect
.top
= rect
.left
= rect
.bottom
= 0;
183 DrawTextA( hdc
, lpszText
, -1, &rect
,
184 DT_LEFT
| DT_EXPANDTABS
| DT_WORDBREAK
| DT_CALCRECT
);
185 /* Min text width corresponds to space for the buttons */
186 tleft
= 2 * ileft
+ iwidth
;
187 twidth
= max((bw
+ bspace
) * buttons
+ bspace
- tleft
, rect
.right
);
188 theight
= rect
.bottom
;
191 SelectObject(hdc
, hPrevFont
);
192 ReleaseDC(hItem
, hdc
);
194 tiheight
= 16 + max(iheight
, theight
);
195 wwidth
= tleft
+ twidth
+ ileft
+ borwidth
;
196 wheight
= 8 + tiheight
+ bh
+ borheight
;
198 /* Resize the window */
199 SetWindowPos(hwnd
, 0, 0, 0, wwidth
, wheight
,
200 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
202 /* Position the icon */
203 SetWindowPos(GetDlgItem(hwnd
, MSGBOX_IDICON
), 0, ileft
, (tiheight
- iheight
) / 2, 0, 0,
204 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
206 /* Position the text */
207 SetWindowPos(GetDlgItem(hwnd
, MSGBOX_IDTEXT
), 0, tleft
, (tiheight
- theight
) / 2, twidth
, theight
,
208 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
210 /* Position the buttons */
211 bpos
= (wwidth
- (bw
+ bspace
) * buttons
+ bspace
) / 2;
212 for (buttons
= i
= 0; i
< 7; i
++) {
213 /* some arithmetic to get the right order for YesNoCancel windows */
214 hItem
= GetDlgItem(hwnd
, (i
+ 5) % 7 + 1);
215 if (GetWindowLongA(hItem
, GWL_STYLE
) & WS_VISIBLE
) {
216 if (buttons
++ == ((lpmb
->dwStyle
& MB_DEFMASK
) >> 8)) {
218 SendMessageA( hItem
, BM_SETSTYLE
, BS_DEFPUSHBUTTON
, TRUE
);
220 SetWindowPos(hItem
, 0, bpos
, tiheight
, bw
, bh
,
221 SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOREDRAW
);
226 /* handle modal MessageBoxes */
227 if (lpmb
->dwStyle
& (MB_TASKMODAL
|MB_SYSTEMMODAL
))
229 FIXME("%s modal msgbox ! Not modal yet.\n",
230 lpmb
->dwStyle
& MB_TASKMODAL
? "task" : "system");
231 /* Probably do EnumTaskWindows etc. here for TASKMODAL
232 * and work your way up to the top - I'm lazy (HWND_TOP) */
233 SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0,
234 SWP_NOSIZE
| SWP_NOMOVE
);
235 if (lpmb
->dwStyle
& MB_TASKMODAL
)
236 /* at least MB_TASKMODAL seems to imply a ShowWindow */
237 ShowWindow(hwnd
, SW_SHOW
);
239 if (lpmb
->dwStyle
& MB_APPLMODAL
)
240 FIXME("app modal msgbox ! Not modal yet.\n");
246 /**************************************************************************
249 * Dialog procedure for message boxes.
251 static LRESULT CALLBACK
MSGBOX_DlgProc( HWND hwnd
, UINT message
,
252 WPARAM wParam
, LPARAM lParam
)
257 hFont
= MSGBOX_OnInit(hwnd
, (LPMSGBOXPARAMSA
)lParam
);
270 EndDialog(hwnd
, wParam
);
277 /* Ok. Ignore all the other messages */
278 TRACE("Message number 0x%04x is being ignored.\n", message
);
285 /**************************************************************************
286 * MessageBoxA (USER32.@)
289 * The WARN is here to help debug erroneous MessageBoxes
290 * Use: -debugmsg warn+dialog,+relay
292 INT WINAPI
MessageBoxA(HWND hWnd
, LPCSTR text
, LPCSTR title
, UINT type
)
298 WARN("Messagebox\n");
300 if(!(hRes
= FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA
)))
302 if(!(template = (LPVOID
)LoadResource(GetModuleHandleA("USER32"), hRes
)))
305 if (!text
) text
="<WINE-NULL>";
308 mbox
.lpszCaption
= title
;
309 mbox
.lpszText
= text
;
311 return DialogBoxIndirectParamA( GetWindowLongA(hWnd
,GWL_HINSTANCE
), template,
312 hWnd
, (DLGPROC
)MSGBOX_DlgProc
, (LPARAM
)&mbox
);
316 /**************************************************************************
317 * MessageBoxW (USER32.@)
319 INT WINAPI
MessageBoxW( HWND hwnd
, LPCWSTR text
, LPCWSTR title
,
322 LPSTR titleA
= HEAP_strdupWtoA( GetProcessHeap(), 0, title
);
323 LPSTR textA
= HEAP_strdupWtoA( GetProcessHeap(), 0, text
);
326 WARN("Messagebox\n");
328 ret
= MessageBoxA( hwnd
, textA
, titleA
, type
);
329 HeapFree( GetProcessHeap(), 0, titleA
);
330 HeapFree( GetProcessHeap(), 0, textA
);
335 /**************************************************************************
336 * MessageBoxExA (USER32.@)
338 INT WINAPI
MessageBoxExA( HWND hWnd
, LPCSTR text
, LPCSTR title
,
339 UINT type
, WORD langid
)
341 WARN("Messagebox\n");
342 /* ignore language id for now */
343 return MessageBoxA(hWnd
,text
,title
,type
);
346 /**************************************************************************
347 * MessageBoxExW (USER32.@)
349 INT WINAPI
MessageBoxExW( HWND hWnd
, LPCWSTR text
, LPCWSTR title
,
350 UINT type
, WORD langid
)
352 WARN("Messagebox\n");
353 /* ignore language id for now */
354 return MessageBoxW(hWnd
,text
,title
,type
);
357 /**************************************************************************
358 * MessageBoxIndirectA (USER32.@)
360 INT WINAPI
MessageBoxIndirectA( LPMSGBOXPARAMSA msgbox
)
365 WARN("Messagebox\n");
367 if(!(hRes
= FindResourceA(GetModuleHandleA("USER32"), "MSGBOX", RT_DIALOGA
)))
369 if(!(template = (LPVOID
)LoadResource(GetModuleHandleA("USER32"), hRes
)))
372 return DialogBoxIndirectParamA( msgbox
->hInstance
, template,
373 msgbox
->hwndOwner
, (DLGPROC
)MSGBOX_DlgProc
,
377 /**************************************************************************
378 * MessageBoxIndirectW (USER32.@)
380 INT WINAPI
MessageBoxIndirectW( LPMSGBOXPARAMSW msgbox
)
382 MSGBOXPARAMSA msgboxa
;
383 memcpy(&msgboxa
,msgbox
,sizeof(msgboxa
));
384 msgboxa
.lpszCaption
= HEAP_strdupWtoA( GetProcessHeap(), 0, msgbox
->lpszCaption
);
385 msgboxa
.lpszText
= HEAP_strdupWtoA( GetProcessHeap(), 0, msgbox
->lpszText
);
386 msgboxa
.lpszIcon
= HEAP_strdupWtoA( GetProcessHeap(), 0, msgbox
->lpszIcon
);
387 return MessageBoxIndirectA(&msgboxa
);