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

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

PF: Don't send WM_COMMAND to disabled button in DIALOG_IsDialogMessage

File size: 10.7 KB
Line 
1/* $Id: windlgmsg.cpp,v 1.13 2002-05-28 09:40:30 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 return FALSE;
224
225 if (dlgCode & DLGC_WANTMESSAGE)
226 {
227 *translate = *dispatch = TRUE;
228 return TRUE;
229 }
230
231 hwndDlg = DIALOG_FindMsgDestination(hwndDlg);
232
233 switch(msg->message)
234 {
235 case WM_KEYDOWN:
236 switch(msg->wParam)
237 {
238 case VK_TAB:
239 if (!(dlgCode & DLGC_WANTTAB))
240 {
241 SendMessageA( hwndDlg, WM_NEXTDLGCTL,
242 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
243 return TRUE;
244 }
245 break;
246
247 case VK_RIGHT:
248 case VK_DOWN:
249 case VK_LEFT:
250 case VK_UP:
251 if (!(dlgCode & DLGC_WANTARROWS))
252 {
253 BOOL fPrevious = (msg->wParam == VK_LEFT || msg->wParam == VK_UP);
254 HWND hwndNext =
255 GetNextDlgGroupItem (hwndDlg, GetFocus(), fPrevious );
256 SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
257 return TRUE;
258 }
259 break;
260
261 case VK_ESCAPE:
262 SendMessageA( hwndDlg, WM_COMMAND, IDCANCEL,
263 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
264 return TRUE;
265
266 case VK_RETURN:
267 {
268 DWORD dw = SendMessageA( hwndDlg, DM_GETDEFID, 0, 0 );
269 if (HIWORD(dw) == DC_HASDEFID)
270 {
271 //@PF If DEFID button is disabled do not press it!
272 if (IsWindowEnabled(GetDlgItem(hwndDlg, LOWORD(dw))))
273 SendMessageA( hwndDlg, WM_COMMAND,
274 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
275 (LPARAM)GetDlgItem(hwndDlg, LOWORD(dw)));
276 }
277 else
278 {
279 SendMessageA( hwndDlg, WM_COMMAND, IDOK,
280 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
281
282 }
283
284 return TRUE;
285 }
286 }
287 *translate = TRUE;
288 break; /* case WM_KEYDOWN */
289
290 case WM_CHAR:
291 if (dlgCode & DLGC_WANTCHARS) break;
292 /* drop through */
293
294 case WM_SYSCHAR:
295 if (DIALOG_IsAccelerator( msg->hwnd, hwndDlg, msg->wParam ))
296 {
297 /* don't translate or dispatch */
298 return TRUE;
299 }
300 break;
301 }
302
303 /* If we get here, the message has not been treated specially */
304 /* and can be sent to its destination window. */
305 *dispatch = TRUE;
306 return TRUE;
307}
308//******************************************************************************
309//******************************************************************************
310BOOL WIN32API IsDialogMessageA( HWND hwndDlg, LPMSG msg)
311{
312 BOOL ret, translate, dispatch;
313 INT dlgCode;
314
315 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
316 return FALSE;
317
318 dlgCode = SendMessageA( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
319 ret = DIALOG_IsDialogMessage(hwndDlg,&translate,&dispatch,dlgCode,msg);
320 if (translate) TranslateMessage( msg );
321 if (dispatch) DispatchMessageA( msg );
322
323 return ret;
324}
325//******************************************************************************
326//******************************************************************************
327BOOL WIN32API IsDialogMessageW(HWND hwndDlg, LPMSG msg)
328{
329 BOOL ret, translate, dispatch;
330 INT dlgCode;
331
332 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
333 return FALSE;
334
335 dlgCode = SendMessageW( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
336 ret = DIALOG_IsDialogMessage(hwndDlg,&translate,&dispatch,dlgCode,msg);
337 if (translate) TranslateMessage( msg );
338 if (dispatch) DispatchMessageW( msg );
339 return ret;
340}
341//******************************************************************************
342//******************************************************************************
Note: See TracBrowser for help on using the repository browser.