blob: 618e3dfc1363af21f2f692037049999a0d8b1880 [file] [log] [blame]
Alexandre Julliard0e607781993-11-03 19:23:37 +00001/*
2 * Default dialog procedure
3 *
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00004 * Copyright 1993, 1996 Alexandre Julliard
Alexandre Julliard234bc241994-12-10 13:02:28 +00005 *
Alexandre Julliard59730ae1996-03-24 16:20:51 +00006 */
Alexandre Julliard0e607781993-11-03 19:23:37 +00007
8#include "windows.h"
9#include "dialog.h"
10#include "win.h"
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000011#include "winproc.h"
12
Alexandre Julliardaca05781994-10-17 18:12:41 +000013
Alexandre Julliardaca05781994-10-17 18:12:41 +000014/***********************************************************************
15 * DEFDLG_SetFocus
16 *
17 * Set the focus to a control of the dialog, selecting the text if
18 * the control is an edit dialog.
19 */
Alexandre Julliard139a4b11996-11-02 14:24:07 +000020static void DEFDLG_SetFocus( HWND32 hwndDlg, HWND32 hwndCtrl )
Alexandre Julliardaca05781994-10-17 18:12:41 +000021{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000022 HWND32 hwndPrev = GetFocus32();
Alexandre Julliardaca05781994-10-17 18:12:41 +000023
Alexandre Julliard01d63461997-01-20 19:43:45 +000024 if (IsChild32( hwndDlg, hwndPrev ))
Alexandre Julliardaca05781994-10-17 18:12:41 +000025 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000026 if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
Alexandre Julliardc6c09441997-01-12 18:32:19 +000027 SendMessage16( hwndPrev, EM_SETSEL16, TRUE, MAKELONG( -1, 0 ) );
Alexandre Julliardaca05781994-10-17 18:12:41 +000028 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +000029 if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
Alexandre Julliardc6c09441997-01-12 18:32:19 +000030 SendMessage16( hwndCtrl, EM_SETSEL16, FALSE, MAKELONG( 0, -1 ) );
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000031 SetFocus32( hwndCtrl );
Alexandre Julliardaca05781994-10-17 18:12:41 +000032}
33
34
35/***********************************************************************
36 * DEFDLG_SaveFocus
37 */
Alexandre Julliard139a4b11996-11-02 14:24:07 +000038static BOOL32 DEFDLG_SaveFocus( HWND32 hwnd, DIALOGINFO *infoPtr )
Alexandre Julliardaca05781994-10-17 18:12:41 +000039{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000040 HWND32 hwndFocus = GetFocus32();
Alexandre Julliardaca05781994-10-17 18:12:41 +000041
Alexandre Julliard01d63461997-01-20 19:43:45 +000042 if (!hwndFocus || !IsChild32( hwnd, hwndFocus )) return FALSE;
Alexandre Julliardaca05781994-10-17 18:12:41 +000043 infoPtr->hwndFocus = hwndFocus;
44 /* Remove default button */
45 return TRUE;
46}
47
48
49/***********************************************************************
50 * DEFDLG_RestoreFocus
51 */
Alexandre Julliard139a4b11996-11-02 14:24:07 +000052static BOOL32 DEFDLG_RestoreFocus( HWND32 hwnd, DIALOGINFO *infoPtr )
Alexandre Julliardaca05781994-10-17 18:12:41 +000053{
Alexandre Julliard01d63461997-01-20 19:43:45 +000054 if (!infoPtr->hwndFocus || IsIconic32(hwnd)) return FALSE;
Alexandre Julliard21979011997-03-05 08:22:35 +000055 if (!IsWindow32( infoPtr->hwndFocus )) return FALSE;
Alexandre Julliardaca05781994-10-17 18:12:41 +000056 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
57 infoPtr->hwndFocus = 0;
58 return TRUE;
59}
60
61
62/***********************************************************************
63 * DEFDLG_FindDefButton
64 *
65 * Find the current default push-button.
66 */
Alexandre Julliard139a4b11996-11-02 14:24:07 +000067static HWND32 DEFDLG_FindDefButton( HWND32 hwndDlg )
Alexandre Julliardaca05781994-10-17 18:12:41 +000068{
Alexandre Julliard01d63461997-01-20 19:43:45 +000069 HWND32 hwndChild = GetWindow32( hwndDlg, GW_CHILD );
Alexandre Julliardaca05781994-10-17 18:12:41 +000070 while (hwndChild)
71 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000072 if (SendMessage16( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
Alexandre Julliardaca05781994-10-17 18:12:41 +000073 break;
Alexandre Julliard01d63461997-01-20 19:43:45 +000074 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
Alexandre Julliardaca05781994-10-17 18:12:41 +000075 }
76 return hwndChild;
77}
78
79
80/***********************************************************************
81 * DEFDLG_SetDefButton
82 *
83 * Set the new default button to be hwndNew.
84 */
Alexandre Julliard139a4b11996-11-02 14:24:07 +000085static BOOL32 DEFDLG_SetDefButton( HWND32 hwndDlg, DIALOGINFO *dlgInfo,
86 HWND32 hwndNew )
Alexandre Julliardaca05781994-10-17 18:12:41 +000087{
88 if (hwndNew &&
Alexandre Julliard2d93d001996-05-21 15:01:41 +000089 !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
Alexandre Julliardaca05781994-10-17 18:12:41 +000090 return FALSE; /* Destination is not a push button */
91
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +000092 if (dlgInfo->idResult) /* There's already a default pushbutton */
Alexandre Julliardaca05781994-10-17 18:12:41 +000093 {
Alexandre Julliard01d63461997-01-20 19:43:45 +000094 HWND32 hwndOld = GetDlgItem32( hwndDlg, dlgInfo->idResult );
Alexandre Julliard2d93d001996-05-21 15:01:41 +000095 if (SendMessage32A( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
96 SendMessage32A( hwndOld, BM_SETSTYLE32, BS_PUSHBUTTON, TRUE );
Alexandre Julliardaca05781994-10-17 18:12:41 +000097 }
98 if (hwndNew)
99 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000100 SendMessage32A( hwndNew, BM_SETSTYLE32, BS_DEFPUSHBUTTON, TRUE );
Alexandre Julliard01d63461997-01-20 19:43:45 +0000101 dlgInfo->idResult = GetDlgCtrlID32( hwndNew );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000102 }
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000103 else dlgInfo->idResult = 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000104 return TRUE;
105}
Alexandre Julliard0e607781993-11-03 19:23:37 +0000106
107
108/***********************************************************************
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000109 * DEFDLG_Proc
110 *
111 * Implementation of DefDlgProc(). Only handle messages that need special
112 * handling for dialogs.
Alexandre Julliard0e607781993-11-03 19:23:37 +0000113 */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000114static LRESULT DEFDLG_Proc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
115 LPARAM lParam, DIALOGINFO *dlgInfo )
Alexandre Julliard0e607781993-11-03 19:23:37 +0000116{
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000117 HWND32 hwndDefId;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000118
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000119 switch(msg)
Alexandre Julliard0e607781993-11-03 19:23:37 +0000120 {
Alexandre Julliard0e607781993-11-03 19:23:37 +0000121 case WM_ERASEBKGND:
Alexandre Julliard530ee841996-10-23 16:59:13 +0000122 FillWindow( hwnd, hwnd, (HDC16)wParam, (HBRUSH16)CTLCOLOR_DLG );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000123 return 1;
Alexandre Julliard0e607781993-11-03 19:23:37 +0000124
125 case WM_NCDESTROY:
126
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000127 /* Free dialog heap (if created) */
128 if (dlgInfo->hDialogHeap)
129 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000130 GlobalUnlock16(dlgInfo->hDialogHeap);
131 GlobalFree16(dlgInfo->hDialogHeap);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000132 dlgInfo->hDialogHeap = 0;
133 }
134
Alexandre Julliard0e607781993-11-03 19:23:37 +0000135 /* Delete font */
136 if (dlgInfo->hUserFont)
137 {
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000138 DeleteObject32( dlgInfo->hUserFont );
Alexandre Julliard0e607781993-11-03 19:23:37 +0000139 dlgInfo->hUserFont = 0;
140 }
141
142 /* Delete menu */
143 if (dlgInfo->hMenu)
144 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000145 DestroyMenu32( dlgInfo->hMenu );
Alexandre Julliard0e607781993-11-03 19:23:37 +0000146 dlgInfo->hMenu = 0;
147 }
148
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000149 /* Delete window procedure */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000150 WINPROC_FreeProc( dlgInfo->dlgProc );
151 dlgInfo->dlgProc = (HWINDOWPROC)0;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000152 dlgInfo->fEnd = TRUE; /* just in case */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000153
Alexandre Julliard0e607781993-11-03 19:23:37 +0000154 /* Window clean-up */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000155 return DefWindowProc32A( hwnd, msg, wParam, lParam );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000156
157 case WM_SHOWWINDOW:
158 if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000159 return DefWindowProc32A( hwnd, msg, wParam, lParam );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000160
161 case WM_ACTIVATE:
162 if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
163 else DEFDLG_SaveFocus( hwnd, dlgInfo );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000164 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000165
166 case WM_SETFOCUS:
167 DEFDLG_RestoreFocus( hwnd, dlgInfo );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000168 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000169
170 case DM_SETDEFID:
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000171 if (dlgInfo->fEnd) return 1;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000172 DEFDLG_SetDefButton( hwnd, dlgInfo,
Alexandre Julliard01d63461997-01-20 19:43:45 +0000173 wParam ? GetDlgItem32( hwnd, wParam ) : 0 );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000174 return 1;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000175
176 case DM_GETDEFID:
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000177 if (dlgInfo->fEnd) return 0;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000178 if (dlgInfo->idResult)
179 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000180 hwndDefId = DEFDLG_FindDefButton( hwnd );
181 if (hwndDefId)
Alexandre Julliard01d63461997-01-20 19:43:45 +0000182 return MAKELONG( GetDlgCtrlID32( hwndDefId ), DC_HASDEFID);
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000183 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000184
185 case WM_NEXTDLGCTL:
186 {
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000187 HWND32 hwndDest = (HWND32)wParam;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000188 if (!lParam)
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000189 hwndDest = GetNextDlgTabItem32(hwnd, GetFocus32(), wParam);
Alexandre Julliardaca05781994-10-17 18:12:41 +0000190 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
191 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
192 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000193 return 0;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000194
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000195 case WM_GETFONT:
196 return dlgInfo->hUserFont;
197
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000198 case WM_CLOSE:
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000199 EndDialog32( hwnd, TRUE );
Alexandre Julliard01d63461997-01-20 19:43:45 +0000200 DestroyWindow32( hwnd );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000201 return 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000202 }
203 return 0;
204}
205
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000206/***********************************************************************
207 * DEFDLG_Signoff
208 */
209static LRESULT DEFDLG_Signoff(DIALOGINFO* dlgInfo, UINT32 msg, BOOL16 fResult)
210{
211 /* see SDK 3.1 */
212
213 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
214 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
215 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
216 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
217 return fResult;
218
219 return dlgInfo->msgResult;
220}
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000221
222/***********************************************************************
223 * DefDlgProc16 (USER.308)
224 */
225LRESULT DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
226{
227 DIALOGINFO * dlgInfo;
228 BOOL16 result = FALSE;
229 WND * wndPtr = WIN_FindWndPtr( hwnd );
230
231 if (!wndPtr) return 0;
232 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000233 dlgInfo->msgResult = 0;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000234
235 if (dlgInfo->dlgProc) /* Call dialog procedure */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000236 result = (BOOL16)CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
237 hwnd, msg, wParam, lParam );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000238
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000239 /* Check if window was destroyed by dialog procedure */
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000240
Alexandre Julliard21979011997-03-05 08:22:35 +0000241 if (!result && IsWindow32(hwnd))
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000242 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000243 /* callback didn't process this message */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000244
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000245 switch(msg)
246 {
247 case WM_ERASEBKGND:
248 case WM_SHOWWINDOW:
249 case WM_ACTIVATE:
250 case WM_SETFOCUS:
251 case DM_SETDEFID:
252 case DM_GETDEFID:
253 case WM_NEXTDLGCTL:
254 case WM_GETFONT:
255 case WM_CLOSE:
256 case WM_NCDESTROY:
257 return DEFDLG_Proc( (HWND32)hwnd, msg,
258 (WPARAM32)wParam, lParam, dlgInfo );
259 case WM_INITDIALOG:
260 case WM_VKEYTOITEM:
261 case WM_COMPAREITEM:
262 case WM_CHARTOITEM:
263 break;
264
265 default:
266 return DefWindowProc16( hwnd, msg, wParam, lParam );
267 }
268 }
269 return DEFDLG_Signoff(dlgInfo, msg, result);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000270}
271
272
273/***********************************************************************
274 * DefDlgProc32A (USER32.119)
275 */
276LRESULT DefDlgProc32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
277{
278 DIALOGINFO * dlgInfo;
279 BOOL16 result = FALSE;
280 WND * wndPtr = WIN_FindWndPtr( hwnd );
281
282 if (!wndPtr) return 0;
283 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000284 dlgInfo->msgResult = 0;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000285
286 if (dlgInfo->dlgProc) /* Call dialog procedure */
287 result = (BOOL16)CallWindowProc32A( (WNDPROC32)dlgInfo->dlgProc,
Alexandre Julliard3051b641996-07-05 17:14:13 +0000288 hwnd, msg, wParam, lParam );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000289
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000290 /* Check if window was destroyed by dialog procedure */
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000291
Alexandre Julliard21979011997-03-05 08:22:35 +0000292 if (!result && IsWindow32(hwnd))
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000293 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000294 /* callback didn't process this message */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000295
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000296 switch(msg)
297 {
298 case WM_ERASEBKGND:
299 case WM_SHOWWINDOW:
300 case WM_ACTIVATE:
301 case WM_SETFOCUS:
302 case DM_SETDEFID:
303 case DM_GETDEFID:
304 case WM_NEXTDLGCTL:
305 case WM_GETFONT:
306 case WM_CLOSE:
307 case WM_NCDESTROY:
308 return DEFDLG_Proc( (HWND32)hwnd, msg,
309 (WPARAM32)wParam, lParam, dlgInfo );
310 case WM_INITDIALOG:
311 case WM_VKEYTOITEM:
312 case WM_COMPAREITEM:
313 case WM_CHARTOITEM:
314 break;
315
316 default:
317 return DefWindowProc32A( hwnd, msg, wParam, lParam );
318 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000319 }
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000320 return DEFDLG_Signoff(dlgInfo, msg, result);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000321}
322
323
324/***********************************************************************
325 * DefDlgProc32W (USER32.120)
326 */
327LRESULT DefDlgProc32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
328{
329 DIALOGINFO * dlgInfo;
330 BOOL16 result = FALSE;
331 WND * wndPtr = WIN_FindWndPtr( hwnd );
332
333 if (!wndPtr) return 0;
334 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000335 dlgInfo->msgResult = 0;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000336
337 if (dlgInfo->dlgProc) /* Call dialog procedure */
338 result = (BOOL16)CallWindowProc32W( (WNDPROC32)dlgInfo->dlgProc,
Alexandre Julliard3051b641996-07-05 17:14:13 +0000339 hwnd, msg, wParam, lParam );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000340
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000341 /* Check if window was destroyed by dialog procedure */
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000342
Alexandre Julliard21979011997-03-05 08:22:35 +0000343 if (!result && IsWindow32(hwnd))
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000344 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000345 /* callback didn't process this message */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000346
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000347 switch(msg)
348 {
349 case WM_ERASEBKGND:
350 case WM_SHOWWINDOW:
351 case WM_ACTIVATE:
352 case WM_SETFOCUS:
353 case DM_SETDEFID:
354 case DM_GETDEFID:
355 case WM_NEXTDLGCTL:
356 case WM_GETFONT:
357 case WM_CLOSE:
358 case WM_NCDESTROY:
359 return DEFDLG_Proc( (HWND32)hwnd, msg,
360 (WPARAM32)wParam, lParam, dlgInfo );
361 case WM_INITDIALOG:
362 case WM_VKEYTOITEM:
363 case WM_COMPAREITEM:
364 case WM_CHARTOITEM:
365 break;
366
367 default:
368 return DefWindowProc32W( hwnd, msg, wParam, lParam );
369 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000370 }
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000371 return DEFDLG_Signoff(dlgInfo, msg, result);
Alexandre Julliard0e607781993-11-03 19:23:37 +0000372}