Fixed some message names.
[wine] / windows / defdlg.c
1 /*
2  * Default dialog procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *
6  */
7
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"
15
16
17 /***********************************************************************
18  *           DEFDLG_SetFocus
19  *
20  * Set the focus to a control of the dialog, selecting the text if
21  * the control is an edit dialog.
22  */
23 static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
24 {
25     HWND hwndPrev = GetFocus();
26
27     if (IsChild( hwndDlg, hwndPrev ))
28     {
29         if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
30             SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
31     }
32     if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
33         SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
34     SetFocus( hwndCtrl );
35 }
36
37
38 /***********************************************************************
39  *           DEFDLG_SaveFocus
40  */
41 static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
42 {
43     HWND hwndFocus = GetFocus();
44
45     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
46     infoPtr->hwndFocus = hwndFocus;
47       /* Remove default button */
48     return TRUE;
49 }
50
51
52 /***********************************************************************
53  *           DEFDLG_RestoreFocus
54  */
55 static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
56 {
57     if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
58     if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
59
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 );
63
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;
67 }
68
69
70 /***********************************************************************
71  *           DEFDLG_FindDefButton
72  *
73  * Find the current default push-button.
74  */
75 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
76 {
77     HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
78     while (hwndChild)
79     {
80         if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
81             break;
82         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
83     }
84     return hwndChild;
85 }
86
87
88 /***********************************************************************
89  *           DEFDLG_SetDefButton
90  *
91  * Set the new default button to be hwndNew.
92  */
93 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
94                                    HWND hwndNew )
95 {
96     if (hwndNew &&
97         !(SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
98         return FALSE;  /* Destination is not a push button */
99     
100     if (dlgInfo->idResult)  /* There's already a default pushbutton */
101     {
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 );
105     }
106     if (hwndNew)
107     {
108         SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
109         dlgInfo->idResult = GetDlgCtrlID( hwndNew );
110     }
111     else dlgInfo->idResult = 0;
112     return TRUE;
113 }
114
115
116 /***********************************************************************
117  *           DEFDLG_Proc
118  *
119  * Implementation of DefDlgProc(). Only handle messages that need special
120  * handling for dialogs.
121  */
122 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
123                             LPARAM lParam, DIALOGINFO *dlgInfo )
124 {
125     switch(msg)
126     {
127         case WM_ERASEBKGND:
128             FillWindow16( hwnd, hwnd, (HDC16)wParam, (HBRUSH16)CTLCOLOR_DLG );
129             return 1;
130
131         case WM_NCDESTROY:
132
133               /* Free dialog heap (if created) */
134             if (dlgInfo->hDialogHeap)
135             {
136                 GlobalUnlock16(dlgInfo->hDialogHeap);
137                 GlobalFree16(dlgInfo->hDialogHeap);
138                 dlgInfo->hDialogHeap = 0;
139             }
140
141               /* Delete font */
142             if (dlgInfo->hUserFont)
143             {
144                 DeleteObject( dlgInfo->hUserFont );
145                 dlgInfo->hUserFont = 0;
146             }
147
148               /* Delete menu */
149             if (dlgInfo->hMenu)
150             {           
151                 DestroyMenu( dlgInfo->hMenu );
152                 dlgInfo->hMenu = 0;
153             }
154
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 */
159
160               /* Window clean-up */
161             return DefWindowProcA( hwnd, msg, wParam, lParam );
162
163         case WM_SHOWWINDOW:
164             if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
165             return DefWindowProcA( hwnd, msg, wParam, lParam );
166
167         case WM_ACTIVATE:
168             if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
169             else DEFDLG_SaveFocus( hwnd, dlgInfo );
170             return 0;
171
172         case WM_SETFOCUS:
173             DEFDLG_RestoreFocus( hwnd, dlgInfo );
174             return 0;
175
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;
181
182         case DM_GETDEFID:
183             {
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);
190             }
191             return 0;
192
193         case WM_NEXTDLGCTL:
194             {
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 );
200             }
201             return 0;
202
203         case WM_ENTERMENULOOP:
204         case WM_LBUTTONDOWN:
205         case WM_NCLBUTTONDOWN:
206             {
207                 HWND hwndFocus = GetFocus();
208                 if (hwndFocus)
209                 {
210                     /* always make combo box hide its listbox control */
211                     if (!SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
212                         SendMessageA( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
213                 }
214             }
215             return DefWindowProcA( hwnd, msg, wParam, lParam );
216
217         case WM_GETFONT: 
218             return dlgInfo->hUserFont;
219
220         case WM_CLOSE:
221             PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
222                             (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
223             return 0;
224     
225         case WM_NOTIFYFORMAT:
226             return DefWindowProcA( hwnd, msg, wParam, lParam );
227     }
228     return 0;
229 }
230
231 /***********************************************************************
232  *           DEFDLG_Epilog
233  */
234 static LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT msg, BOOL fResult)
235 {
236     /* see SDK 3.1 */
237
238     if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
239          msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
240          msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
241          msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
242         return fResult; 
243
244     return dlgInfo->msgResult;
245 }
246
247 /***********************************************************************
248  *              DefDlgProc (USER.308)
249  */
250 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
251                              LPARAM lParam )
252 {
253     DIALOGINFO * dlgInfo;
254     BOOL result = FALSE;
255     WND * wndPtr = WIN_FindWndPtr( hwnd );
256     
257     if (!wndPtr) return 0;
258     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
259     dlgInfo->msgResult = 0;
260
261     if (dlgInfo->dlgProc) {     /* Call dialog procedure */
262         result = CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
263                                            hwnd, msg, wParam, lParam );
264         /* 16 bit dlg procs only return BOOL16 */
265         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
266             result = LOWORD(result);
267     }
268
269     if (!result && IsWindow(hwnd))
270     {
271         /* callback didn't process this message */
272
273         switch(msg)
274         {
275             case WM_ERASEBKGND:
276             case WM_SHOWWINDOW:
277             case WM_ACTIVATE:
278             case WM_SETFOCUS:
279             case DM_SETDEFID:
280             case DM_GETDEFID:
281             case WM_NEXTDLGCTL:
282             case WM_GETFONT:
283             case WM_CLOSE:
284             case WM_NCDESTROY:
285             case WM_ENTERMENULOOP:
286             case WM_LBUTTONDOWN:
287             case WM_NCLBUTTONDOWN:
288                 WIN_ReleaseWndPtr(wndPtr);
289                 return DEFDLG_Proc( (HWND)hwnd, msg, 
290                                     (WPARAM)wParam, lParam, dlgInfo );
291             case WM_INITDIALOG:
292             case WM_VKEYTOITEM:
293             case WM_COMPAREITEM:
294             case WM_CHARTOITEM:
295                 break;
296
297             default:
298                 WIN_ReleaseWndPtr(wndPtr);
299                 return DefWindowProc16( hwnd, msg, wParam, lParam );
300         }
301     }   
302     WIN_ReleaseWndPtr(wndPtr);
303     return DEFDLG_Epilog(dlgInfo, msg, result);
304 }
305
306
307 /***********************************************************************
308  *              DefDlgProcA (USER32.@)
309  */
310 LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg,
311                               WPARAM wParam, LPARAM lParam )
312 {
313     DIALOGINFO * dlgInfo;
314     BOOL result = FALSE;
315     WND * wndPtr = WIN_FindWndPtr( hwnd );
316     
317     if (!wndPtr) return 0;
318     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
319     dlgInfo->msgResult = 0;
320
321     if (dlgInfo->dlgProc) {      /* Call dialog procedure */
322         result = CallWindowProcA( (WNDPROC)dlgInfo->dlgProc,
323                                             hwnd, msg, wParam, lParam );
324         /* 16 bit dlg procs only return BOOL16 */
325         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
326             result = LOWORD(result);
327     }
328
329     if (!result && IsWindow(hwnd))
330     {
331         /* callback didn't process this message */
332
333         switch(msg)
334         {
335             case WM_ERASEBKGND:
336             case WM_SHOWWINDOW:
337             case WM_ACTIVATE:
338             case WM_SETFOCUS:
339             case DM_SETDEFID:
340             case DM_GETDEFID:
341             case WM_NEXTDLGCTL:
342             case WM_GETFONT:
343             case WM_CLOSE:
344             case WM_NCDESTROY:
345             case WM_ENTERMENULOOP:
346             case WM_LBUTTONDOWN:
347             case WM_NCLBUTTONDOWN:
348                  WIN_ReleaseWndPtr(wndPtr);
349                  return DEFDLG_Proc( (HWND)hwnd, msg,
350                                      (WPARAM)wParam, lParam, dlgInfo );
351             case WM_INITDIALOG:
352             case WM_VKEYTOITEM:
353             case WM_COMPAREITEM:
354             case WM_CHARTOITEM:
355                  break;
356
357             default:
358                  WIN_ReleaseWndPtr(wndPtr);
359                  return DefWindowProcA( hwnd, msg, wParam, lParam );
360         }
361     }
362     WIN_ReleaseWndPtr(wndPtr);
363     return DEFDLG_Epilog(dlgInfo, msg, result);
364 }
365
366
367 /***********************************************************************
368  *              DefDlgProcW (USER32.@)
369  */
370 LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam,
371                               LPARAM lParam )
372 {
373     DIALOGINFO * dlgInfo;
374     BOOL result = FALSE;
375     WND * wndPtr = WIN_FindWndPtr( hwnd );
376     
377     if (!wndPtr) return 0;
378     dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
379     dlgInfo->msgResult = 0;
380
381     if (dlgInfo->dlgProc) {      /* Call dialog procedure */
382         result = CallWindowProcW( (WNDPROC)dlgInfo->dlgProc,
383                                             hwnd, msg, wParam, lParam );
384         /* 16 bit dlg procs only return BOOL16 */
385         if( WINPROC_GetProcType( dlgInfo->dlgProc ) == WIN_PROC_16 )
386             result = LOWORD(result);
387     }
388
389     if (!result && IsWindow(hwnd))
390     {
391         /* callback didn't process this message */
392
393         switch(msg)
394         {
395             case WM_ERASEBKGND:
396             case WM_SHOWWINDOW:
397             case WM_ACTIVATE:
398             case WM_SETFOCUS:
399             case DM_SETDEFID:
400             case DM_GETDEFID:
401             case WM_NEXTDLGCTL:
402             case WM_GETFONT:
403             case WM_CLOSE:
404             case WM_NCDESTROY:
405             case WM_ENTERMENULOOP:
406             case WM_LBUTTONDOWN:
407             case WM_NCLBUTTONDOWN:
408                  WIN_ReleaseWndPtr(wndPtr);
409                  return DEFDLG_Proc( (HWND)hwnd, msg,
410                                      (WPARAM)wParam, lParam, dlgInfo );
411             case WM_INITDIALOG:
412             case WM_VKEYTOITEM:
413             case WM_COMPAREITEM:
414             case WM_CHARTOITEM:
415                  break;
416
417             default:
418                  WIN_ReleaseWndPtr(wndPtr);
419                  return DefWindowProcW( hwnd, msg, wParam, lParam );
420         }
421     }
422     WIN_ReleaseWndPtr(wndPtr);
423     return DEFDLG_Epilog(dlgInfo, msg, result);
424 }