source: trunk/src/user32/controls/defdlg.c@ 8543

Last change on this file since 8543 was 8543, checked in by sandervl, 23 years ago

seperate odin control dll with latest wine controls added (not activate & not finished)

File size: 13.5 KB
Line 
1/*
2 * Default dialog procedure
3 *
4 * Copyright 1993, 1996 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "windef.h"
22#include "winbase.h"
23#include "wingdi.h"
24#include "wine/winuser16.h"
25#include "controls.h"
26#include "win.h"
27#include "winproc.h"
28#include "wine/debug.h"
29
30WINE_DEFAULT_DEBUG_CHANNEL(dialog);
31
32
33/***********************************************************************
34 * DEFDLG_GetDlgProc
35 */
36static WNDPROC DEFDLG_GetDlgProc( HWND hwnd )
37{
38 WNDPROC ret;
39 WND *wndPtr = WIN_GetPtr( hwnd );
40
41 if (!wndPtr) return 0;
42 if (wndPtr == WND_OTHER_PROCESS)
43 {
44 ERR( "cannot get dlg proc %x from other process\n", hwnd );
45 return 0;
46 }
47 ret = *(WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
48 WIN_ReleasePtr( wndPtr );
49 return ret;
50}
51
52/***********************************************************************
53 * DEFDLG_SetFocus
54 *
55 * Set the focus to a control of the dialog, selecting the text if
56 * the control is an edit dialog.
57 */
58static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
59{
60 HWND hwndPrev = GetFocus();
61
62 if (IsChild( hwndDlg, hwndPrev ))
63 {
64 if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
65 SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
66 }
67 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
68 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
69 SetFocus( hwndCtrl );
70}
71
72
73/***********************************************************************
74 * DEFDLG_SaveFocus
75 */
76static void DEFDLG_SaveFocus( HWND hwnd )
77{
78 DIALOGINFO *infoPtr;
79 HWND hwndFocus = GetFocus();
80
81 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
82 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
83 infoPtr->hwndFocus = hwndFocus;
84 /* Remove default button */
85}
86
87
88/***********************************************************************
89 * DEFDLG_RestoreFocus
90 */
91static void DEFDLG_RestoreFocus( HWND hwnd )
92{
93 DIALOGINFO *infoPtr;
94
95 if (IsIconic( hwnd )) return;
96 if (!(infoPtr = DIALOG_get_info( hwnd ))) return;
97 if (!IsWindow( infoPtr->hwndFocus )) return;
98 /* Don't set the focus back to controls if EndDialog is already called.*/
99 if (!(infoPtr->flags & DF_END))
100 {
101 DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
102 return;
103 }
104 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
105 sometimes losing focus when receiving WM_SETFOCUS messages. */
106}
107
108
109/***********************************************************************
110 * DEFDLG_FindDefButton
111 *
112 * Find the current default push-button.
113 */
114static HWND DEFDLG_FindDefButton( HWND hwndDlg )
115{
116 HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
117 while (hwndChild)
118 {
119 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
120 break;
121 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
122 }
123 return hwndChild;
124}
125
126
127/***********************************************************************
128 * DEFDLG_SetDefButton
129 *
130 * Set the new default button to be hwndNew.
131 */
132static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
133 HWND hwndNew )
134{
135 DWORD dlgcode=0; /* initialize just to avoid a warning */
136 if (hwndNew &&
137 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
138 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
139 return FALSE; /* Destination is not a push button */
140
141 if (dlgInfo->idResult) /* There's already a default pushbutton */
142 {
143 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
144 if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
145 SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
146 }
147 if (hwndNew)
148 {
149 if(dlgcode==DLGC_UNDEFPUSHBUTTON)
150 SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
151 dlgInfo->idResult = GetDlgCtrlID( hwndNew );
152 }
153 else dlgInfo->idResult = 0;
154 return TRUE;
155}
156
157
158/***********************************************************************
159 * DEFDLG_Proc
160 *
161 * Implementation of DefDlgProc(). Only handle messages that need special
162 * handling for dialogs.
163 */
164static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
165 LPARAM lParam, DIALOGINFO *dlgInfo )
166{
167 switch(msg)
168 {
169 case WM_ERASEBKGND:
170 {
171 HBRUSH brush = SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
172 if (!brush) brush = DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
173 if (brush)
174 {
175 RECT rect;
176 HDC hdc = (HDC)wParam;
177 GetClientRect( hwnd, &rect );
178 DPtoLP( hdc, (LPPOINT)&rect, 2 );
179 FillRect( hdc, &rect, brush );
180 }
181 return 1;
182 }
183 case WM_NCDESTROY:
184 if ((dlgInfo = (DIALOGINFO *)SetWindowLongW( hwnd, DWL_WINE_DIALOGINFO, 0 )))
185 {
186 /* Free dialog heap (if created) */
187 if (dlgInfo->hDialogHeap)
188 {
189 GlobalUnlock16(dlgInfo->hDialogHeap);
190 GlobalFree16(dlgInfo->hDialogHeap);
191 }
192 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
193 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
194 WINPROC_FreeProc( DEFDLG_GetDlgProc( hwnd ), WIN_PROC_WINDOW );
195 HeapFree( GetProcessHeap(), 0, dlgInfo );
196 }
197 /* Window clean-up */
198 return DefWindowProcA( hwnd, msg, wParam, lParam );
199
200 case WM_SHOWWINDOW:
201 if (!wParam) DEFDLG_SaveFocus( hwnd );
202 return DefWindowProcA( hwnd, msg, wParam, lParam );
203
204 case WM_ACTIVATE:
205 if (wParam) DEFDLG_RestoreFocus( hwnd );
206 else DEFDLG_SaveFocus( hwnd );
207 return 0;
208
209 case WM_SETFOCUS:
210 DEFDLG_RestoreFocus( hwnd );
211 return 0;
212
213 case DM_SETDEFID:
214 if (dlgInfo->flags & DF_END) return 1;
215 DEFDLG_SetDefButton( hwnd, dlgInfo,
216 wParam ? GetDlgItem( hwnd, wParam ) : 0 );
217 return 1;
218
219 case DM_GETDEFID:
220 {
221 HWND hwndDefId;
222 if (dlgInfo->flags & DF_END) return 0;
223 if (dlgInfo->idResult)
224 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
225 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
226 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
227 }
228 return 0;
229
230 case WM_NEXTDLGCTL:
231 {
232 HWND hwndDest = (HWND)wParam;
233 if (!lParam)
234 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
235 if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
236 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
237 }
238 return 0;
239
240 case WM_ENTERMENULOOP:
241 case WM_LBUTTONDOWN:
242 case WM_NCLBUTTONDOWN:
243 {
244 HWND hwndFocus = GetFocus();
245 if (hwndFocus)
246 {
247 /* always make combo box hide its listbox control */
248 if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
249 SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
250 }
251 }
252 return DefWindowProcA( hwnd, msg, wParam, lParam );
253
254 case WM_GETFONT:
255 return dlgInfo->hUserFont;
256
257 case WM_CLOSE:
258 PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
259 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
260 return 0;
261
262 case WM_NOTIFYFORMAT:
263 return DefWindowProcA( hwnd, msg, wParam, lParam );
264 }
265 return 0;
266}
267
268/***********************************************************************
269 * DEFDLG_Epilog
270 */
271static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
272{
273 /* see SDK 3.1 */
274
275 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
276 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
277 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
278 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
279 return fResult;
280
281 return GetWindowLongA( hwnd, DWL_MSGRESULT );
282}
283#ifndef __WIN32OS2__
284/***********************************************************************
285 * DefDlgProc (USER.308)
286 */
287LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
288 LPARAM lParam )
289{
290 WNDPROC16 dlgproc;
291 HWND hwnd32 = WIN_Handle32( hwnd );
292 BOOL result = FALSE;
293
294 SetWindowLongW( hwnd32, DWL_MSGRESULT, 0 );
295
296 if ((dlgproc = (WNDPROC16)DEFDLG_GetDlgProc( hwnd32 )))
297 {
298 /* Call dialog procedure */
299 result = CallWindowProc16( dlgproc, hwnd, msg, wParam, lParam );
300 /* 16 bit dlg procs only return BOOL16 */
301 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
302 result = LOWORD(result);
303 }
304
305 if (!result && IsWindow(hwnd32))
306 {
307 /* callback didn't process this message */
308
309 switch(msg)
310 {
311 case WM_ERASEBKGND:
312 case WM_SHOWWINDOW:
313 case WM_ACTIVATE:
314 case WM_SETFOCUS:
315 case DM_SETDEFID:
316 case DM_GETDEFID:
317 case WM_NEXTDLGCTL:
318 case WM_GETFONT:
319 case WM_CLOSE:
320 case WM_NCDESTROY:
321 case WM_ENTERMENULOOP:
322 case WM_LBUTTONDOWN:
323 case WM_NCLBUTTONDOWN:
324 return DEFDLG_Proc( hwnd32, msg, (WPARAM)wParam, lParam, DIALOG_get_info(hwnd32) );
325 case WM_INITDIALOG:
326 case WM_VKEYTOITEM:
327 case WM_COMPAREITEM:
328 case WM_CHARTOITEM:
329 break;
330
331 default:
332 return DefWindowProc16( hwnd, msg, wParam, lParam );
333 }
334 }
335 return DEFDLG_Epilog( hwnd32, msg, result);
336}
337#endif
338
339/***********************************************************************
340 * DefDlgProcA (USER32.@)
341 */
342LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
343{
344 WNDPROC dlgproc;
345 BOOL result = FALSE;
346
347 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
348
349 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
350 {
351 /* Call dialog procedure */
352 result = CallWindowProcA( dlgproc, hwnd, msg, wParam, lParam );
353#ifndef __WIN32OS2__
354 /* 16 bit dlg procs only return BOOL16 */
355 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
356 result = LOWORD(result);
357#endif
358 }
359
360 if (!result && IsWindow(hwnd))
361 {
362 /* callback didn't process this message */
363
364 switch(msg)
365 {
366 case WM_ERASEBKGND:
367 case WM_SHOWWINDOW:
368 case WM_ACTIVATE:
369 case WM_SETFOCUS:
370 case DM_SETDEFID:
371 case DM_GETDEFID:
372 case WM_NEXTDLGCTL:
373 case WM_GETFONT:
374 case WM_CLOSE:
375 case WM_NCDESTROY:
376 case WM_ENTERMENULOOP:
377 case WM_LBUTTONDOWN:
378 case WM_NCLBUTTONDOWN:
379 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
380 case WM_INITDIALOG:
381 case WM_VKEYTOITEM:
382 case WM_COMPAREITEM:
383 case WM_CHARTOITEM:
384 break;
385
386 default:
387 return DefWindowProcA( hwnd, msg, wParam, lParam );
388 }
389 }
390 return DEFDLG_Epilog(hwnd, msg, result);
391}
392
393
394/***********************************************************************
395 * DefDlgProcW (USER32.@)
396 */
397LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
398{
399 BOOL result = FALSE;
400 WNDPROC dlgproc;
401
402 SetWindowLongW( hwnd, DWL_MSGRESULT, 0 );
403
404 if ((dlgproc = DEFDLG_GetDlgProc( hwnd )))
405 {
406 /* Call dialog procedure */
407 result = CallWindowProcW( dlgproc, hwnd, msg, wParam, lParam );
408#ifndef __WIN32OS2__
409 /* 16 bit dlg procs only return BOOL16 */
410 if( WINPROC_GetProcType( dlgproc ) == WIN_PROC_16 )
411 result = LOWORD(result);
412#endif
413 }
414
415 if (!result && IsWindow(hwnd))
416 {
417 /* callback didn't process this message */
418
419 switch(msg)
420 {
421 case WM_ERASEBKGND:
422 case WM_SHOWWINDOW:
423 case WM_ACTIVATE:
424 case WM_SETFOCUS:
425 case DM_SETDEFID:
426 case DM_GETDEFID:
427 case WM_NEXTDLGCTL:
428 case WM_GETFONT:
429 case WM_CLOSE:
430 case WM_NCDESTROY:
431 case WM_ENTERMENULOOP:
432 case WM_LBUTTONDOWN:
433 case WM_NCLBUTTONDOWN:
434 return DEFDLG_Proc( hwnd, msg, wParam, lParam, DIALOG_get_info(hwnd) );
435 case WM_INITDIALOG:
436 case WM_VKEYTOITEM:
437 case WM_COMPAREITEM:
438 case WM_CHARTOITEM:
439 break;
440
441 default:
442 return DefWindowProcW( hwnd, msg, wParam, lParam );
443 }
444 }
445 return DEFDLG_Epilog(hwnd, msg, result);
446}
Note: See TracBrowser for help on using the repository browser.