Small patch.
[wine/multimedia.git] / windows / defdlg.c
blob7e1fdf576d4689c4de571783f19b108e855ddbfd
1 /*
2 * Default dialog procedure
4 * Copyright 1993, 1996 Alexandre Julliard
6 */
8 #include "wine/winuser16.h"
9 #include "dialog.h"
10 #include "win.h"
11 #include "winproc.h"
14 /***********************************************************************
15 * DEFDLG_SetFocus
17 * Set the focus to a control of the dialog, selecting the text if
18 * the control is an edit dialog.
20 static void DEFDLG_SetFocus( HWND32 hwndDlg, HWND32 hwndCtrl )
22 HWND32 hwndPrev = GetFocus32();
24 if (IsChild32( hwndDlg, hwndPrev ))
26 if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
27 SendMessage16( hwndPrev, EM_SETSEL16, TRUE, MAKELONG( -1, 0 ) );
29 if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
30 SendMessage16( hwndCtrl, EM_SETSEL16, FALSE, MAKELONG( 0, -1 ) );
31 SetFocus32( hwndCtrl );
35 /***********************************************************************
36 * DEFDLG_SaveFocus
38 static BOOL32 DEFDLG_SaveFocus( HWND32 hwnd, DIALOGINFO *infoPtr )
40 HWND32 hwndFocus = GetFocus32();
42 if (!hwndFocus || !IsChild32( hwnd, hwndFocus )) return FALSE;
43 infoPtr->hwndFocus = hwndFocus;
44 /* Remove default button */
45 return TRUE;
49 /***********************************************************************
50 * DEFDLG_RestoreFocus
52 static BOOL32 DEFDLG_RestoreFocus( HWND32 hwnd, DIALOGINFO *infoPtr )
54 if (!infoPtr->hwndFocus || IsIconic32(hwnd)) return FALSE;
55 if (!IsWindow32( infoPtr->hwndFocus )) return FALSE;
56 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
57 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
58 sometimes losing focus when receiving WM_SETFOCUS messages. */
59 return TRUE;
63 /***********************************************************************
64 * DEFDLG_FindDefButton
66 * Find the current default push-button.
68 static HWND32 DEFDLG_FindDefButton( HWND32 hwndDlg )
70 HWND32 hwndChild = GetWindow32( hwndDlg, GW_CHILD );
71 while (hwndChild)
73 if (SendMessage16( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
74 break;
75 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
77 return hwndChild;
81 /***********************************************************************
82 * DEFDLG_SetDefButton
84 * Set the new default button to be hwndNew.
86 static BOOL32 DEFDLG_SetDefButton( HWND32 hwndDlg, DIALOGINFO *dlgInfo,
87 HWND32 hwndNew )
89 if (hwndNew &&
90 !(SendMessage16(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
91 return FALSE; /* Destination is not a push button */
93 if (dlgInfo->idResult) /* There's already a default pushbutton */
95 HWND32 hwndOld = GetDlgItem32( hwndDlg, dlgInfo->idResult );
96 if (SendMessage32A( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
97 SendMessage32A( hwndOld, BM_SETSTYLE32, BS_PUSHBUTTON, TRUE );
99 if (hwndNew)
101 SendMessage32A( hwndNew, BM_SETSTYLE32, BS_DEFPUSHBUTTON, TRUE );
102 dlgInfo->idResult = GetDlgCtrlID32( hwndNew );
104 else dlgInfo->idResult = 0;
105 return TRUE;
109 /***********************************************************************
110 * DEFDLG_Proc
112 * Implementation of DefDlgProc(). Only handle messages that need special
113 * handling for dialogs.
115 static LRESULT DEFDLG_Proc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
116 LPARAM lParam, DIALOGINFO *dlgInfo )
118 switch(msg)
120 case WM_ERASEBKGND:
121 FillWindow( hwnd, hwnd, (HDC16)wParam, (HBRUSH16)CTLCOLOR_DLG );
122 return 1;
124 case WM_NCDESTROY:
126 /* Free dialog heap (if created) */
127 if (dlgInfo->hDialogHeap)
129 GlobalUnlock16(dlgInfo->hDialogHeap);
130 GlobalFree16(dlgInfo->hDialogHeap);
131 dlgInfo->hDialogHeap = 0;
134 /* Delete font */
135 if (dlgInfo->hUserFont)
137 DeleteObject32( dlgInfo->hUserFont );
138 dlgInfo->hUserFont = 0;
141 /* Delete menu */
142 if (dlgInfo->hMenu)
144 DestroyMenu32( dlgInfo->hMenu );
145 dlgInfo->hMenu = 0;
148 /* Delete window procedure */
149 WINPROC_FreeProc( dlgInfo->dlgProc, WIN_PROC_WINDOW );
150 dlgInfo->dlgProc = (HWINDOWPROC)0;
151 dlgInfo->flags |= DF_END; /* just in case */
153 /* Window clean-up */
154 return DefWindowProc32A( hwnd, msg, wParam, lParam );
156 case WM_SHOWWINDOW:
157 if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
158 return DefWindowProc32A( hwnd, msg, wParam, lParam );
160 case WM_ACTIVATE:
161 if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
162 else DEFDLG_SaveFocus( hwnd, dlgInfo );
163 return 0;
165 case WM_SETFOCUS:
166 DEFDLG_RestoreFocus( hwnd, dlgInfo );
167 return 0;
169 case DM_SETDEFID:
170 if (dlgInfo->flags & DF_END) return 1;
171 DEFDLG_SetDefButton( hwnd, dlgInfo,
172 wParam ? GetDlgItem32( hwnd, wParam ) : 0 );
173 return 1;
175 case DM_GETDEFID:
177 HWND32 hwndDefId;
178 if (dlgInfo->flags & DF_END) return 0;
179 if (dlgInfo->idResult)
180 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
181 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
182 return MAKELONG( GetDlgCtrlID32( hwndDefId ), DC_HASDEFID);
184 return 0;
186 case WM_NEXTDLGCTL:
188 HWND32 hwndDest = (HWND32)wParam;
189 if (!lParam)
190 hwndDest = GetNextDlgTabItem32(hwnd, GetFocus32(), wParam);
191 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
192 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
194 return 0;
196 case WM_ENTERMENULOOP:
197 case WM_LBUTTONDOWN:
198 case WM_NCLBUTTONDOWN:
200 HWND32 hwndFocus = GetFocus32();
201 if (hwndFocus)
203 WND *wnd = WIN_FindWndPtr( hwndFocus );
205 if( wnd )
207 /* always make combo box hide its listbox control */
209 if( WIDGETS_IsControl32( wnd, BIC32_COMBO ) )
210 SendMessage32A( hwndFocus, CB_SHOWDROPDOWN32,
211 FALSE, 0 );
212 else if( WIDGETS_IsControl32( wnd, BIC32_EDIT ) &&
213 WIDGETS_IsControl32( wnd->parent,
214 BIC32_COMBO ))
215 SendMessage32A( wnd->parent->hwndSelf,
216 CB_SHOWDROPDOWN32, FALSE, 0 );
220 return DefWindowProc32A( hwnd, msg, wParam, lParam );
222 case WM_GETFONT:
223 return dlgInfo->hUserFont;
225 case WM_CLOSE:
226 PostMessage32A( hwnd, WM_COMMAND, IDCANCEL,
227 (LPARAM)GetDlgItem32( hwnd, IDCANCEL ) );
228 return 0;
230 return 0;
233 /***********************************************************************
234 * DEFDLG_Epilog
236 static LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT32 msg, BOOL32 fResult)
238 /* see SDK 3.1 */
240 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
241 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
242 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
243 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
244 return fResult;
246 return dlgInfo->msgResult;
249 /***********************************************************************
250 * DefDlgProc16 (USER.308)
252 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
253 LPARAM lParam )
255 DIALOGINFO * dlgInfo;
256 BOOL32 result = FALSE;
257 WND * wndPtr = WIN_FindWndPtr( hwnd );
259 if (!wndPtr) return 0;
260 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
261 dlgInfo->msgResult = 0;
263 if (dlgInfo->dlgProc) { /* Call dialog procedure */
264 result = CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
265 hwnd, msg, wParam, lParam );
266 /* 16 bit dlg procs only return BOOL16 */
267 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
268 result = LOWORD(result);
270 /* Check if window was destroyed by dialog procedure */
271 if (dlgInfo->flags & DF_END && !(dlgInfo->flags & DF_ENDING)) {
272 dlgInfo->flags |= DF_ENDING;
273 DestroyWindow32( hwnd );
277 if (!result && IsWindow32(hwnd))
279 /* callback didn't process this message */
281 switch(msg)
283 case WM_ERASEBKGND:
284 case WM_SHOWWINDOW:
285 case WM_ACTIVATE:
286 case WM_SETFOCUS:
287 case DM_SETDEFID:
288 case DM_GETDEFID:
289 case WM_NEXTDLGCTL:
290 case WM_GETFONT:
291 case WM_CLOSE:
292 case WM_NCDESTROY:
293 case WM_ENTERMENULOOP:
294 case WM_LBUTTONDOWN:
295 case WM_NCLBUTTONDOWN:
296 return DEFDLG_Proc( (HWND32)hwnd, msg,
297 (WPARAM32)wParam, lParam, dlgInfo );
298 case WM_INITDIALOG:
299 case WM_VKEYTOITEM:
300 case WM_COMPAREITEM:
301 case WM_CHARTOITEM:
302 break;
304 default:
305 return DefWindowProc16( hwnd, msg, wParam, lParam );
308 return DEFDLG_Epilog(dlgInfo, msg, result);
312 /***********************************************************************
313 * DefDlgProc32A (USER32.120)
315 LRESULT WINAPI DefDlgProc32A( HWND32 hwnd, UINT32 msg,
316 WPARAM32 wParam, LPARAM lParam )
318 DIALOGINFO * dlgInfo;
319 BOOL32 result = FALSE;
320 WND * wndPtr = WIN_FindWndPtr( hwnd );
322 if (!wndPtr) return 0;
323 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
324 dlgInfo->msgResult = 0;
326 if (dlgInfo->dlgProc) { /* Call dialog procedure */
327 result = CallWindowProc32A( (WNDPROC32)dlgInfo->dlgProc,
328 hwnd, msg, wParam, lParam );
329 /* 16 bit dlg procs only return BOOL16 */
330 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
331 result = LOWORD(result);
333 /* Check if window was destroyed by dialog procedure */
334 if (dlgInfo->flags & DF_END && !(dlgInfo->flags & DF_ENDING)) {
335 dlgInfo->flags |= DF_ENDING;
336 DestroyWindow32( hwnd );
340 if (!result && IsWindow32(hwnd))
342 /* callback didn't process this message */
344 switch(msg)
346 case WM_ERASEBKGND:
347 case WM_SHOWWINDOW:
348 case WM_ACTIVATE:
349 case WM_SETFOCUS:
350 case DM_SETDEFID:
351 case DM_GETDEFID:
352 case WM_NEXTDLGCTL:
353 case WM_GETFONT:
354 case WM_CLOSE:
355 case WM_NCDESTROY:
356 case WM_ENTERMENULOOP:
357 case WM_LBUTTONDOWN:
358 case WM_NCLBUTTONDOWN:
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;
367 default:
368 return DefWindowProc32A( hwnd, msg, wParam, lParam );
371 return DEFDLG_Epilog(dlgInfo, msg, result);
375 /***********************************************************************
376 * DefDlgProc32W (USER32.121)
378 LRESULT WINAPI DefDlgProc32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
379 LPARAM lParam )
381 DIALOGINFO * dlgInfo;
382 BOOL32 result = FALSE;
383 WND * wndPtr = WIN_FindWndPtr( hwnd );
385 if (!wndPtr) return 0;
386 dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
387 dlgInfo->msgResult = 0;
389 if (dlgInfo->dlgProc) { /* Call dialog procedure */
390 result = CallWindowProc32W( (WNDPROC32)dlgInfo->dlgProc,
391 hwnd, msg, wParam, lParam );
392 /* 16 bit dlg procs only return BOOL16 */
393 if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
394 result = LOWORD(result);
396 /* Check if window was destroyed by dialog procedure */
397 if (dlgInfo->flags & DF_END && !(dlgInfo->flags & DF_ENDING)) {
398 dlgInfo->flags |= DF_ENDING;
399 DestroyWindow32( hwnd );
403 if (!result && IsWindow32(hwnd))
405 /* callback didn't process this message */
407 switch(msg)
409 case WM_ERASEBKGND:
410 case WM_SHOWWINDOW:
411 case WM_ACTIVATE:
412 case WM_SETFOCUS:
413 case DM_SETDEFID:
414 case DM_GETDEFID:
415 case WM_NEXTDLGCTL:
416 case WM_GETFONT:
417 case WM_CLOSE:
418 case WM_NCDESTROY:
419 case WM_ENTERMENULOOP:
420 case WM_LBUTTONDOWN:
421 case WM_NCLBUTTONDOWN:
422 return DEFDLG_Proc( (HWND32)hwnd, msg,
423 (WPARAM32)wParam, lParam, dlgInfo );
424 case WM_INITDIALOG:
425 case WM_VKEYTOITEM:
426 case WM_COMPAREITEM:
427 case WM_CHARTOITEM:
428 break;
430 default:
431 return DefWindowProc32W( hwnd, msg, wParam, lParam );
434 return DEFDLG_Epilog(dlgInfo, msg, result);