Skip BitBlt DIB optimization if source and dest DCs have different
[wine/multimedia.git] / windows / defdlg.c
blob3cc9b71b8b057c3fdf6c6b8784fc76059203deb1
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 "controls.h"
13 #include "win.h"
14 #include "winproc.h"
17 /***********************************************************************
18 * DEFDLG_GetDlgProc
20 static WNDPROC DEFDLG_GetDlgProc( HWND hwnd )
22 WNDPROC ret = 0;
23 WND * wndPtr = WIN_FindWndPtr( hwnd );
24 if (wndPtr)
26 ret = *(WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
27 WIN_ReleaseWndPtr(wndPtr);
29 return ret;
32 /***********************************************************************
33 * DEFDLG_SetFocus
35 * Set the focus to a control of the dialog, selecting the text if
36 * the control is an edit dialog.
38 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
40 HWND hwndPrev = GetFocus();
42 if (IsChild( hwndDlg, hwndPrev ))
44 if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
45 SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
47 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
48 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
49 SetFocus( hwndCtrl );
53 /***********************************************************************
54 * DEFDLG_SaveFocus
56 static void DEFDLG_SaveFocus( HWND hwnd )
58 DIALOGINFO *infoPtr;
59 HWND hwndFocus = GetFocus();
61 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
62 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
63 infoPtr->hwndFocus = hwndFocus;
64 /* Remove default button */
68 /***********************************************************************
69 * DEFDLG_RestoreFocus
71 static void DEFDLG_RestoreFocus( HWND hwnd )
73 DIALOGINFO *infoPtr;
75 if (IsIconic( hwnd )) return;
76 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
77 if (!IsWindow( infoPtr->hwndFocus )) return;
78 /* Don't set the focus back to controls if EndDialog is already called.*/
79 if (!(infoPtr->flags & DF_END))
81 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
82 return;
84 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
85 sometimes losing focus when receiving WM_SETFOCUS messages. */
89 /***********************************************************************
90 * DEFDLG_FindDefButton
92 * Find the current default push-button.
94 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
96 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
97 while (hwndChild)
99 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
100 break;
101 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
103 return hwndChild;
107 /***********************************************************************
108 * DEFDLG_SetDefButton
110 * Set the new default button to be hwndNew.
112 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
113 HWND hwndNew )
115 if (hwndNew &&
116 !(SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
117 return FALSE; /* Destination is not a push button */
119 if (dlgInfo->idResult) /* There's already a default pushbutton */
121 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
122 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
123 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
125 if (hwndNew)
127 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
128 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
130 else dlgInfo->idResult = 0;
131 return TRUE;
135 /***********************************************************************
136 * DEFDLG_Proc
138 * Implementation of DefDlgProc(). Only handle messages that need special
139 * handling for dialogs.
141 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
142 LPARAM lParam, DIALOGINFO *dlgInfo )
144 switch(msg)
146 case WM_ERASEBKGND:
148 HBRUSH brush = SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
149 if (!brush) brush = DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
150 if (brush)
152 RECT rect;
153 HDC hdc = (HDC)wParam;
154 GetClientRect( hwnd, &rect );
155 DPtoLP( hdc, (LPPOINT)&rect, 2 );
156 FillRect( hdc, &rect, brush );
158 return 1;
160 case WM_NCDESTROY:
161 if ((dlgInfo = (DIALOGINFO *)SetWindowLongW( hwnd, DWL_WINE_DIALOGINFO, 0 )))
163 /* Free dialog heap (if created) */
164 if (dlgInfo->hDialogHeap)
166 GlobalUnlock16(dlgInfo->hDialogHeap);
167 GlobalFree16(dlgInfo->hDialogHeap);
169 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
170 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
171 WINPROC_FreeProc( DEFDLG_GetDlgProc( hwnd ), WIN_PROC_WINDOW );
172 HeapFree( GetProcessHeap(), 0, dlgInfo );
174 /* Window clean-up */
175 return DefWindowProcA( hwnd, msg, wParam, lParam );
177 case WM_SHOWWINDOW:
178 if (!wParam) DEFDLG_SaveFocus( hwnd );
179 return DefWindowProcA( hwnd, msg, wParam, lParam );
181 case WM_ACTIVATE:
182 if (wParam) DEFDLG_RestoreFocus( hwnd );
183 else DEFDLG_SaveFocus( hwnd );
184 return 0;
186 case WM_SETFOCUS:
187 DEFDLG_RestoreFocus( hwnd );
188 return 0;
190 case DM_SETDEFID:
191 if (dlgInfo->flags & DF_END) return 1;
192 DEFDLG_SetDefButton( hwnd, dlgInfo,
193 wParam ? GetDlgItem( hwnd, wParam ) : 0 );
194 return 1;
196 case DM_GETDEFID:
198 HWND hwndDefId;
199 if (dlgInfo->flags & DF_END) return 0;
200 if (dlgInfo->idResult)
201 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
202 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
203 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
205 return 0;
207 case WM_NEXTDLGCTL:
209 HWND hwndDest = (HWND)wParam;
210 if (!lParam)
211 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
212 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
213 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
215 return 0;
217 case WM_ENTERMENULOOP:
218 case WM_LBUTTONDOWN:
219 case WM_NCLBUTTONDOWN:
221 HWND hwndFocus = GetFocus();
222 if (hwndFocus)
224 /* always make combo box hide its listbox control */
225 if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
226 SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
229 return DefWindowProcA( hwnd, msg, wParam, lParam );
231 case WM_GETFONT:
232 return dlgInfo->hUserFont;
234 case WM_CLOSE:
235 PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
236 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
237 return 0;
239 case WM_NOTIFYFORMAT:
240 return DefWindowProcA( hwnd, msg, wParam, lParam );
242 return 0;
245 /***********************************************************************
246 * DEFDLG_Epilog
248 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
250 /* see SDK 3.1 */
252 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
253 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
254 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
255 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
256 return fResult;
258 return GetWindowLongA( hwnd, DWL_MSGRESULT );
261 /***********************************************************************
262 * DefDlgProc (USER.308)
264 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
265 LPARAM lParam )
267 WNDPROC16 dlgproc;
268 HWND hwnd32 = WIN_Handle32( hwnd );
269 BOOL result = FALSE;
271 SetWindowLongW( hwnd32, DWL_MSGRESULT, 0 );
273 if ((dlgproc = (WNDPROC16)DEFDLG_GetDlgProc( hwnd32 )))
275 /* Call dialog procedure */
276 result = CallWindowProc16( dlgproc, hwnd, msg, wParam, lParam );
277 /* 16 bit dlg procs only return BOOL16 */
278 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
279 result = LOWORD(result);
282 if (!result && IsWindow(hwnd32))
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 return DEFDLG_Proc( hwnd32, msg, (WPARAM)wParam, lParam, DIALOG_get_info(hwnd32) );
302 case WM_INITDIALOG:
303 case WM_VKEYTOITEM:
304 case WM_COMPAREITEM:
305 case WM_CHARTOITEM:
306 break;
308 default:
309 return DefWindowProc16( hwnd, msg, wParam, lParam );
312 return DEFDLG_Epilog( hwnd32, msg, result);
316 /***********************************************************************
317 * DefDlgProcA (USER32.@)
319 LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
321 WNDPROC dlgproc;
322 BOOL result = FALSE;
324 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
326 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
328 /* Call dialog procedure */
329 result = CallWindowProcA( dlgproc, hwnd, msg, wParam, lParam );
330 /* 16 bit dlg procs only return BOOL16 */
331 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
332 result = LOWORD(result);
335 if (!result && IsWindow(hwnd))
337 /* callback didn't process this message */
339 switch(msg)
341 case WM_ERASEBKGND:
342 case WM_SHOWWINDOW:
343 case WM_ACTIVATE:
344 case WM_SETFOCUS:
345 case DM_SETDEFID:
346 case DM_GETDEFID:
347 case WM_NEXTDLGCTL:
348 case WM_GETFONT:
349 case WM_CLOSE:
350 case WM_NCDESTROY:
351 case WM_ENTERMENULOOP:
352 case WM_LBUTTONDOWN:
353 case WM_NCLBUTTONDOWN:
354 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
355 case WM_INITDIALOG:
356 case WM_VKEYTOITEM:
357 case WM_COMPAREITEM:
358 case WM_CHARTOITEM:
359 break;
361 default:
362 return DefWindowProcA( hwnd, msg, wParam, lParam );
365 return DEFDLG_Epilog(hwnd, msg, result);
369 /***********************************************************************
370 * DefDlgProcW (USER32.@)
372 LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
374 BOOL result = FALSE;
375 WNDPROC dlgproc;
377 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
379 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
381 /* Call dialog procedure */
382 result = CallWindowProcW( dlgproc, hwnd, msg, wParam, lParam );
383 /* 16 bit dlg procs only return BOOL16 */
384 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
385 result = LOWORD(result);
388 if (!result && IsWindow(hwnd))
390 /* callback didn't process this message */
392 switch(msg)
394 case WM_ERASEBKGND:
395 case WM_SHOWWINDOW:
396 case WM_ACTIVATE:
397 case WM_SETFOCUS:
398 case DM_SETDEFID:
399 case DM_GETDEFID:
400 case WM_NEXTDLGCTL:
401 case WM_GETFONT:
402 case WM_CLOSE:
403 case WM_NCDESTROY:
404 case WM_ENTERMENULOOP:
405 case WM_LBUTTONDOWN:
406 case WM_NCLBUTTONDOWN:
407 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
408 case WM_INITDIALOG:
409 case WM_VKEYTOITEM:
410 case WM_COMPAREITEM:
411 case WM_CHARTOITEM:
412 break;
414 default:
415 return DefWindowProcW( hwnd, msg, wParam, lParam );
418 return DEFDLG_Epilog(hwnd, msg, result);