Owen Wang
[wine.git] / windows / defdlg.c
blobe00dec68a8183fc50c1871a8221234e3f2818762
1 /*
2 * Default dialog procedure
4 * Copyright 1993, 1996 Alexandre Julliard
6 */
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "wine/winuser16.h"
12 #include "dialog.h"
13 #include "win.h"
14 #include "winproc.h"
17 /***********************************************************************
18 * DEFDLG_SetFocus
20 * Set the focus to a control of the dialog, selecting the text if
21 * the control is an edit dialog.
23 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
25 HWND hwndPrev = GetFocus();
27 if (IsChild( hwndDlg, hwndPrev ))
29 if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
30 SendMessage16( hwndPrev, EM_SETSEL16, TRUE, MAKELONG( -1, 0 ) );
32 if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
33 SendMessage16( hwndCtrl, EM_SETSEL16, FALSE, MAKELONG( 0, -1 ) );
34 SetFocus( hwndCtrl );
38 /***********************************************************************
39 * DEFDLG_SaveFocus
41 static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
43 HWND hwndFocus = GetFocus();
45 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
46 infoPtr->hwndFocus = hwndFocus;
47 /* Remove default button */
48 return TRUE;
52 /***********************************************************************
53 * DEFDLG_RestoreFocus
55 static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
57 if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
58 if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
60 /* Don't set the focus back to controls if EndDialog is already called.*/
61 if (!(infoPtr->flags & DF_END))
62 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
64 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
65 sometimes losing focus when receiving WM_SETFOCUS messages. */
66 return TRUE;
70 /***********************************************************************
71 * DEFDLG_FindDefButton
73 * Find the current default push-button.
75 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
77 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
78 while (hwndChild)
80 if (SendMessage16( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
81 break;
82 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
84 return hwndChild;
88 /***********************************************************************
89 * DEFDLG_SetDefButton
91 * Set the new default button to be hwndNew.
93 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
94 HWND hwndNew )
96 if (hwndNew &&
97 !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
98 return FALSE; /* Destination is not a push button */
100 if (dlgInfo->idResult) /* There's already a default pushbutton */
102 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
103 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
104 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
106 if (hwndNew)
108 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
109 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
111 else dlgInfo->idResult = 0;
112 return TRUE;
116 /***********************************************************************
117 * DEFDLG_Proc
119 * Implementation of DefDlgProc(). Only handle messages that need special
120 * handling for dialogs.
122 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
123 LPARAM lParam, DIALOGINFO *dlgInfo )
125 switch(msg)
127 case WM_ERASEBKGND:
128 FillWindow16( hwnd, hwnd, (HDC16)wParam, (HBRUSH16)CTLCOLOR_DLG );
129 return 1;
131 case WM_NCDESTROY:
133 /* Free dialog heap (if created) */
134 if (dlgInfo->hDialogHeap)
136 GlobalUnlock16(dlgInfo->hDialogHeap);
137 GlobalFree16(dlgInfo->hDialogHeap);
138 dlgInfo->hDialogHeap = 0;
141 /* Delete font */
142 if (dlgInfo->hUserFont)
144 DeleteObject( dlgInfo->hUserFont );
145 dlgInfo->hUserFont = 0;
148 /* Delete menu */
149 if (dlgInfo->hMenu)
151 DestroyMenu( dlgInfo->hMenu );
152 dlgInfo->hMenu = 0;
155 /* Delete window procedure */
156 WINPROC_FreeProc( dlgInfo->dlgProc, WIN_PROC_WINDOW );
157 dlgInfo->dlgProc = (HWINDOWPROC)0;
158 dlgInfo->flags |= DF_END; /* just in case */
160 /* Window clean-up */
161 return DefWindowProcA( hwnd, msg, wParam, lParam );
163 case WM_SHOWWINDOW:
164 if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
165 return DefWindowProcA( hwnd, msg, wParam, lParam );
167 case WM_ACTIVATE:
168 if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
169 else DEFDLG_SaveFocus( hwnd, dlgInfo );
170 return 0;
172 case WM_SETFOCUS:
173 DEFDLG_RestoreFocus( hwnd, dlgInfo );
174 return 0;
176 case DM_SETDEFID:
177 if (dlgInfo->flags & DF_END) return 1;
178 DEFDLG_SetDefButton( hwnd, dlgInfo,
179 wParam ? GetDlgItem( hwnd, wParam ) : 0 );
180 return 1;
182 case DM_GETDEFID:
184 HWND hwndDefId;
185 if (dlgInfo->flags & DF_END) return 0;
186 if (dlgInfo->idResult)
187 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
188 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
189 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
191 return 0;
193 case WM_NEXTDLGCTL:
195 HWND hwndDest = (HWND)wParam;
196 if (!lParam)
197 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
198 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
199 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
201 return 0;
203 case WM_ENTERMENULOOP:
204 case WM_LBUTTONDOWN:
205 case WM_NCLBUTTONDOWN:
207 HWND hwndFocus = GetFocus();
208 if (hwndFocus)
210 WND *wnd = WIN_FindWndPtr( hwndFocus );
212 if( wnd )
214 /* always make combo box hide its listbox control */
216 if( WIDGETS_IsControl( wnd, BIC32_COMBO ) )
217 SendMessageA( hwndFocus, CB_SHOWDROPDOWN,
218 FALSE, 0 );
219 else if( WIDGETS_IsControl( wnd, BIC32_EDIT ) &&
220 WIDGETS_IsControl( wnd->parent,
221 BIC32_COMBO ))
222 SendMessageA( wnd->parent->hwndSelf,
223 CB_SHOWDROPDOWN, FALSE, 0 );
225 WIN_ReleaseWndPtr(wnd);
228 return DefWindowProcA( hwnd, msg, wParam, lParam );
230 case WM_GETFONT:
231 return dlgInfo->hUserFont;
233 case WM_CLOSE:
234 PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
235 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
236 return 0;
238 case WM_NOTIFYFORMAT:
239 return DefWindowProcA( hwnd, msg, wParam, lParam );
241 return 0;
244 /***********************************************************************
245 * DEFDLG_Epilog
247 static LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT msg, BOOL fResult)
249 /* see SDK 3.1 */
251 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
252 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
253 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
254 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
255 return fResult;
257 return dlgInfo->msgResult;
260 /***********************************************************************
261 * DefDlgProc16 (USER.308)
263 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
264 LPARAM lParam )
266 DIALOGINFO * dlgInfo;
267 BOOL result = FALSE;
268 WND * wndPtr = WIN_FindWndPtr( hwnd );
270 if (!wndPtr) return 0;
271 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
272 dlgInfo->msgResult = 0;
274 if (dlgInfo->dlgProc) { /* Call dialog procedure */
275 result = CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
276 hwnd, msg, wParam, lParam );
277 /* 16 bit dlg procs only return BOOL16 */
278 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
279 result = LOWORD(result);
282 if (!result && IsWindow(hwnd))
284 /* callback didn't process this message */
286 switch(msg)
288 case WM_ERASEBKGND:
289 case WM_SHOWWINDOW:
290 case WM_ACTIVATE:
291 case WM_SETFOCUS:
292 case DM_SETDEFID:
293 case DM_GETDEFID:
294 case WM_NEXTDLGCTL:
295 case WM_GETFONT:
296 case WM_CLOSE:
297 case WM_NCDESTROY:
298 case WM_ENTERMENULOOP:
299 case WM_LBUTTONDOWN:
300 case WM_NCLBUTTONDOWN:
301 WIN_ReleaseWndPtr(wndPtr);
302 return DEFDLG_Proc( (HWND)hwnd, msg,
303 (WPARAM)wParam, lParam, dlgInfo );
304 case WM_INITDIALOG:
305 case WM_VKEYTOITEM:
306 case WM_COMPAREITEM:
307 case WM_CHARTOITEM:
308 break;
310 default:
311 WIN_ReleaseWndPtr(wndPtr);
312 return DefWindowProc16( hwnd, msg, wParam, lParam );
315 WIN_ReleaseWndPtr(wndPtr);
316 return DEFDLG_Epilog(dlgInfo, msg, result);
320 /***********************************************************************
321 * DefDlgProcA (USER32.120)
323 LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg,
324 WPARAM wParam, LPARAM lParam )
326 DIALOGINFO * dlgInfo;
327 BOOL result = FALSE;
328 WND * wndPtr = WIN_FindWndPtr( hwnd );
330 if (!wndPtr) return 0;
331 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
332 dlgInfo->msgResult = 0;
334 if (dlgInfo->dlgProc) { /* Call dialog procedure */
335 result = CallWindowProcA( (WNDPROC)dlgInfo->dlgProc,
336 hwnd, msg, wParam, lParam );
337 /* 16 bit dlg procs only return BOOL16 */
338 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
339 result = LOWORD(result);
342 if (!result && IsWindow(hwnd))
344 /* callback didn't process this message */
346 switch(msg)
348 case WM_ERASEBKGND:
349 case WM_SHOWWINDOW:
350 case WM_ACTIVATE:
351 case WM_SETFOCUS:
352 case DM_SETDEFID:
353 case DM_GETDEFID:
354 case WM_NEXTDLGCTL:
355 case WM_GETFONT:
356 case WM_CLOSE:
357 case WM_NCDESTROY:
358 case WM_ENTERMENULOOP:
359 case WM_LBUTTONDOWN:
360 case WM_NCLBUTTONDOWN:
361 WIN_ReleaseWndPtr(wndPtr);
362 return DEFDLG_Proc( (HWND)hwnd, msg,
363 (WPARAM)wParam, lParam, dlgInfo );
364 case WM_INITDIALOG:
365 case WM_VKEYTOITEM:
366 case WM_COMPAREITEM:
367 case WM_CHARTOITEM:
368 break;
370 default:
371 WIN_ReleaseWndPtr(wndPtr);
372 return DefWindowProcA( hwnd, msg, wParam, lParam );
375 WIN_ReleaseWndPtr(wndPtr);
376 return DEFDLG_Epilog(dlgInfo, msg, result);
380 /***********************************************************************
381 * DefDlgProcW (USER32.121)
383 LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam,
384 LPARAM lParam )
386 DIALOGINFO * dlgInfo;
387 BOOL result = FALSE;
388 WND * wndPtr = WIN_FindWndPtr( hwnd );
390 if (!wndPtr) return 0;
391 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
392 dlgInfo->msgResult = 0;
394 if (dlgInfo->dlgProc) { /* Call dialog procedure */
395 result = CallWindowProcW( (WNDPROC)dlgInfo->dlgProc,
396 hwnd, msg, wParam, lParam );
397 /* 16 bit dlg procs only return BOOL16 */
398 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
399 result = LOWORD(result);
402 if (!result && IsWindow(hwnd))
404 /* callback didn't process this message */
406 switch(msg)
408 case WM_ERASEBKGND:
409 case WM_SHOWWINDOW:
410 case WM_ACTIVATE:
411 case WM_SETFOCUS:
412 case DM_SETDEFID:
413 case DM_GETDEFID:
414 case WM_NEXTDLGCTL:
415 case WM_GETFONT:
416 case WM_CLOSE:
417 case WM_NCDESTROY:
418 case WM_ENTERMENULOOP:
419 case WM_LBUTTONDOWN:
420 case WM_NCLBUTTONDOWN:
421 WIN_ReleaseWndPtr(wndPtr);
422 return DEFDLG_Proc( (HWND)hwnd, msg,
423 (WPARAM)wParam, lParam, dlgInfo );
424 case WM_INITDIALOG:
425 case WM_VKEYTOITEM:
426 case WM_COMPAREITEM:
427 case WM_CHARTOITEM:
428 break;
430 default:
431 WIN_ReleaseWndPtr(wndPtr);
432 return DefWindowProcW( hwnd, msg, wParam, lParam );
435 WIN_ReleaseWndPtr(wndPtr);
436 return DEFDLG_Epilog(dlgInfo, msg, result);