source: trunk/src/user32/windlgmsg.cpp@ 8812

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

Translate & dispatch unprocessed messages in IsDialogMessageA/W (Wine doesn't do this, but experiments in Windows 2000 show different behaviour)

File size: 11.0 KB
Line 
1/* $Id: windlgmsg.cpp,v 1.15 2002-07-01 11:33:09 sandervl Exp $ */
2/*
3 * Win32 dialog message APIs for OS/2
4 *
5 * Copyright 1999 Sander van Leeuwen (OS/2 port & adaption)
6 *
7 * Based on Corel WINE code (20000317: window\dialog.c)
8 * (Based on Wine code (990815: window\dialog.c))
9 *
10 * Copyright 1993, 1994, 1996 Alexandre Julliard
11 *
12 * TODO: Dialog accelerator
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17#include <os2win.h>
18#include <misc.h>
19#include <string.h>
20#include <ctype.h>
21#include "win32wbase.h"
22#include "win32dlg.h"
23#include <winnls.h>
24#include <wine\unicode.h>
25
26#define DBG_LOCALLOG DBG_windlgmsg
27#include "dbglocal.h"
28
29//******************************************************************************
30//******************************************************************************
31LONG WIN32API SendDlgItemMessageA( HWND hwnd, int id, UINT Msg, WPARAM wParam, LPARAM lParam)
32{
33 Win32Dialog *dialog;
34 HWND hwndDlgItem;
35
36 dialog = (Win32Dialog *)Win32BaseWindow::GetWindowFromHandle(hwnd);
37 if(!dialog) {
38 dprintf(("SendDlgItemMessageA, window %x not found", hwnd));
39 return 0;
40 }
41 hwndDlgItem = dialog->getDlgItem(id);
42 RELEASE_WNDOBJ(dialog);
43 if(hwndDlgItem) {
44 return SendMessageA(hwndDlgItem, Msg, wParam, lParam);
45 }
46 return 0;
47}
48//******************************************************************************
49//******************************************************************************
50LONG WIN32API SendDlgItemMessageW( HWND hwnd, int id, UINT Msg, WPARAM wParam, LPARAM lParam)
51{
52 Win32Dialog *dialog;
53 HWND hwndDlgItem;
54
55 dialog = (Win32Dialog *)Win32BaseWindow::GetWindowFromHandle(hwnd);
56 if(!dialog) {
57 dprintf(("SendDlgItemMessageW, window %x not found", hwnd));
58 return 0;
59 }
60 hwndDlgItem = dialog->getDlgItem(id);
61 RELEASE_WNDOBJ(dialog);
62 if(hwndDlgItem) {
63 return SendMessageW(hwndDlgItem, Msg, wParam, lParam);
64 }
65 return 0;
66}
67/***********************************************************************
68 * DIALOG_IsAccelerator
69 */
70static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM vKey )
71{
72 HWND hwndControl = hwnd;
73 HWND hwndNext;
74 BOOL RetVal = FALSE;
75 WCHAR buffer[128];
76 INT dlgCode;
77
78#ifdef __WIN32OS2__
79 //@PF: Experimental DIALOG_IsAccelerator fix; return FALSE if window is not visible
80 //(fixes endless loop in property sheet when switching page with keyboard)
81 if (!IsWindowVisible(hwnd))
82 return FALSE;
83#endif
84
85 if (vKey == VK_SPACE)
86 {
87 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
88 if (dlgCode & DLGC_BUTTON)
89 {
90 /* send BM_CLICK message to the control */
91 SendMessageA( hwndControl, BM_CLICK, 0, 0 );
92 return TRUE;
93 }
94 }
95
96 do
97 {
98 DWORD style = GetWindowLongW( hwndControl, GWL_STYLE );
99 if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
100 {
101 dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
102 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
103 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
104 {
105 /* find the accelerator key */
106 LPWSTR p = buffer - 2;
107 char a_char = vKey;
108 WCHAR w_char = 0;
109
110 do
111 {
112 p = strchrW( p + 2, '&' );
113 }
114 while (p != NULL && p[1] == '&');
115
116 /* and check if it's the one we're looking for */
117 MultiByteToWideChar(CP_ACP, 0, &a_char, 1, &w_char, 1);
118 if (p != NULL && toupperW( p[1] ) == toupperW( w_char ) )
119 {
120 if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
121 {
122 /* set focus to the control */
123 SendMessageA( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
124 /* and bump it on to next */
125 SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
126 }
127 else if (dlgCode & DLGC_BUTTON)
128 {
129 /* send BM_CLICK message to the control */
130 SendMessageA( hwndControl, BM_CLICK, 0, 0 );
131 }
132 return TRUE;
133 }
134 }
135 hwndNext = GetWindow( hwndControl, GW_CHILD );
136 }
137 else hwndNext = 0;
138
139 if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
140
141 while (!hwndNext && hwndControl)
142 {
143 hwndControl = GetParent( hwndControl );
144 if (hwndControl == hwndDlg)
145 {
146 if(hwnd==hwndDlg) /* prevent endless loop */
147 {
148 hwndNext=hwnd;
149 break;
150 }
151 hwndNext = GetWindow( hwndDlg, GW_CHILD );
152 }
153 else
154#ifdef __WIN32OS2__
155 {
156 if(hwndControl == 0) {
157 dprintf(("WARNING: DIALOG_IsAccelerator %x %x -> hwndControl == 0", hwnd, hwndDlg));
158 return FALSE;
159 }
160 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
161 }
162#else
163 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
164#endif
165 }
166 hwndControl = hwndNext;
167 }
168 while (hwndControl && (hwndControl != hwnd));
169
170 return FALSE;
171}
172/***********************************************************************
173 * DIALOG_FindMsgDestination
174 *
175 * The messages that IsDialogMessage send may not go to the dialog
176 * calling IsDialogMessage if that dialog is a child, and it has the
177 * DS_CONTROL style set.
178 * We propagate up until we hit a that does not have DS_CONTROL, or
179 * whose parent is not a dialog.
180 *
181 * This is undocumented behaviour.
182 */
183static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
184{
185 while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
186 {
187 Win32BaseWindow *pParent;
188 HWND hParent = GetParent(hwndDlg);
189 if (!hParent) break;
190
191 pParent = Win32BaseWindow::GetWindowFromHandle(hParent);
192 if (!pParent) break;
193
194 if (!pParent->IsDialog()) {
195 RELEASE_WNDOBJ(pParent);
196 break;
197 }
198 RELEASE_WNDOBJ(pParent);
199 hwndDlg = hParent;
200 }
201
202 return hwndDlg;
203}
204
205/***********************************************************************
206 * DIALOG_IsDialogMessage
207 */
208static BOOL DIALOG_IsDialogMessage( HWND hwndDlg, BOOL *translate, BOOL *dispatch, INT dlgCode, LPMSG msg )
209{
210 *translate = *dispatch = FALSE;
211
212 if (msg->message == WM_PAINT)
213 {
214 /* Apparently, we have to handle this one as well */
215 *dispatch = TRUE;
216 return TRUE;
217 }
218
219 /* Only the key messages get special processing */
220 if ((msg->message != WM_KEYDOWN) &&
221 (msg->message != WM_SYSCHAR) &&
222 (msg->message != WM_CHAR))
223 {
224#ifdef __WIN32OS2__
225 *translate = *dispatch = TRUE;
226 return TRUE;
227#else
228 return FALSE;
229#endif
230 }
231
232 if (dlgCode & DLGC_WANTMESSAGE)
233 {
234 *translate = *dispatch = TRUE;
235 return TRUE;
236 }
237
238 hwndDlg = DIALOG_FindMsgDestination(hwndDlg);
239
240 switch(msg->message)
241 {
242 case WM_KEYDOWN:
243 switch(msg->wParam)
244 {
245 case VK_TAB:
246 if (!(dlgCode & DLGC_WANTTAB))
247 {
248 SendMessageA( hwndDlg, WM_NEXTDLGCTL,
249 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
250 return TRUE;
251 }
252 break;
253
254 case VK_RIGHT:
255 case VK_DOWN:
256 case VK_LEFT:
257 case VK_UP:
258 if (!(dlgCode & DLGC_WANTARROWS))
259 {
260 BOOL fPrevious = (msg->wParam == VK_LEFT || msg->wParam == VK_UP);
261 HWND hwndNext =
262 GetNextDlgGroupItem (hwndDlg, GetFocus(), fPrevious );
263 SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
264 return TRUE;
265 }
266 break;
267
268 case VK_ESCAPE:
269 SendMessageA( hwndDlg, WM_COMMAND, IDCANCEL,
270 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
271 return TRUE;
272
273 case VK_RETURN:
274 {
275 DWORD dw = SendMessageA( hwndDlg, DM_GETDEFID, 0, 0 );
276 if (HIWORD(dw) == DC_HASDEFID)
277 {
278 //@PF If DEFID button is disabled do not press it!
279 if (IsWindowEnabled(GetDlgItem(hwndDlg, LOWORD(dw))))
280 SendMessageA( hwndDlg, WM_COMMAND,
281 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
282 (LPARAM)GetDlgItem(hwndDlg, LOWORD(dw)));
283 }
284 else
285 {
286 SendMessageA( hwndDlg, WM_COMMAND, IDOK,
287 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
288
289 }
290
291 return TRUE;
292 }
293 }
294 *translate = TRUE;
295 break; /* case WM_KEYDOWN */
296
297 case WM_CHAR:
298 if (dlgCode & DLGC_WANTCHARS) break;
299 /* drop through */
300
301 case WM_SYSCHAR:
302 if (DIALOG_IsAccelerator( msg->hwnd, hwndDlg, msg->wParam ))
303 {
304 /* don't translate or dispatch */
305 return TRUE;
306 }
307 break;
308 }
309
310 /* If we get here, the message has not been treated specially */
311 /* and can be sent to its destination window. */
312 *dispatch = TRUE;
313 return TRUE;
314}
315//******************************************************************************
316//******************************************************************************
317BOOL WIN32API IsDialogMessageA( HWND hwndDlg, LPMSG msg)
318{
319 BOOL ret, translate, dispatch;
320 INT dlgCode;
321
322 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
323 return FALSE;
324
325#ifdef __WIN32OS2__
326 if(CallMsgFilterA(msg, HC_ACTION)) {
327 return TRUE;
328 }
329#endif
330
331 dlgCode = SendMessageA( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
332 ret = DIALOG_IsDialogMessage(hwndDlg,&translate,&dispatch,dlgCode,msg);
333 if (translate) TranslateMessage( msg );
334 if (dispatch) DispatchMessageA( msg );
335
336 return ret;
337}
338//******************************************************************************
339//******************************************************************************
340BOOL WIN32API IsDialogMessageW(HWND hwndDlg, LPMSG msg)
341{
342 BOOL ret, translate, dispatch;
343 INT dlgCode;
344
345 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
346 return FALSE;
347
348#ifdef __WIN32OS2__
349 if(CallMsgFilterW(msg, HC_ACTION)) {
350 return TRUE;
351 }
352#endif
353
354 dlgCode = SendMessageW( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
355 ret = DIALOG_IsDialogMessage(hwndDlg,&translate,&dispatch,dlgCode,msg);
356 if (translate) TranslateMessage( msg );
357 if (dispatch) DispatchMessageW( msg );
358 return ret;
359}
360//******************************************************************************
361//******************************************************************************
Note: See TracBrowser for help on using the repository browser.