2 * Default dialog procedure
4 * Copyright 1993, 1996 Alexandre Julliard
11 #include "wine/winuser16.h"
15 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(dialog);
20 /***********************************************************************
23 static WNDPROC DEFDLG_GetDlgProc( HWND hwnd )
26 WND *wndPtr = WIN_GetPtr( hwnd );
28 if (!wndPtr) return 0;
29 if (wndPtr == WND_OTHER_PROCESS)
31 ERR( "cannot get dlg proc %x from other process\n", hwnd );
34 ret = *(WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
35 WIN_ReleasePtr( wndPtr );
39 /***********************************************************************
42 * Set the focus to a control of the dialog, selecting the text if
43 * the control is an edit dialog.
45 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
47 HWND hwndPrev = GetFocus();
49 if (IsChild( hwndDlg, hwndPrev ))
51 if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
52 SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
54 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
55 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
60 /***********************************************************************
63 static void DEFDLG_SaveFocus( HWND hwnd )
66 HWND hwndFocus = GetFocus();
68 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
69 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
70 infoPtr->hwndFocus = hwndFocus;
71 /* Remove default button */
75 /***********************************************************************
78 static void DEFDLG_RestoreFocus( HWND hwnd )
82 if (IsIconic( hwnd )) return;
83 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
84 if (!IsWindow( infoPtr->hwndFocus )) return;
85 /* Don't set the focus back to controls if EndDialog is already called.*/
86 if (!(infoPtr->flags & DF_END))
88 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
91 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
92 sometimes losing focus when receiving WM_SETFOCUS messages. */
96 /***********************************************************************
97 * DEFDLG_FindDefButton
99 * Find the current default push-button.
101 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
103 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
106 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
108 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
114 /***********************************************************************
115 * DEFDLG_SetDefButton
117 * Set the new default button to be hwndNew.
119 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
122 DWORD dlgcode=0; /* initialize just to avoid a warning */
124 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
125 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
126 return FALSE; /* Destination is not a push button */
128 if (dlgInfo->idResult) /* There's already a default pushbutton */
130 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
131 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
132 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
136 if(dlgcode==DLGC_UNDEFPUSHBUTTON)
137 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
138 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
140 else dlgInfo->idResult = 0;
145 /***********************************************************************
148 * Implementation of DefDlgProc(). Only handle messages that need special
149 * handling for dialogs.
151 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
152 LPARAM lParam, DIALOGINFO *dlgInfo )
158 HBRUSH brush = SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
159 if (!brush) brush = DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
163 HDC hdc = (HDC)wParam;
164 GetClientRect( hwnd, &rect );
165 DPtoLP( hdc, (LPPOINT)&rect, 2 );
166 FillRect( hdc, &rect, brush );
171 if ((dlgInfo = (DIALOGINFO *)SetWindowLongW( hwnd, DWL_WINE_DIALOGINFO, 0 )))
173 /* Free dialog heap (if created) */
174 if (dlgInfo->hDialogHeap)
176 GlobalUnlock16(dlgInfo->hDialogHeap);
177 GlobalFree16(dlgInfo->hDialogHeap);
179 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
180 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
181 WINPROC_FreeProc( DEFDLG_GetDlgProc( hwnd ), WIN_PROC_WINDOW );
182 HeapFree( GetProcessHeap(), 0, dlgInfo );
184 /* Window clean-up */
185 return DefWindowProcA( hwnd, msg, wParam, lParam );
188 if (!wParam) DEFDLG_SaveFocus( hwnd );
189 return DefWindowProcA( hwnd, msg, wParam, lParam );
192 if (wParam) DEFDLG_RestoreFocus( hwnd );
193 else DEFDLG_SaveFocus( hwnd );
197 DEFDLG_RestoreFocus( hwnd );
201 if (dlgInfo->flags & DF_END) return 1;
202 DEFDLG_SetDefButton( hwnd, dlgInfo,
203 wParam ? GetDlgItem( hwnd, wParam ) : 0 );
209 if (dlgInfo->flags & DF_END) return 0;
210 if (dlgInfo->idResult)
211 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
212 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
213 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
219 HWND hwndDest = (HWND)wParam;
221 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
222 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
223 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
227 case WM_ENTERMENULOOP:
229 case WM_NCLBUTTONDOWN:
231 HWND hwndFocus = GetFocus();
234 /* always make combo box hide its listbox control */
235 if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
236 SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
239 return DefWindowProcA( hwnd, msg, wParam, lParam );
242 return dlgInfo->hUserFont;
245 PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
246 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
249 case WM_NOTIFYFORMAT:
250 return DefWindowProcA( hwnd, msg, wParam, lParam );
255 /***********************************************************************
258 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
262 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
263 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
264 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
265 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
268 return GetWindowLongA( hwnd, DWL_MSGRESULT );
271 /***********************************************************************
272 * DefDlgProc (USER.308)
274 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
278 HWND hwnd32 = WIN_Handle32( hwnd );
281 SetWindowLongW( hwnd32, DWL_MSGRESULT, 0 );
283 if ((dlgproc = (WNDPROC16)DEFDLG_GetDlgProc( hwnd32 )))
285 /* Call dialog procedure */
286 result = CallWindowProc16( dlgproc, hwnd, msg, wParam, lParam );
287 /* 16 bit dlg procs only return BOOL16 */
288 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
289 result = LOWORD(result);
292 if (!result && IsWindow(hwnd32))
294 /* callback didn't process this message */
308 case WM_ENTERMENULOOP:
310 case WM_NCLBUTTONDOWN:
311 return DEFDLG_Proc( hwnd32, msg, (WPARAM)wParam, lParam, DIALOG_get_info(hwnd32) );
319 return DefWindowProc16( hwnd, msg, wParam, lParam );
322 return DEFDLG_Epilog( hwnd32, msg, result);
326 /***********************************************************************
327 * DefDlgProcA (USER32.@)
329 LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
334 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
336 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
338 /* Call dialog procedure */
339 result = CallWindowProcA( dlgproc, hwnd, msg, wParam, lParam );
340 /* 16 bit dlg procs only return BOOL16 */
341 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
342 result = LOWORD(result);
345 if (!result && IsWindow(hwnd))
347 /* callback didn't process this message */
361 case WM_ENTERMENULOOP:
363 case WM_NCLBUTTONDOWN:
364 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
372 return DefWindowProcA( hwnd, msg, wParam, lParam );
375 return DEFDLG_Epilog(hwnd, msg, result);
379 /***********************************************************************
380 * DefDlgProcW (USER32.@)
382 LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
387 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
389 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
391 /* Call dialog procedure */
392 result = CallWindowProcW( dlgproc, hwnd, msg, wParam, lParam );
393 /* 16 bit dlg procs only return BOOL16 */
394 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
395 result = LOWORD(result);
398 if (!result && IsWindow(hwnd))
400 /* callback didn't process this message */
414 case WM_ENTERMENULOOP:
416 case WM_NCLBUTTONDOWN:
417 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
425 return DefWindowProcW( hwnd, msg, wParam, lParam );
428 return DEFDLG_Epilog(hwnd, msg, result);