1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS user32.dll
21 * FILE: win32ss/user/user32/windows/dialog.c
22 * PURPOSE: Dialog Manager
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
25 * Steven Edwards (Steven_Ed4153@yahoo.com)
26 * UPDATE HISTORY:
27 * 07-26-2003 Code ported from wine
28 * 09-05-2001 CSH Created
29 */
30
31 #include <user32.h>
32
33 WINE_DEFAULT_DEBUG_CHANNEL(user32);
34
35 /* MACROS/DEFINITIONS ********************************************************/
36
37 #define DF_END 0x0001
38 #define DF_DIALOGACTIVE 0x4000 // ReactOS
39 #define GETDLGINFO(hwnd) DIALOG_get_info(hwnd, FALSE)
40 #define GET_WORD(ptr) (*(WORD *)(ptr))
41 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
42 #define GET_LONG(ptr) (*(const LONG *)(ptr))
43 #define DLG_ISANSI 2
44
45 /* INTERNAL STRUCTS **********************************************************/
46
47 /* Dialog info structure */
48 typedef struct
49 {
50 HWND hwndFocus; /* Current control with focus */
51 HFONT hUserFont; /* Dialog font */
52 HMENU hMenu; /* Dialog menu */
53 UINT xBaseUnit; /* Dialog units (depends on the font) */
54 UINT yBaseUnit;
55 INT idResult; /* EndDialog() result / default pushbutton ID */
56 UINT flags; /* EndDialog() called for this dialog */
57 } DIALOGINFO;
58
59 /* Dialog control information */
60 typedef struct
61 {
62 DWORD style;
63 DWORD exStyle;
64 DWORD helpId;
65 short x;
66 short y;
67 short cx;
68 short cy;
69 UINT id;
70 LPCWSTR className;
71 LPCWSTR windowName;
72 BOOL windowNameFree; // ReactOS
73 LPCVOID data;
74 } DLG_CONTROL_INFO;
75
76 /* Dialog template */
77 typedef struct
78 {
79 DWORD style;
80 DWORD exStyle;
81 DWORD helpId;
82 WORD nbItems;
83 short x;
84 short y;
85 short cx;
86 short cy;
87 LPCWSTR menuName;
88 LPCWSTR className;
89 LPCWSTR caption;
90 WORD pointSize;
91 WORD weight;
92 BOOL italic;
93 LPCWSTR faceName;
94 BOOL dialogEx;
95 } DLG_TEMPLATE;
96
97 /* CheckRadioButton structure */
98 typedef struct
99 {
100 UINT firstID;
101 UINT lastID;
102 UINT checkID;
103 } RADIOGROUP;
104
105
106 /*********************************************************************
107 * dialog class descriptor
108 */
109 const struct builtin_class_descr DIALOG_builtin_class =
110 {
111 WC_DIALOG, /* name */
112 CS_SAVEBITS | CS_DBLCLKS, /* style */
113 DefDlgProcA, /* procA */
114 DefDlgProcW, /* procW */
115 DLGWINDOWEXTRA, /* extra */
116 (LPCWSTR) IDC_ARROW, /* cursor */
117 0 /* brush */
118 };
119
120
121 /* INTERNAL FUNCTIONS ********************************************************/
122
123 /***********************************************************************
124 * DIALOG_get_info
125 *
126 * Get the DIALOGINFO structure of a window, allocating it if needed
127 * and 'create' is TRUE.
128 *
129 * ReactOS
130 */
DIALOG_get_info(HWND hWnd,BOOL create)131 DIALOGINFO *DIALOG_get_info( HWND hWnd, BOOL create )
132 {
133 PWND pWindow;
134 DIALOGINFO* dlgInfo;
135
136 pWindow = ValidateHwnd( hWnd );
137 if (!pWindow)
138 {
139 return NULL;
140 }
141
142 dlgInfo = pWindow->DialogPointer;
143
144 if (!dlgInfo && create)
145 {
146 if (pWindow && pWindow->cbwndExtra >= DLGWINDOWEXTRA)
147 {
148 if (!(dlgInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dlgInfo) )))
149 return NULL;
150
151 dlgInfo->idResult = IDOK;
152 NtUserxSetDialogPointer( hWnd, dlgInfo );
153 }
154 else
155 {
156 return NULL;
157 }
158 }
159
160 return dlgInfo;
161 }
162
163 /***********************************************************************
164 * DIALOG_GetControl32
165 *
166 * Return the class and text of the control pointed to by ptr,
167 * fill the header structure and return a pointer to the next control.
168 */
DIALOG_GetControl32(const WORD * p,DLG_CONTROL_INFO * info,BOOL dialogEx)169 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
170 BOOL dialogEx )
171 {
172 if (dialogEx)
173 {
174 info->helpId = GET_DWORD(p); p += 2;
175 info->exStyle = GET_DWORD(p); p += 2;
176 info->style = GET_DWORD(p); p += 2;
177 }
178 else
179 {
180 info->helpId = 0;
181 info->style = GET_DWORD(p); p += 2;
182 info->exStyle = GET_DWORD(p); p += 2;
183 }
184 info->x = GET_WORD(p); p++;
185 info->y = GET_WORD(p); p++;
186 info->cx = GET_WORD(p); p++;
187 info->cy = GET_WORD(p); p++;
188
189 if (dialogEx)
190 {
191 /* id is 4 bytes for DIALOGEX */
192 info->id = GET_LONG(p);
193 p += 2;
194 }
195 else
196 {
197 info->id = GET_WORD(p);
198 p++;
199 }
200
201 if (GET_WORD(p) == 0xffff)
202 {
203 static const WCHAR class_names[6][10] =
204 {
205 { 'B','u','t','t','o','n', }, /* 0x80 */
206 { 'E','d','i','t', }, /* 0x81 */
207 { 'S','t','a','t','i','c', }, /* 0x82 */
208 { 'L','i','s','t','B','o','x', }, /* 0x83 */
209 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
210 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
211 };
212 WORD id = GET_WORD(p+1);
213 /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
214 if ((id >= 0x80) && (id <= 0x85)) id -= 0x80;
215 if (id <= 5)
216 {
217 info->className = class_names[id];
218 }
219 else
220 {
221 info->className = NULL;
222 /* FIXME: load other classes here? */
223 ERR("Unknown built-in class id %04x\n", id );
224 }
225 p += 2;
226 }
227 else
228 {
229 info->className = (LPCWSTR)p;
230 p += strlenW( info->className ) + 1;
231 }
232
233 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
234 {
235 //// ReactOS Rev 6478
236 info->windowName = HeapAlloc( GetProcessHeap(), 0, sizeof(L"#65535") );
237 if (info->windowName != NULL)
238 {
239 wsprintf((LPWSTR)info->windowName, L"#%u", GET_WORD(p + 1));
240 info->windowNameFree = TRUE;
241 }
242 else
243 {
244 info->windowNameFree = FALSE;
245 }
246 p += 2;
247 }
248 else
249 {
250 info->windowName = (LPCWSTR)p;
251 info->windowNameFree = FALSE;
252 p += strlenW( info->windowName ) + 1;
253 }
254
255 TRACE(" %s %s %ld, %d, %d, %d, %d, %08x, %08x, %08x\n",
256 debugstr_w( info->className ), debugstr_w( info->windowName ),
257 info->id, info->x, info->y, info->cx, info->cy,
258 info->style, info->exStyle, info->helpId );
259
260 if (GET_WORD(p))
261 {
262 info->data = p;
263 p += GET_WORD(p) / sizeof(WORD);
264 }
265 else info->data = NULL;
266 p++;
267
268 /* Next control is on dword boundary */
269 return (const WORD *)(((UINT_PTR)p + 3) & ~3);
270 }
271
272
273 /***********************************************************************
274 * DIALOG_CreateControls32
275 *
276 * Create the control windows for a dialog.
277 */
DIALOG_CreateControls32(HWND hwnd,LPCSTR template,const DLG_TEMPLATE * dlgTemplate,HINSTANCE hInst,BOOL unicode)278 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate,
279 HINSTANCE hInst, BOOL unicode )
280 {
281 DIALOGINFO * dlgInfo;
282 DLG_CONTROL_INFO info;
283 HWND hwndCtrl, hwndDefButton = 0;
284 INT items = dlgTemplate->nbItems;
285
286 if (!(dlgInfo = GETDLGINFO(hwnd))) return FALSE;
287
288 TRACE(" BEGIN\n" );
289 while (items--)
290 {
291 template = (LPCSTR)DIALOG_GetControl32( (const WORD *)template, &info,
292 dlgTemplate->dialogEx );
293 info.style &= ~WS_POPUP;
294 info.style |= WS_CHILD;
295
296 if (info.style & WS_BORDER)
297 {
298 info.style &= ~WS_BORDER;
299 info.exStyle |= WS_EX_CLIENTEDGE;
300 }
301
302 if (unicode)
303 {
304 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
305 info.className, info.windowName,
306 info.style | WS_CHILD,
307 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
308 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
309 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
310 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
311 hwnd, (HMENU)(ULONG_PTR)info.id,
312 hInst, (LPVOID)info.data );
313 }
314 else
315 {
316 LPSTR class = (LPSTR)info.className;
317 LPSTR caption = (LPSTR)info.windowName;
318
319 if (!IS_INTRESOURCE(class))
320 {
321 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL );
322 class = HeapAlloc( GetProcessHeap(), 0, len );
323 if (class != NULL)
324 WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL );
325 }
326 if (!IS_INTRESOURCE(caption))
327 {
328 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL );
329 caption = HeapAlloc( GetProcessHeap(), 0, len );
330 if (caption != NULL)
331 WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL );
332 }
333
334 if (class != NULL && caption != NULL)
335 {
336 hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY,
337 class, caption, info.style | WS_CHILD,
338 MulDiv(info.x, dlgInfo->xBaseUnit, 4),
339 MulDiv(info.y, dlgInfo->yBaseUnit, 8),
340 MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
341 MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
342 hwnd, (HMENU)(ULONG_PTR)info.id,
343 hInst, (LPVOID)info.data );
344 }
345 else
346 hwndCtrl = NULL;
347 if (!IS_INTRESOURCE(class)) HeapFree( GetProcessHeap(), 0, class );
348 if (!IS_INTRESOURCE(caption)) HeapFree( GetProcessHeap(), 0, caption );
349 }
350
351 if (info.windowNameFree)
352 {
353 HeapFree( GetProcessHeap(), 0, (LPVOID)info.windowName );
354 }
355
356 if (!hwndCtrl)
357 {
358 WARN("control %s %s creation failed\n", debugstr_w(info.className),
359 debugstr_w(info.windowName));
360 if (dlgTemplate->style & DS_NOFAILCREATE) continue;
361 return FALSE;
362 }
363
364 /* Send initialisation messages to the control */
365 if (dlgInfo->hUserFont) SendMessageW( hwndCtrl, WM_SETFONT,
366 (WPARAM)dlgInfo->hUserFont, 0 );
367 if (SendMessageW(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
368 {
369 /* If there's already a default push-button, set it back */
370 /* to normal and use this one instead. */
371 if (hwndDefButton)
372 SendMessageW( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE );
373 hwndDefButton = hwndCtrl;
374 dlgInfo->idResult = GetWindowLongPtrA( hwndCtrl, GWLP_ID );
375 }
376 }
377 TRACE(" END\n" );
378 return TRUE;
379 }
380
381
382 /***********************************************************************
383 * DIALOG_IsAccelerator
384 */
DIALOG_IsAccelerator(HWND hwnd,HWND hwndDlg,WPARAM wParam)385 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam )
386 {
387 HWND hwndControl = hwnd;
388 HWND hwndNext;
389 INT dlgCode;
390 WCHAR buffer[128];
391
392 do
393 {
394 DWORD style = GetWindowLongPtrW( hwndControl, GWL_STYLE );
395 if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
396 {
397 dlgCode = SendMessageW( hwndControl, WM_GETDLGCODE, 0, 0 );
398 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
399 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
400 {
401 /* find the accelerator key */
402 LPWSTR p = buffer - 2;
403
404 do
405 {
406 p = strchrW( p + 2, '&' );
407 }
408 while (p != NULL && p[1] == '&');
409
410 /* and check if it's the one we're looking for */
411 if (p != NULL && toupperW( p[1] ) == toupperW( wParam ) )
412 {
413 if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
414 {
415 /* set focus to the control */
416 SendMessageW( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
417 /* and bump it on to next */
418 SendMessageW( hwndDlg, WM_NEXTDLGCTL, 0, 0);
419 }
420 else if (dlgCode & DLGC_BUTTON)
421 {
422 /* send BM_CLICK message to the control */
423 SendMessageW( hwndControl, BM_CLICK, 0, 0 );
424 }
425 return TRUE;
426 }
427 }
428 hwndNext = GetWindow( hwndControl, GW_CHILD );
429 }
430 else hwndNext = 0;
431
432 if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
433
434 while (!hwndNext && hwndControl)
435 {
436 hwndControl = GetParent( hwndControl );
437 if (hwndControl == hwndDlg)
438 {
439 if(hwnd==hwndDlg) /* prevent endless loop */
440 {
441 hwndNext=hwnd;
442 break;
443 }
444 hwndNext = GetWindow( hwndDlg, GW_CHILD );
445 }
446 else
447 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
448 }
449 hwndControl = hwndNext;
450 }
451 while (hwndControl && (hwndControl != hwnd));
452
453 return FALSE;
454 }
455
456 /***********************************************************************
457 * DIALOG_FindMsgDestination
458 *
459 * The messages that IsDialogMessage sends may not go to the dialog
460 * calling IsDialogMessage if that dialog is a child, and it has the
461 * DS_CONTROL style set.
462 * We propagate up until we hit one that does not have DS_CONTROL, or
463 * whose parent is not a dialog.
464 *
465 * This is undocumented behaviour.
466 */
DIALOG_FindMsgDestination(HWND hwndDlg)467 static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
468 {
469 while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
470 {
471 PWND pWnd;
472 HWND hParent = GetParent(hwndDlg);
473 if (!hParent) break;
474 // ReactOS
475 if (!IsWindow(hParent)) break;
476
477 pWnd = ValidateHwnd(hParent);
478 // FIXME: Use pWnd->fnid == FNID_DESKTOP
479 if (!pWnd || !TestWindowProcess(pWnd) || hParent == GetDesktopWindow()) break;
480
481 if (!(pWnd->state & WNDS_DIALOGWINDOW))
482 {
483 break;
484 }
485
486 hwndDlg = hParent;
487 }
488
489 return hwndDlg;
490 }
491
492 /***********************************************************************
493 * DIALOG_DoDialogBox
494 */
DIALOG_DoDialogBox(HWND hwnd,HWND owner)495 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
496 {
497 DIALOGINFO * dlgInfo;
498 MSG msg;
499 INT retval;
500 BOOL bFirstEmpty;
501 PWND pWnd;
502
503 pWnd = ValidateHwnd(hwnd);
504 if (!pWnd) return -1;
505
506 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
507
508 bFirstEmpty = TRUE;
509 if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
510 {
511 for (;;)
512 {
513 if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
514 {
515 if (bFirstEmpty)
516 {
517 /* ShowWindow the first time the queue goes empty */
518 ShowWindow( hwnd, SW_SHOWNORMAL );
519 bFirstEmpty = FALSE;
520 }
521 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
522 {
523 /* No message present -> send ENTERIDLE and wait */
524 SendMessageW( owner, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
525 }
526 GetMessageW( &msg, 0, 0, 0 );
527 }
528
529 if (msg.message == WM_QUIT)
530 {
531 PostQuitMessage( msg.wParam );
532 if (!IsWindow( hwnd )) return 0;
533 break;
534 }
535
536 /*
537 * If the user is pressing Ctrl+C, send a WM_COPY message.
538 * Guido Pola, CORE-4829, Is there another way to check if the Dialog is a MessageBox?
539 */
540 if (msg.message == WM_KEYDOWN &&
541 pWnd->state & WNDS_MSGBOX && // Yes!
542 GetForegroundWindow() == hwnd)
543 {
544 if (msg.wParam == L'C' && GetKeyState(VK_CONTROL) < 0)
545 SendMessageW(hwnd, WM_COPY, 0, 0);
546 }
547
548 if (!IsWindow( hwnd )) return 0;
549 if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
550 {
551 TranslateMessage( &msg );
552 DispatchMessageW( &msg );
553 }
554 if (!IsWindow( hwnd )) return 0;
555 if (dlgInfo->flags & DF_END) break;
556
557 if (bFirstEmpty && msg.message == WM_TIMER)
558 {
559 ShowWindow( hwnd, SW_SHOWNORMAL );
560 bFirstEmpty = FALSE;
561 }
562 }
563 }
564 retval = dlgInfo->idResult;
565 DestroyWindow( hwnd );
566 return retval;
567 }
568
569 /***********************************************************************
570 * DIALOG_ParseTemplate32
571 *
572 * Fill a DLG_TEMPLATE structure from the dialog template, and return
573 * a pointer to the first control.
574 */
DIALOG_ParseTemplate32(LPCSTR template,DLG_TEMPLATE * result)575 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
576 {
577 const WORD *p = (const WORD *)template;
578 WORD signature;
579 WORD dlgver;
580
581 dlgver = GET_WORD(p); p++;
582 signature = GET_WORD(p); p++;
583
584 if (dlgver == 1 && signature == 0xffff) /* DIALOGEX resource */
585 {
586 result->dialogEx = TRUE;
587 result->helpId = GET_DWORD(p); p += 2;
588 result->exStyle = GET_DWORD(p); p += 2;
589 result->style = GET_DWORD(p); p += 2;
590 }
591 else
592 {
593 result->style = GET_DWORD(p - 2);
594 result->dialogEx = FALSE;
595 result->helpId = 0;
596 result->exStyle = GET_DWORD(p); p += 2;
597 }
598 result->nbItems = GET_WORD(p); p++;
599 result->x = GET_WORD(p); p++;
600 result->y = GET_WORD(p); p++;
601 result->cx = GET_WORD(p); p++;
602 result->cy = GET_WORD(p); p++;
603 TRACE("DIALOG%s %d, %d, %d, %d, %d\n",
604 result->dialogEx ? "EX" : "", result->x, result->y,
605 result->cx, result->cy, result->helpId );
606 TRACE(" STYLE 0x%08x\n", result->style );
607 TRACE(" EXSTYLE 0x%08x\n", result->exStyle );
608
609 /* Get the menu name */
610
611 switch(GET_WORD(p))
612 {
613 case 0x0000:
614 result->menuName = NULL;
615 p++;
616 break;
617 case 0xffff:
618 result->menuName = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 );
619 p += 2;
620 TRACE(" MENU %04x\n", LOWORD(result->menuName) );
621 break;
622 default:
623 result->menuName = (LPCWSTR)p;
624 TRACE(" MENU %s\n", debugstr_w(result->menuName) );
625 p += strlenW( result->menuName ) + 1;
626 break;
627 }
628
629 /* Get the class name */
630
631 switch(GET_WORD(p))
632 {
633 case 0x0000:
634 result->className = WC_DIALOG;
635 p++;
636 break;
637 case 0xffff:
638 result->className = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 );
639 p += 2;
640 TRACE(" CLASS %04x\n", LOWORD(result->className) );
641 break;
642 default:
643 result->className = (LPCWSTR)p;
644 TRACE(" CLASS %s\n", debugstr_w( result->className ));
645 p += strlenW( result->className ) + 1;
646 break;
647 }
648
649 /* Get the window caption */
650
651 result->caption = (LPCWSTR)p;
652 p += strlenW( result->caption ) + 1;
653 TRACE(" CAPTION %s\n", debugstr_w( result->caption ) );
654
655 /* Get the font name */
656
657 result->pointSize = 0;
658 result->faceName = NULL;
659 result->weight = FW_DONTCARE;
660 result->italic = FALSE;
661
662 if (result->style & DS_SETFONT)
663 {
664 result->pointSize = GET_WORD(p);
665 p++;
666
667 /* If pointSize is 0x7fff, it means that we need to use the font
668 * in NONCLIENTMETRICSW.lfMessageFont, and NOT read the weight,
669 * italic, and facename from the dialog template.
670 */
671 if (result->pointSize == 0x7fff)
672 {
673 /* We could call SystemParametersInfo here, but then we'd have
674 * to convert from pixel size to point size (which can be
675 * imprecise).
676 */
677 TRACE(" FONT: Using message box font\n");
678 }
679 else
680 {
681 if (result->dialogEx)
682 {
683 result->weight = GET_WORD(p); p++;
684 result->italic = LOBYTE(GET_WORD(p)); p++;
685 }
686 result->faceName = (LPCWSTR)p;
687 p += strlenW( result->faceName ) + 1;
688
689 TRACE(" FONT %d, %s, %d, %s\n",
690 result->pointSize, debugstr_w( result->faceName ),
691 result->weight, result->italic ? "TRUE" : "FALSE" );
692 }
693 }
694
695 /* First control is on dword boundary */
696 return (LPCSTR)((((UINT_PTR)p) + 3) & ~3);
697 }
698
699 /***********************************************************************
700 * DEFDLG_SetFocus
701 *
702 * Set the focus to a control of the dialog, selecting the text if
703 * the control is an edit dialog that has DLGC_HASSETSEL.
704 */
DEFDLG_SetFocus(HWND hwndCtrl)705 static void DEFDLG_SetFocus( HWND hwndCtrl )
706 {
707 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
708 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
709 SetFocus( hwndCtrl );
710 }
711
712
713 /***********************************************************************
714 * DEFDLG_SaveFocus
715 */
DEFDLG_SaveFocus(HWND hwnd)716 static void DEFDLG_SaveFocus( HWND hwnd )
717 {
718 DIALOGINFO *infoPtr;
719 HWND hwndFocus = GetFocus();
720
721 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
722 if (!(infoPtr = GETDLGINFO(hwnd))) return;
723 infoPtr->hwndFocus = hwndFocus;
724 /* Remove default button */
725 }
726
727
728 /***********************************************************************
729 * DEFDLG_RestoreFocus
730 */
DEFDLG_RestoreFocus(HWND hwnd,BOOL justActivate)731 static void DEFDLG_RestoreFocus( HWND hwnd, BOOL justActivate )
732 {
733 DIALOGINFO *infoPtr;
734
735 if (IsIconic( hwnd )) return;
736 if (!(infoPtr = GETDLGINFO(hwnd))) return;
737 /* Don't set the focus back to controls if EndDialog is already called.*/
738 if (infoPtr->flags & DF_END) return;
739 if (!IsWindow(infoPtr->hwndFocus) || infoPtr->hwndFocus == hwnd) {
740 if (justActivate) return;
741 /* If no saved focus control exists, set focus to the first visible,
742 non-disabled, WS_TABSTOP control in the dialog */
743 infoPtr->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
744 /* If there are no WS_TABSTOP controls, set focus to the first visible,
745 non-disabled control in the dialog */
746 if (!infoPtr->hwndFocus) infoPtr->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE );
747 if (!IsWindow( infoPtr->hwndFocus )) return;
748 }
749 if (justActivate)
750 SetFocus( infoPtr->hwndFocus );
751 else
752 DEFDLG_SetFocus( infoPtr->hwndFocus );
753
754 infoPtr->hwndFocus = NULL;
755 }
756
757 /***********************************************************************
758 * DIALOG_CreateIndirect
759 * Creates a dialog box window
760 *
761 * modal = TRUE if we are called from a modal dialog box.
762 * (it's more compatible to do it here, as under Windows the owner
763 * is never disabled if the dialog fails because of an invalid template)
764 */
DIALOG_CreateIndirect(HINSTANCE hInst,LPCVOID dlgTemplate,HWND owner,DLGPROC dlgProc,LPARAM param,BOOL unicode,HWND * modal_owner)765 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
766 HWND owner, DLGPROC dlgProc, LPARAM param,
767 BOOL unicode, HWND *modal_owner )
768 {
769 HWND hwnd;
770 RECT rect;
771 POINT pos;
772 SIZE size;
773 DLG_TEMPLATE template;
774 DIALOGINFO * dlgInfo = NULL;
775 DWORD units = GetDialogBaseUnits();
776 HWND disabled_owner = NULL;
777 HMENU hMenu = 0;
778 HFONT hUserFont = 0;
779 UINT flags = 0;
780 UINT xBaseUnit = LOWORD(units);
781 UINT yBaseUnit = HIWORD(units);
782
783 /* Parse dialog template */
784
785 if (!dlgTemplate) return 0;
786 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
787
788 /* Load menu */
789
790 if (template.menuName) hMenu = LoadMenuW( hInst, template.menuName );
791
792 /* Create custom font if needed */
793
794 if (template.style & DS_SETFONT)
795 {
796 HDC dc = GetDC(0);
797
798 if (template.pointSize == 0x7fff)
799 {
800 /* We get the message font from the non-client metrics */
801 NONCLIENTMETRICSW ncMetrics;
802
803 ncMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
804 if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
805 sizeof(NONCLIENTMETRICSW), &ncMetrics, 0))
806 {
807 hUserFont = CreateFontIndirectW( &ncMetrics.lfMessageFont );
808 }
809 }
810 else
811 {
812 /* We convert the size to pixels and then make it -ve. This works
813 * for both +ve and -ve template.pointSize */
814 int pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
815 hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
816 template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
817 PROOF_QUALITY, FF_DONTCARE,
818 template.faceName );
819 }
820
821 if (hUserFont)
822 {
823 SIZE charSize;
824 HFONT hOldFont = SelectObject( dc, hUserFont );
825 charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy );
826 if (charSize.cx)
827 {
828 xBaseUnit = charSize.cx;
829 yBaseUnit = charSize.cy;
830 }
831 SelectObject( dc, hOldFont );
832 }
833 ReleaseDC(0, dc);
834 TRACE("units = %d,%d\n", xBaseUnit, yBaseUnit );
835 }
836
837 /* Create dialog main window */
838
839 SetRect(&rect, 0, 0, MulDiv(template.cx, xBaseUnit, 4), MulDiv(template.cy, yBaseUnit, 8));
840 if (template.style & DS_CONTROL)
841 template.style &= ~(WS_CAPTION|WS_SYSMENU);
842 template.style |= DS_3DLOOK;
843 if (template.style & DS_MODALFRAME)
844 template.exStyle |= WS_EX_DLGMODALFRAME;
845 if ((template.style & DS_CONTROL) || !(template.style & WS_CHILD))
846 template.exStyle |= WS_EX_CONTROLPARENT;
847 AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle );
848 pos.x = rect.left;
849 pos.y = rect.top;
850 size.cx = rect.right - rect.left;
851 size.cy = rect.bottom - rect.top;
852
853 if (template.x == CW_USEDEFAULT16)
854 {
855 pos.x = pos.y = CW_USEDEFAULT;
856 }
857 else
858 {
859 HMONITOR monitor = 0;
860 MONITORINFO mon_info;
861
862 mon_info.cbSize = sizeof(mon_info);
863 if (template.style & DS_CENTER)
864 {
865 monitor = MonitorFromWindow( owner ? owner : GetActiveWindow(), MONITOR_DEFAULTTOPRIMARY );
866 GetMonitorInfoW( monitor, &mon_info );
867 pos.x = (mon_info.rcWork.left + mon_info.rcWork.right - size.cx) / 2;
868 pos.y = (mon_info.rcWork.top + mon_info.rcWork.bottom - size.cy) / 2;
869 }
870 else if (template.style & DS_CENTERMOUSE)
871 {
872 GetCursorPos( &pos );
873 monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
874 GetMonitorInfoW( monitor, &mon_info );
875 }
876 else
877 {
878 pos.x += MulDiv(template.x, xBaseUnit, 4);
879 pos.y += MulDiv(template.y, yBaseUnit, 8);
880 //
881 // REACTOS : Need an owner to be passed!!!
882 //
883 if (!(template.style & (WS_CHILD|DS_ABSALIGN)) && owner ) ClientToScreen( owner, &pos );
884 }
885 if ( !(template.style & WS_CHILD) )
886 {
887 INT dX, dY;
888
889 /* try to fit it into the desktop */
890
891 if (!monitor)
892 {
893 SetRect( &rect, pos.x, pos.y, pos.x + size.cx, pos.y + size.cy );
894 monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
895 GetMonitorInfoW( monitor, &mon_info );
896 }
897 if ((dX = pos.x + size.cx + GetSystemMetrics(SM_CXDLGFRAME) - mon_info.rcWork.right) > 0)
898 pos.x -= dX;
899 if ((dY = pos.y + size.cy + GetSystemMetrics(SM_CYDLGFRAME) - mon_info.rcWork.bottom) > 0)
900 pos.y -= dY;
901 if( pos.x < mon_info.rcWork.left ) pos.x = mon_info.rcWork.left;
902 if( pos.y < mon_info.rcWork.top ) pos.y = mon_info.rcWork.top;
903 }
904 }
905
906 if (modal_owner && owner)
907 {
908 HWND parent = NULL;
909 /*
910 * Owner needs to be top level window. We need to duplicate the logic from server,
911 * because we need to disable it before creating dialog window. Note that we do that
912 * even if dialog has WS_CHILD, but only for modal dialogs, which matched what
913 * Windows does.
914 */
915 while ((GetWindowLongW( owner, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD)
916 {
917 parent = GetParent( owner );
918 if (!parent || parent == GetDesktopWindow()) break;
919 owner = parent;
920 }
921 ////// Wine'ie babies need to fix your code!!!! CORE-11633
922 if (!parent) parent = GetAncestor( owner, GA_ROOT );
923
924 if (parent)
925 {
926 owner = parent;
927
928 if (IsWindowEnabled( owner ))
929 {
930 HWND captured = NULL;
931 disabled_owner = owner;
932 EnableWindow( disabled_owner, FALSE );
933
934 captured = GetCapture();
935
936 if (captured)
937 SendMessageW(captured, WM_CANCELMODE, 0, 0);
938 }
939 }
940 *modal_owner = owner;
941 }
942
943 if (unicode)
944 {
945 hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
946 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
947 owner, hMenu, hInst, NULL );
948 }
949 else
950 {
951 LPCSTR class = (LPCSTR)template.className;
952 LPCSTR caption = (LPCSTR)template.caption;
953 LPSTR class_tmp = NULL;
954 LPSTR caption_tmp = NULL;
955
956 if (!IS_INTRESOURCE(class))
957 {
958 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
959 class_tmp = HeapAlloc( GetProcessHeap(), 0, len );
960 WideCharToMultiByte( CP_ACP, 0, template.className, -1, class_tmp, len, NULL, NULL );
961 class = class_tmp;
962 }
963 if (!IS_INTRESOURCE(caption))
964 {
965 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
966 caption_tmp = HeapAlloc( GetProcessHeap(), 0, len );
967 WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption_tmp, len, NULL, NULL );
968 caption = caption_tmp;
969 }
970 hwnd = CreateWindowExA(template.exStyle, class, caption,
971 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
972 owner, hMenu, hInst, NULL );
973 HeapFree( GetProcessHeap(), 0, class_tmp );
974 HeapFree( GetProcessHeap(), 0, caption_tmp );
975 }
976
977 if (!hwnd)
978 {
979 if (hUserFont) DeleteObject( hUserFont );
980 if (hMenu) DestroyMenu( hMenu );
981 if (disabled_owner) EnableWindow( disabled_owner, TRUE );
982 return 0;
983 }
984
985 /* moved this from the top of the method to here as DIALOGINFO structure
986 will be valid only after WM_CREATE message has been handled in DefDlgProc
987 All the members of the structure get filled here using temp variables */
988 dlgInfo = DIALOG_get_info( hwnd, TRUE );
989 // ReactOS
990 if (dlgInfo == NULL)
991 {
992 if (hUserFont) DeleteObject( hUserFont );
993 if (hMenu) DestroyMenu( hMenu );
994 if (disabled_owner) EnableWindow( disabled_owner, TRUE );
995 return 0;
996 }
997 //
998 dlgInfo->hwndFocus = 0;
999 dlgInfo->hUserFont = hUserFont;
1000 dlgInfo->hMenu = hMenu;
1001 dlgInfo->xBaseUnit = xBaseUnit;
1002 dlgInfo->yBaseUnit = yBaseUnit;
1003 dlgInfo->flags = flags;
1004
1005 if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId );
1006
1007 if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
1008 else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
1009
1010 if (dlgProc && dlgInfo->hUserFont)
1011 SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
1012
1013 /* Create controls */
1014
1015 if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
1016 {
1017 /* Send initialisation messages and set focus */
1018
1019 if (dlgProc)
1020 {
1021 HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE );
1022 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
1023 if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) &&
1024 ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
1025 {
1026 /* By returning TRUE, app has requested a default focus assignment.
1027 * WM_INITDIALOG may have changed the tab order, so find the first
1028 * tabstop control again. */
1029 focus = GetNextDlgTabItem( hwnd, 0, FALSE );
1030 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
1031 if (focus)
1032 {
1033 if (SendMessageW( focus, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
1034 SendMessageW( focus, EM_SETSEL, 0, MAXLONG );
1035 SetFocus( focus );
1036 }
1037 else
1038 {
1039 if (!(template.style & WS_CHILD))
1040 SetFocus( hwnd );
1041 }
1042 }
1043 //// ReactOS see 43396, Fixes setting focus on Open and Close dialogs to the FileName edit control in OpenOffice.
1044 //// This now breaks test_SaveRestoreFocus.
1045 //DEFDLG_SaveFocus( hwnd );
1046 ////
1047 }
1048 //// ReactOS Rev 30613 & 30644
1049 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_CHILD))
1050 SendMessageW( hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
1051 ////
1052 if (template.style & WS_VISIBLE && !(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_VISIBLE))
1053 {
1054 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
1055 UpdateWindow( hwnd );
1056 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGSTART, hwnd, OBJID_WINDOW, CHILDID_SELF, 0);
1057 }
1058 return hwnd;
1059 }
1060 if (disabled_owner) EnableWindow( disabled_owner, TRUE );
1061 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGEND, hwnd, OBJID_WINDOW, CHILDID_SELF, 0);
1062 if( IsWindow(hwnd) )
1063 {
1064 DestroyWindow( hwnd );
1065 //// ReactOS
1066 if (owner)
1067 { ERR("DIALOG_CreateIndirect 1\n");
1068 if ( NtUserGetThreadState(THREADSTATE_FOREGROUNDTHREAD) && // Rule #1.
1069 !NtUserQueryWindow(owner, QUERY_WINDOW_FOREGROUND) )
1070 { ERR("DIALOG_CreateIndirect SFW\n");
1071 SetForegroundWindow(owner);
1072 }
1073 }
1074 ////
1075 }
1076 return 0;
1077 }
1078
1079
1080 /***********************************************************************
1081 * DEFDLG_FindDefButton
1082 *
1083 * Find the current default push-button.
1084 */
DEFDLG_FindDefButton(HWND hwndDlg)1085 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
1086 {
1087 HWND hwndChild, hwndTmp;
1088
1089 hwndChild = GetWindow( hwndDlg, GW_CHILD );
1090 while (hwndChild)
1091 {
1092 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
1093 break;
1094
1095 /* Recurse into WS_EX_CONTROLPARENT controls */
1096 if (GetWindowLongPtrW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT)
1097 {
1098 LONG dsStyle = GetWindowLongPtrW( hwndChild, GWL_STYLE );
1099 if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) &&
1100 (hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL)
1101 return hwndTmp;
1102 }
1103 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
1104 }
1105 return hwndChild;
1106 }
1107
1108
1109 /***********************************************************************
1110 * DEFDLG_SetDefId
1111 *
1112 * Set the default button id.
1113 */
DEFDLG_SetDefId(HWND hwndDlg,DIALOGINFO * dlgInfo,WPARAM wParam)1114 static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam)
1115 {
1116 DWORD dlgcode=0; /* initialize just to avoid a warning */
1117 HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam);
1118 INT old_id = dlgInfo->idResult;
1119
1120 dlgInfo->idResult = wParam;
1121 if (hwndNew &&
1122 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
1123 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
1124 return FALSE; /* Destination is not a push button */
1125
1126 /* Make sure the old default control is a valid push button ID */
1127 hwndOld = GetDlgItem( hwndDlg, old_id );
1128 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
1129 hwndOld = DEFDLG_FindDefButton( hwndDlg );
1130 if (hwndOld && hwndOld != hwndNew)
1131 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
1132
1133 if (hwndNew)
1134 {
1135 if(dlgcode & DLGC_UNDEFPUSHBUTTON)
1136 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
1137 }
1138 return TRUE;
1139 }
1140
1141
1142 /***********************************************************************
1143 * DEFDLG_SetDefButton
1144 *
1145 * Set the new default button to be hwndNew.
1146 */
DEFDLG_SetDefButton(HWND hwndDlg,DIALOGINFO * dlgInfo,HWND hwndNew)1147 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew )
1148 {
1149 DWORD dlgcode=0; /* initialize just to avoid a warning */
1150 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
1151
1152 if (hwndNew &&
1153 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
1154 & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON)))
1155 {
1156 /**
1157 * Need to draw only default push button rectangle.
1158 * Since the next control is not a push button, need to draw the push
1159 * button rectangle for the default control.
1160 */
1161 hwndNew = hwndOld;
1162 dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 );
1163 }
1164
1165 /* Make sure the old default control is a valid push button ID */
1166 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
1167 hwndOld = DEFDLG_FindDefButton( hwndDlg );
1168 if (hwndOld && hwndOld != hwndNew)
1169 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
1170
1171 if (hwndNew)
1172 {
1173 if(dlgcode & DLGC_UNDEFPUSHBUTTON)
1174 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
1175 }
1176 return TRUE;
1177 }
1178
1179 #ifdef __REACTOS__
DEFDLG_Reposition(HWND hwnd)1180 static void DEFDLG_Reposition(HWND hwnd)
1181 {
1182 HMONITOR hMon;
1183 MONITORINFO mi = { sizeof(mi) };
1184 RECT rc;
1185 LONG cx, cy;
1186
1187 if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD)
1188 return;
1189
1190 if (IsIconic(hwnd))
1191 return;
1192
1193 hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
1194
1195 if (!GetMonitorInfoW(hMon, &mi) || !GetWindowRect(hwnd, &rc))
1196 return;
1197
1198 cx = rc.right - rc.left;
1199 cy = rc.bottom - rc.top;
1200
1201 if (rc.right > mi.rcWork.right)
1202 {
1203 rc.right = mi.rcWork.right;
1204 rc.left = rc.right - cx;
1205 }
1206 if (rc.bottom > mi.rcWork.bottom - 4)
1207 {
1208 rc.bottom = mi.rcWork.bottom - 4;
1209 rc.top = rc.bottom - cy;
1210 }
1211
1212 if (rc.left < mi.rcWork.left)
1213 {
1214 rc.left = mi.rcWork.left;
1215 }
1216 if (rc.top < mi.rcWork.top)
1217 {
1218 rc.top = mi.rcWork.top;
1219 }
1220
1221 SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0,
1222 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE |
1223 SWP_NOZORDER);
1224 }
1225 #endif
1226 /***********************************************************************
1227 * DEFDLG_Proc
1228 *
1229 * Implementation of DefDlgProc(). Only handle messages that need special
1230 * handling for dialogs.
1231 */
DEFDLG_Proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam,DIALOGINFO * dlgInfo)1232 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
1233 LPARAM lParam, DIALOGINFO *dlgInfo )
1234 {
1235 switch(msg)
1236 {
1237 case WM_ERASEBKGND:
1238 {
1239 HBRUSH brush = GetControlColor( hwnd, hwnd, (HDC)wParam, WM_CTLCOLORDLG);
1240 if (brush)
1241 {
1242 RECT rect;
1243 HDC hdc = (HDC)wParam;
1244 GetClientRect( hwnd, &rect );
1245 DPtoLP( hdc, (LPPOINT)&rect, 2 );
1246 FillRect( hdc, &rect, brush );
1247 }
1248 return 1;
1249 }
1250 case WM_NCDESTROY:
1251 //// ReactOS
1252 dlgInfo = DIALOG_get_info(hwnd, FALSE);
1253 if (dlgInfo != NULL)
1254 {
1255 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
1256 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
1257 HeapFree( GetProcessHeap(), 0, dlgInfo );
1258 NtUserSetThreadState(0,DF_DIALOGACTIVE);
1259 NtUserxSetDialogPointer( hwnd, 0 );
1260 }
1261 /* Window clean-up */
1262 return DefWindowProcA( hwnd, msg, wParam, lParam );
1263
1264 case WM_SHOWWINDOW:
1265 if (!wParam) DEFDLG_SaveFocus( hwnd );
1266 return DefWindowProcA( hwnd, msg, wParam, lParam );
1267
1268 case WM_ACTIVATE:
1269 { // ReactOS
1270 DWORD dwSetFlag;
1271 HWND hwndparent = DIALOG_FindMsgDestination( hwnd );
1272 // if WA_CLICK/ACTIVE ? set dialog is active.
1273 dwSetFlag = wParam ? DF_DIALOGACTIVE : 0;
1274 if (hwndparent != hwnd) NtUserSetThreadState(dwSetFlag, DF_DIALOGACTIVE);
1275 }
1276 if (wParam) DEFDLG_RestoreFocus( hwnd, TRUE );
1277 else DEFDLG_SaveFocus( hwnd );
1278 return 0;
1279
1280 case WM_SETFOCUS:
1281 DEFDLG_RestoreFocus( hwnd, FALSE );
1282 return 0;
1283
1284 case DM_SETDEFID:
1285 if (dlgInfo && !(dlgInfo->flags & DF_END))
1286 DEFDLG_SetDefId( hwnd, dlgInfo, wParam );
1287 return 1;
1288
1289 case DM_GETDEFID:
1290 if (dlgInfo && !(dlgInfo->flags & DF_END))
1291 {
1292 HWND hwndDefId;
1293 if (dlgInfo->idResult)
1294 return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
1295 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
1296 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
1297 }
1298 return 0;
1299
1300 #ifdef __REACTOS__
1301 case DM_REPOSITION:
1302 DEFDLG_Reposition(hwnd);
1303 return 0;
1304 #endif
1305 case WM_NEXTDLGCTL:
1306 if (dlgInfo)
1307 {
1308 HWND hwndDest = (HWND)wParam;
1309 if (!lParam)
1310 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
1311 if (hwndDest) DEFDLG_SetFocus( hwndDest );
1312 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
1313 }
1314 return 0;
1315
1316 case WM_ENTERMENULOOP:
1317 case WM_LBUTTONDOWN:
1318 case WM_NCLBUTTONDOWN:
1319 {
1320 HWND hwndFocus = GetFocus();
1321 if (hwndFocus)
1322 {
1323 /* always make combo box hide its listbox control */
1324 if (!SendMessageW( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
1325 SendMessageW( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
1326 }
1327 }
1328 return DefWindowProcA( hwnd, msg, wParam, lParam );
1329
1330 case WM_GETFONT:
1331 return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
1332
1333 case WM_CLOSE:
1334 PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
1335 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
1336 return 0;
1337 }
1338 return 0;
1339 }
1340
1341 /***********************************************************************
1342 * DEFDLG_Epilog
1343 */
DEFDLG_Epilog(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam,BOOL fResult,BOOL fAnsi)1344 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fResult, BOOL fAnsi)
1345 {
1346 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
1347 msg == WM_CTLCOLOR)
1348 {
1349 if (fResult) return fResult;
1350
1351 return fAnsi ? DefWindowProcA(hwnd, msg, wParam, lParam):
1352 DefWindowProcW(hwnd, msg, wParam, lParam);
1353 }
1354 if ( msg == WM_COMPAREITEM ||
1355 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
1356 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
1357 return fResult;
1358
1359 return GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
1360 }
1361
1362 /***********************************************************************
1363 * DIALOG_GetNextTabItem
1364 *
1365 * Helper for GetNextDlgTabItem
1366 */
DIALOG_GetNextTabItem(HWND hwndMain,HWND hwndDlg,HWND hwndCtrl,BOOL fPrevious)1367 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1368 {
1369 LONG dsStyle;
1370 LONG exStyle;
1371 UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
1372 HWND retWnd = 0;
1373 HWND hChildFirst = 0;
1374
1375 if(!hwndCtrl)
1376 {
1377 hChildFirst = GetWindow(hwndDlg,GW_CHILD);
1378 if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
1379 }
1380 else if (IsChild( hwndMain, hwndCtrl ))
1381 {
1382 hChildFirst = GetWindow(hwndCtrl,wndSearch);
1383 if(!hChildFirst)
1384 {
1385 if(GetParent(hwndCtrl) != hwndMain)
1386 /* i.e. if we are not at the top level of the recursion */
1387 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
1388 else
1389 hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST);
1390 }
1391 }
1392
1393 while(hChildFirst)
1394 {
1395 dsStyle = GetWindowLongPtrA(hChildFirst,GWL_STYLE);
1396 exStyle = GetWindowLongPtrA(hChildFirst,GWL_EXSTYLE);
1397 if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1398 {
1399 HWND retWnd;
1400 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
1401 if (retWnd) return (retWnd);
1402 }
1403 else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1404 {
1405 return (hChildFirst);
1406 }
1407 hChildFirst = GetWindow(hChildFirst,wndSearch);
1408 }
1409 if(hwndCtrl)
1410 {
1411 HWND hParent = GetParent(hwndCtrl);
1412 while(hParent)
1413 {
1414 if(hParent == hwndMain) break;
1415 retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
1416 if(retWnd) break;
1417 hParent = GetParent(hParent);
1418 }
1419 if(!retWnd)
1420 retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
1421 }
1422 return retWnd ? retWnd : hwndCtrl;
1423 }
1424
1425
1426 /**********************************************************************
1427 * DIALOG_DlgDirListW
1428 *
1429 * Helper function for DlgDirList*W
1430 */
DIALOG_DlgDirListW(HWND hDlg,LPWSTR spec,INT idLBox,INT idStatic,UINT attrib,BOOL combo)1431 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1432 INT idStatic, UINT attrib, BOOL combo )
1433 {
1434 HWND hwnd;
1435 LPWSTR orig_spec = spec;
1436 WCHAR any[] = {'*','.','*',0};
1437 WCHAR star[] = {'*',0};
1438
1439 #define SENDMSG(msg,wparam,lparam) \
1440 ((attrib & DDL_POSTMSGS) ? PostMessageW( hwnd, msg, wparam, lparam ) \
1441 : SendMessageW( hwnd, msg, wparam, lparam ))
1442
1443 TRACE("%p %s %d %d %04x\n", hDlg, debugstr_w(spec), idLBox, idStatic, attrib );
1444
1445 /* If the path exists and is a directory, chdir to it */
1446 if (!spec || !spec[0] || SetCurrentDirectoryW( spec )) spec = star;
1447 else
1448 {
1449 WCHAR *p, *p2;
1450
1451 if (!strchrW(spec, '*') && !strchrW(spec, '?'))
1452 {
1453 SetLastError(ERROR_NO_WILDCARD_CHARACTERS);
1454 return FALSE;
1455 }
1456 p = spec;
1457 if ((p2 = strchrW( p, ':' ))) p = p2 + 1;
1458 if ((p2 = strrchrW( p, '\\' ))) p = p2;
1459 if ((p2 = strrchrW( p, '/' ))) p = p2;
1460 if (p != spec)
1461 {
1462 WCHAR sep = *p;
1463 *p = 0;
1464 if (!SetCurrentDirectoryW( spec ))
1465 {
1466 *p = sep; /* Restore the original spec */
1467 return FALSE;
1468 }
1469 spec = p + 1;
1470 }
1471 }
1472
1473 TRACE( "mask=%s\n", spec );
1474
1475 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1476 {
1477 if (attrib == DDL_DRIVES) attrib |= DDL_EXCLUSIVE;
1478
1479 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1480 if (attrib & DDL_DIRECTORY)
1481 {
1482 if (!(attrib & DDL_EXCLUSIVE))
1483 {
1484 SENDMSG( combo ? CB_DIR : LB_DIR,
1485 attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1486 (LPARAM)spec );
1487 }
1488 SENDMSG( combo ? CB_DIR : LB_DIR,
1489 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1490 (LPARAM)any );
1491 }
1492 else
1493 {
1494 SENDMSG( combo ? CB_DIR : LB_DIR, attrib, (LPARAM)spec );
1495 }
1496 }
1497
1498 /* Convert path specification to uppercase */
1499 if (spec) CharUpperW(spec);
1500
1501 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1502 {
1503 WCHAR temp[MAX_PATH];
1504 GetCurrentDirectoryW( sizeof(temp)/sizeof(WCHAR), temp );
1505 CharLowerW( temp );
1506 /* Can't use PostMessage() here, because the string is on the stack */
1507 SetDlgItemTextW( hDlg, idStatic, temp );
1508 }
1509
1510 if (orig_spec && (spec != orig_spec))
1511 {
1512 /* Update the original file spec */
1513 WCHAR *p = spec;
1514 while ((*orig_spec++ = *p++));
1515 }
1516
1517 return TRUE;
1518 #undef SENDMSG
1519 }
1520
1521
1522 /**********************************************************************
1523 * DIALOG_DlgDirListA
1524 *
1525 * Helper function for DlgDirList*A
1526 */
DIALOG_DlgDirListA(HWND hDlg,LPSTR spec,INT idLBox,INT idStatic,UINT attrib,BOOL combo)1527 static INT DIALOG_DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox,
1528 INT idStatic, UINT attrib, BOOL combo )
1529 {
1530 if (spec)
1531 {
1532 INT ret, len = MultiByteToWideChar( CP_ACP, 0, spec, -1, NULL, 0 );
1533 LPWSTR specW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1534 if (specW == NULL)
1535 return FALSE;
1536 MultiByteToWideChar( CP_ACP, 0, spec, -1, specW, len );
1537 ret = DIALOG_DlgDirListW( hDlg, specW, idLBox, idStatic, attrib, combo );
1538 WideCharToMultiByte( CP_ACP, 0, specW, -1, spec, 0x7fffffff, NULL, NULL );
1539 HeapFree( GetProcessHeap(), 0, specW );
1540 return ret;
1541 }
1542 return DIALOG_DlgDirListW( hDlg, NULL, idLBox, idStatic, attrib, combo );
1543 }
1544
1545 /**********************************************************************
1546 * DIALOG_DlgDirSelect
1547 *
1548 * Helper function for DlgDirSelect*
1549 */
DIALOG_DlgDirSelect(HWND hwnd,LPWSTR str,INT len,INT id,BOOL unicode,BOOL combo)1550 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPWSTR str, INT len,
1551 INT id, BOOL unicode, BOOL combo )
1552 {
1553 WCHAR *buffer, *ptr;
1554 INT item, size;
1555 BOOL ret;
1556 HWND listbox = GetDlgItem( hwnd, id );
1557
1558 TRACE("%p %s %d\n", hwnd, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str), id );
1559 if (!listbox) return FALSE;
1560
1561 item = SendMessageW(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 );
1562 if (item == LB_ERR) return FALSE;
1563
1564 size = SendMessageW(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, item, 0 );
1565 if (size == LB_ERR) return FALSE;
1566
1567 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size+2) * sizeof(WCHAR) ))) return FALSE;
1568
1569 SendMessageW( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer );
1570
1571 if ((ret = (buffer[0] == '['))) /* drive or directory */
1572 {
1573 if (buffer[1] == '-') /* drive */
1574 {
1575 buffer[3] = ':';
1576 buffer[4] = 0;
1577 ptr = buffer + 2;
1578 }
1579 else
1580 {
1581 buffer[strlenW(buffer)-1] = '\\';
1582 ptr = buffer + 1;
1583 }
1584 }
1585 else
1586 {
1587 /* Filenames without a dot extension must have one tacked at the end */
1588 if (strchrW(buffer, '.') == NULL)
1589 {
1590 buffer[strlenW(buffer)+1] = '\0';
1591 buffer[strlenW(buffer)] = '.';
1592 }
1593 ptr = buffer;
1594 }
1595
1596 if (!unicode)
1597 {
1598 if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, ptr, -1, (LPSTR)str, len, 0, 0 ))
1599 ((LPSTR)str)[len-1] = 0;
1600 }
1601 else lstrcpynW( str, ptr, len );
1602 HeapFree( GetProcessHeap(), 0, buffer );
1603 TRACE("Returning %d %s\n", ret, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str) );
1604 return ret;
1605 }
1606
1607
1608 /* FUNCTIONS *****************************************************************/
1609
1610 /*
1611 * @implemented
1612 */
1613 HWND
1614 WINAPI
CreateDialogIndirectParamAorW(HINSTANCE hInstance,LPCDLGTEMPLATE lpTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM lParamInit,DWORD Flags)1615 CreateDialogIndirectParamAorW(
1616 HINSTANCE hInstance,
1617 LPCDLGTEMPLATE lpTemplate,
1618 HWND hWndParent,
1619 DLGPROC lpDialogFunc,
1620 LPARAM lParamInit,
1621 DWORD Flags)
1622 {
1623 /* FIXME:
1624 * This function might be obsolete since I don't think it is exported by NT
1625 * Also wine has one more parameter identifying weather it should call
1626 * the function with unicode or not
1627 */
1628 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit , Flags == DLG_ISANSI ? FALSE : TRUE, NULL );
1629 }
1630
1631
1632 /*
1633 * @implemented
1634 */
1635 HWND
1636 WINAPI
CreateDialogIndirectParamA(HINSTANCE hInstance,LPCDLGTEMPLATE lpTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM lParamInit)1637 CreateDialogIndirectParamA(
1638 HINSTANCE hInstance,
1639 LPCDLGTEMPLATE lpTemplate,
1640 HWND hWndParent,
1641 DLGPROC lpDialogFunc,
1642 LPARAM lParamInit)
1643 {
1644 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, DLG_ISANSI);
1645 }
1646
1647
1648 /*
1649 * @implemented
1650 */
1651 HWND
1652 WINAPI
CreateDialogIndirectParamW(HINSTANCE hInstance,LPCDLGTEMPLATE lpTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM lParamInit)1653 CreateDialogIndirectParamW(
1654 HINSTANCE hInstance,
1655 LPCDLGTEMPLATE lpTemplate,
1656 HWND hWndParent,
1657 DLGPROC lpDialogFunc,
1658 LPARAM lParamInit)
1659 {
1660 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, 0);
1661 }
1662
1663
1664 /*
1665 * @implemented
1666 */
1667 HWND
1668 WINAPI
CreateDialogParamA(HINSTANCE hInstance,LPCSTR lpTemplateName,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1669 CreateDialogParamA(
1670 HINSTANCE hInstance,
1671 LPCSTR lpTemplateName,
1672 HWND hWndParent,
1673 DLGPROC lpDialogFunc,
1674 LPARAM dwInitParam)
1675 {
1676 HRSRC hrsrc;
1677 LPCDLGTEMPLATE ptr;
1678
1679 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1680 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1681 return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1682 }
1683
1684
1685 /*
1686 * @implemented
1687 */
1688 HWND
1689 WINAPI
CreateDialogParamW(HINSTANCE hInstance,LPCWSTR lpTemplateName,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1690 CreateDialogParamW(
1691 HINSTANCE hInstance,
1692 LPCWSTR lpTemplateName,
1693 HWND hWndParent,
1694 DLGPROC lpDialogFunc,
1695 LPARAM dwInitParam)
1696 {
1697 HRSRC hrsrc;
1698 LPCDLGTEMPLATE ptr;
1699
1700 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1701 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1702 return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1703 }
1704
1705
1706 /*
1707 * @implemented
1708 */
1709 LRESULT
1710 WINAPI
DefDlgProcA(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)1711 DefDlgProcA(
1712 HWND hDlg,
1713 UINT Msg,
1714 WPARAM wParam,
1715 LPARAM lParam)
1716 {
1717 DIALOGINFO *dlgInfo;
1718 WNDPROC dlgproc;
1719 BOOL result = FALSE;
1720
1721 /* Perform DIALOGINFO initialization if not done */
1722 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass.
1723
1724 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 );
1725
1726 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC )))
1727 {
1728 /* Call dialog procedure */
1729 result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam );
1730 }
1731
1732 if (!result && IsWindow(hDlg))
1733 {
1734 /* callback didn't process this message */
1735
1736 switch(Msg)
1737 {
1738 case WM_ERASEBKGND:
1739 case WM_SHOWWINDOW:
1740 case WM_ACTIVATE:
1741 case WM_SETFOCUS:
1742 case DM_SETDEFID:
1743 case DM_GETDEFID:
1744 #ifdef __REACTOS__
1745 case DM_REPOSITION:
1746 #endif
1747 case WM_NEXTDLGCTL:
1748 case WM_GETFONT:
1749 case WM_CLOSE:
1750 case WM_NCDESTROY:
1751 case WM_ENTERMENULOOP:
1752 case WM_LBUTTONDOWN:
1753 case WM_NCLBUTTONDOWN:
1754 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1755 case WM_INITDIALOG:
1756 case WM_VKEYTOITEM:
1757 case WM_COMPAREITEM:
1758 case WM_CHARTOITEM:
1759 break;
1760
1761 default:
1762 return DefWindowProcA( hDlg, Msg, wParam, lParam );
1763 }
1764 }
1765 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, TRUE);
1766 }
1767
1768
1769 /*
1770 * @implemented
1771 */
1772 LRESULT
1773 WINAPI
DefDlgProcW(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)1774 DefDlgProcW(
1775 HWND hDlg,
1776 UINT Msg,
1777 WPARAM wParam,
1778 LPARAM lParam)
1779 {
1780 DIALOGINFO *dlgInfo;
1781 WNDPROC dlgproc;
1782 BOOL result = FALSE;
1783
1784 /* Perform DIALOGINFO initialization if not done */
1785 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass.
1786
1787 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 );
1788
1789 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC )))
1790 {
1791 /* Call dialog procedure */
1792 result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam );
1793 }
1794
1795 if (!result && IsWindow(hDlg))
1796 {
1797 /* callback didn't process this message */
1798
1799 switch(Msg)
1800 {
1801 case WM_ERASEBKGND:
1802 case WM_SHOWWINDOW:
1803 case WM_ACTIVATE:
1804 case WM_SETFOCUS:
1805 case DM_SETDEFID:
1806 case DM_GETDEFID:
1807 #ifdef __REACTOS__
1808 case DM_REPOSITION:
1809 #endif
1810 case WM_NEXTDLGCTL:
1811 case WM_GETFONT:
1812 case WM_CLOSE:
1813 case WM_NCDESTROY:
1814 case WM_ENTERMENULOOP:
1815 case WM_LBUTTONDOWN:
1816 case WM_NCLBUTTONDOWN:
1817 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1818 case WM_INITDIALOG:
1819 case WM_VKEYTOITEM:
1820 case WM_COMPAREITEM:
1821 case WM_CHARTOITEM:
1822 break;
1823
1824 default:
1825 return DefWindowProcW( hDlg, Msg, wParam, lParam );
1826 }
1827 }
1828 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, FALSE);
1829 }
1830
1831
1832 /*
1833 * @implemented
1834 */
1835 INT_PTR
1836 WINAPI
DialogBoxIndirectParamAorW(HINSTANCE hInstance,LPCDLGTEMPLATE hDialogTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam,DWORD Flags)1837 DialogBoxIndirectParamAorW(
1838 HINSTANCE hInstance,
1839 LPCDLGTEMPLATE hDialogTemplate,
1840 HWND hWndParent,
1841 DLGPROC lpDialogFunc,
1842 LPARAM dwInitParam,
1843 DWORD Flags)
1844 {
1845 /* FIXME:
1846 * This function might be obsolete since I don't think it is exported by NT
1847 * Also wine has one more parameter identifying weather it should call
1848 * the function with unicode or not
1849 */
1850 HWND hWnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, Flags == DLG_ISANSI ? FALSE : TRUE, &hWndParent );
1851 if (hWnd) return DIALOG_DoDialogBox( hWnd, hWndParent );
1852 return -1;
1853 }
1854
1855
1856 /*
1857 * @implemented
1858 */
1859 INT_PTR
1860 WINAPI
DialogBoxIndirectParamA(HINSTANCE hInstance,LPCDLGTEMPLATE hDialogTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1861 DialogBoxIndirectParamA(
1862 HINSTANCE hInstance,
1863 LPCDLGTEMPLATE hDialogTemplate,
1864 HWND hWndParent,
1865 DLGPROC lpDialogFunc,
1866 LPARAM dwInitParam)
1867 {
1868 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, DLG_ISANSI);
1869 }
1870
1871
1872 /*
1873 * @implemented
1874 */
1875 INT_PTR
1876 WINAPI
DialogBoxIndirectParamW(HINSTANCE hInstance,LPCDLGTEMPLATE hDialogTemplate,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1877 DialogBoxIndirectParamW(
1878 HINSTANCE hInstance,
1879 LPCDLGTEMPLATE hDialogTemplate,
1880 HWND hWndParent,
1881 DLGPROC lpDialogFunc,
1882 LPARAM dwInitParam)
1883 {
1884 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, 0);
1885 }
1886
1887
1888 /*
1889 * @implemented
1890 */
1891 INT_PTR
1892 WINAPI
DialogBoxParamA(HINSTANCE hInstance,LPCSTR lpTemplateName,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1893 DialogBoxParamA(
1894 HINSTANCE hInstance,
1895 LPCSTR lpTemplateName,
1896 HWND hWndParent,
1897 DLGPROC lpDialogFunc,
1898 LPARAM dwInitParam)
1899 {
1900 HWND hwnd;
1901 HRSRC hrsrc;
1902 LPCDLGTEMPLATE ptr;
1903 //// ReactOS rev 33532
1904 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG )) ||
1905 !(ptr = LoadResource(hInstance, hrsrc)))
1906 {
1907 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
1908 return -1;
1909 }
1910 if (hWndParent != NULL && !IsWindow(hWndParent))
1911 {
1912 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1913 return 0;
1914 }
1915 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, &hWndParent );
1916 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1917 return -1;
1918 }
1919
1920
1921 /*
1922 * @implemented
1923 */
1924 INT_PTR
1925 WINAPI
DialogBoxParamW(HINSTANCE hInstance,LPCWSTR lpTemplateName,HWND hWndParent,DLGPROC lpDialogFunc,LPARAM dwInitParam)1926 DialogBoxParamW(
1927 HINSTANCE hInstance,
1928 LPCWSTR lpTemplateName,
1929 HWND hWndParent,
1930 DLGPROC lpDialogFunc,
1931 LPARAM dwInitParam)
1932 {
1933 HWND hwnd;
1934 HRSRC hrsrc;
1935 LPCDLGTEMPLATE ptr;
1936 //// ReactOS rev 33532
1937 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG )) ||
1938 !(ptr = LoadResource(hInstance, hrsrc)))
1939 {
1940 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
1941 return -1;
1942 }
1943 if (hWndParent != NULL && !IsWindow(hWndParent))
1944 {
1945 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1946 return 0;
1947 }
1948 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, &hWndParent );
1949 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1950 return -1;
1951 }
1952
1953
1954 /*
1955 * @implemented
1956 */
1957 int
1958 WINAPI
DlgDirListA(HWND hDlg,LPSTR lpPathSpec,int nIDListBox,int nIDStaticPath,UINT uFileType)1959 DlgDirListA(
1960 HWND hDlg,
1961 LPSTR lpPathSpec,
1962 int nIDListBox,
1963 int nIDStaticPath,
1964 UINT uFileType)
1965 {
1966 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1967 }
1968
1969
1970 /*
1971 * @implemented
1972 */
1973 int
1974 WINAPI
DlgDirListComboBoxA(HWND hDlg,LPSTR lpPathSpec,int nIDComboBox,int nIDStaticPath,UINT uFiletype)1975 DlgDirListComboBoxA(
1976 HWND hDlg,
1977 LPSTR lpPathSpec,
1978 int nIDComboBox,
1979 int nIDStaticPath,
1980 UINT uFiletype)
1981 {
1982 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE );
1983 }
1984
1985
1986 /*
1987 * @implemented
1988 */
1989 int
1990 WINAPI
DlgDirListComboBoxW(HWND hDlg,LPWSTR lpPathSpec,int nIDComboBox,int nIDStaticPath,UINT uFiletype)1991 DlgDirListComboBoxW(
1992 HWND hDlg,
1993 LPWSTR lpPathSpec,
1994 int nIDComboBox,
1995 int nIDStaticPath,
1996 UINT uFiletype)
1997 {
1998 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE );
1999 }
2000
2001
2002 /*
2003 * @implemented
2004 */
2005 int
2006 WINAPI
DlgDirListW(HWND hDlg,LPWSTR lpPathSpec,int nIDListBox,int nIDStaticPath,UINT uFileType)2007 DlgDirListW(
2008 HWND hDlg,
2009 LPWSTR lpPathSpec,
2010 int nIDListBox,
2011 int nIDStaticPath,
2012 UINT uFileType)
2013 {
2014 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
2015 }
2016
2017
2018 /*
2019 * @implemented
2020 */
2021 BOOL
2022 WINAPI
DlgDirSelectComboBoxExA(HWND hDlg,LPSTR lpString,int nCount,int nIDComboBox)2023 DlgDirSelectComboBoxExA(
2024 HWND hDlg,
2025 LPSTR lpString,
2026 int nCount,
2027 int nIDComboBox)
2028 {
2029 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, FALSE, TRUE );
2030 }
2031
2032
2033 /*
2034 * @implemented
2035 */
2036 BOOL
2037 WINAPI
DlgDirSelectComboBoxExW(HWND hDlg,LPWSTR lpString,int nCount,int nIDComboBox)2038 DlgDirSelectComboBoxExW(
2039 HWND hDlg,
2040 LPWSTR lpString,
2041 int nCount,
2042 int nIDComboBox)
2043 {
2044 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, TRUE, TRUE );
2045 }
2046
2047
2048 /*
2049 * @implemented
2050 */
2051 BOOL
2052 WINAPI
DlgDirSelectExA(HWND hDlg,LPSTR lpString,int nCount,int nIDListBox)2053 DlgDirSelectExA(
2054 HWND hDlg,
2055 LPSTR lpString,
2056 int nCount,
2057 int nIDListBox)
2058 {
2059 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDListBox, FALSE, FALSE );
2060 }
2061
2062
2063 /*
2064 * @implemented
2065 */
2066 BOOL
2067 WINAPI
DlgDirSelectExW(HWND hDlg,LPWSTR lpString,int nCount,int nIDListBox)2068 DlgDirSelectExW(
2069 HWND hDlg,
2070 LPWSTR lpString,
2071 int nCount,
2072 int nIDListBox)
2073 {
2074 return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, TRUE, FALSE );
2075 }
2076
2077
2078 /*
2079 * @implemented Modified for ReactOS. Do not Port Sync!!!
2080 */
2081 BOOL
2082 WINAPI
EndDialog(HWND hwnd,INT_PTR retval)2083 EndDialog(
2084 HWND hwnd,
2085 INT_PTR retval)
2086 {
2087 DIALOGINFO * dlgInfo;
2088 HWND owner;
2089 BOOL wasActive;
2090
2091 TRACE("%p %ld\n", hwnd, retval );
2092
2093 if (!(dlgInfo = GETDLGINFO(hwnd)))
2094 {
2095 ERR("got invalid window handle (%p); buggy app !?\n", hwnd);
2096 return FALSE;
2097 }
2098 wasActive = (hwnd == GetActiveWindow());
2099 dlgInfo->idResult = retval;
2100 dlgInfo->flags |= DF_END;
2101
2102 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD)
2103 {
2104 owner = GetAncestor( hwnd, GA_PARENT);
2105 }
2106 else
2107 owner = GetWindow( hwnd, GW_OWNER );
2108
2109 if (owner)
2110 EnableWindow( owner, TRUE );
2111
2112 /* Windows sets the focus to the dialog itself in EndDialog */
2113
2114 if (wasActive && IsChild(hwnd, GetFocus()))
2115 SetFocus( hwnd );
2116
2117 /* Don't have to send a ShowWindow(SW_HIDE), just do
2118 SetWindowPos with SWP_HIDEWINDOW as done in Windows */
2119
2120 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
2121 | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
2122
2123 if (wasActive && owner)
2124 {
2125 /* If this dialog was given an owner then set the focus to that owner. */
2126 SetActiveWindow(owner);
2127 }
2128 else if (hwnd == GetActiveWindow()) // Check it again!
2129 {
2130 NtUserCallNoParam(NOPARAM_ROUTINE_ZAPACTIVEANDFOUS);
2131 }
2132
2133 /* unblock dialog loop */
2134 PostMessageA(hwnd, WM_NULL, 0, 0);
2135 return TRUE;
2136 }
2137
2138
2139 /*
2140 * @implemented
2141 */
2142 LONG
2143 WINAPI
GetDialogBaseUnits(VOID)2144 GetDialogBaseUnits(VOID)
2145 {
2146 static DWORD units;
2147
2148 if (!units)
2149 {
2150 HDC hdc;
2151 SIZE size;
2152
2153 if ((hdc = GetDC(0)))
2154 {
2155 size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
2156 if (size.cx) units = MAKELONG( size.cx, size.cy );
2157 ReleaseDC( 0, hdc );
2158 }
2159 }
2160 return units;
2161 }
2162
2163
2164 /*
2165 * @implemented
2166 */
2167 int
2168 WINAPI
GetDlgCtrlID(HWND hwndCtl)2169 GetDlgCtrlID(
2170 HWND hwndCtl)
2171 {
2172 return GetWindowLongPtrW( hwndCtl, GWLP_ID );
2173 }
2174
2175
2176 /*
2177 * @implemented
2178 */
2179 HWND
2180 WINAPI
GetDlgItem(HWND hDlg,int nIDDlgItem)2181 GetDlgItem(
2182 HWND hDlg,
2183 int nIDDlgItem)
2184 {
2185 int i;
2186 HWND *list;
2187 HWND ret = 0;
2188
2189 if (!hDlg) return 0;
2190
2191 list = WIN_ListChildren(hDlg);
2192 if (!list) return 0;
2193
2194 for (i = 0; list[i]; i++) if (GetWindowLongPtrW(list[i], GWLP_ID) == nIDDlgItem) break;
2195 ret = list[i];
2196 HeapFree(GetProcessHeap(), 0, list);
2197 // if (!ret) SetLastError(ERROR_CONTROL_ID_NOT_FOUND);
2198 return ret;
2199 }
2200
2201
2202 /*
2203 * @implemented
2204 */
2205 UINT
2206 WINAPI
GetDlgItemInt(HWND hDlg,int nIDDlgItem,BOOL * lpTranslated,BOOL bSigned)2207 GetDlgItemInt(
2208 HWND hDlg,
2209 int nIDDlgItem,
2210 BOOL *lpTranslated,
2211 BOOL bSigned)
2212 {
2213 char str[30];
2214 char * endptr;
2215 LONG_PTR result = 0;
2216
2217 if (lpTranslated) *lpTranslated = FALSE;
2218 if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str))
2219 return 0;
2220 if (bSigned)
2221 {
2222 result = strtol( str, &endptr, 10 );
2223 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
2224 return 0;
2225 if (((result == LONG_MIN) || (result == LONG_MAX)))
2226 return 0;
2227 }
2228 else
2229 {
2230 result = strtoul( str, &endptr, 10 );
2231 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
2232 return 0;
2233 if (result == ULONG_MAX) return 0;
2234 }
2235 if (lpTranslated) *lpTranslated = TRUE;
2236 return (UINT)result;
2237 }
2238
2239
2240 /*
2241 * @implemented
2242 */
2243 UINT
2244 WINAPI
GetDlgItemTextA(HWND hDlg,int nIDDlgItem,LPSTR lpString,int nMaxCount)2245 GetDlgItemTextA(
2246 HWND hDlg,
2247 int nIDDlgItem,
2248 LPSTR lpString,
2249 int nMaxCount)
2250 {
2251 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
2252 if ( hWnd ) return GetWindowTextA(hWnd, lpString, nMaxCount);
2253 if ( nMaxCount ) lpString[0] = '\0';
2254 return 0;
2255 }
2256
2257
2258 /*
2259 * @implemented
2260 */
2261 UINT
2262 WINAPI
GetDlgItemTextW(HWND hDlg,int nIDDlgItem,LPWSTR lpString,int nMaxCount)2263 GetDlgItemTextW(
2264 HWND hDlg,
2265 int nIDDlgItem,
2266 LPWSTR lpString,
2267 int nMaxCount)
2268 {
2269 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
2270 if ( hWnd ) return GetWindowTextW(hWnd, lpString, nMaxCount);
2271 if ( nMaxCount ) lpString[0] = '\0';
2272 return 0;
2273 }
2274
2275 /*
2276 * @implemented
2277 */
2278 HWND
2279 WINAPI
GetNextDlgGroupItem(HWND hDlg,HWND hCtl,BOOL bPrevious)2280 GetNextDlgGroupItem(
2281 HWND hDlg,
2282 HWND hCtl,
2283 BOOL bPrevious)
2284 {
2285 HWND hwnd, hwndNext, retvalue, hwndLastGroup = 0;
2286 BOOL fLooped=FALSE;
2287 BOOL fSkipping=FALSE;
2288
2289 if (hDlg == hCtl) hCtl = NULL;
2290 if (!hCtl && bPrevious) return 0;
2291
2292 /* if the hwndCtrl is the child of the control in the hwndDlg,
2293 * then the hwndDlg has to be the parent of the hwndCtrl */
2294
2295 if (hCtl)
2296 {
2297 if (!IsChild (hDlg, hCtl)) return 0;
2298 /* Make sure hwndCtrl is a top-level child */
2299 }
2300 else
2301 {
2302 /* No ctrl specified -> start from the beginning */
2303 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
2304 /* MSDN is wrong. bPrevious does not result in the last child */
2305
2306 /* Maybe that first one is valid. If so then we don't want to skip it*/
2307 if ((GetWindowLongPtrW( hCtl, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
2308 {
2309 return hCtl;
2310 }
2311 }
2312
2313 /* Always go forward around the group and list of controls; for the
2314 * previous control keep track; for the next break when you find one
2315 */
2316 retvalue = hCtl;
2317 hwnd = hCtl;
2318 while (1)
2319 {
2320 hwndNext = GetWindow (hwnd, GW_HWNDNEXT);
2321 while (!hwndNext)
2322 {
2323 /* Climb out until there is a next sibling of the ancestor or we
2324 * reach the top (in which case we loop back to the start)
2325 */
2326 if (hDlg == GetParent (hwnd))
2327 {
2328 /* Wrap around to the beginning of the list, within the same
2329 * group. (Once only)
2330 */
2331 if (fLooped) goto end;
2332 fLooped = TRUE;
2333 hwndNext = GetWindow (hDlg, GW_CHILD);
2334 }
2335 else
2336 {
2337 hwnd = GetParent (hwnd);
2338 hwndNext = GetWindow (hwnd, GW_HWNDNEXT);
2339 }
2340 }
2341 hwnd = hwndNext;
2342
2343 /* Wander down the leading edge of controlparents */
2344 while ( (GetWindowLongPtrW (hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) &&
2345 ((GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) &&
2346 (hwndNext = GetWindow (hwnd, GW_CHILD)))
2347 hwnd = hwndNext;
2348 /* Question. If the control is a control parent but either has no
2349 * children or is not visible/enabled then if it has a WS_GROUP does
2350 * it count? For that matter does it count anyway?
2351 * I believe it doesn't count.
2352 */
2353
2354 if ((GetWindowLongPtrW (hwnd, GWL_STYLE) & WS_GROUP))
2355 {
2356 hwndLastGroup = hwnd;
2357 if (!fSkipping)
2358 {
2359 /* Look for the beginning of the group */
2360 fSkipping = TRUE;
2361 }
2362 }
2363
2364 if (hwnd == hCtl)
2365 {
2366 if (!fSkipping) break;
2367 if (hwndLastGroup == hwnd) break;
2368 hwnd = hwndLastGroup;
2369 fSkipping = FALSE;
2370 fLooped = FALSE;
2371 }
2372
2373 if (!fSkipping &&
2374 (GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE|WS_DISABLED)) ==
2375 WS_VISIBLE)
2376 {
2377 retvalue = hwnd;
2378 if (!bPrevious) break;
2379 }
2380 }
2381 end:
2382 return retvalue;
2383 }
2384
2385
2386 /*
2387 * @implemented
2388 */
2389 HWND
2390 WINAPI
GetNextDlgTabItem(HWND hDlg,HWND hCtl,BOOL bPrevious)2391 GetNextDlgTabItem(
2392 HWND hDlg,
2393 HWND hCtl,
2394 BOOL bPrevious)
2395 {
2396 PWND pWindow;
2397
2398 pWindow = ValidateHwnd( hDlg );
2399 if (!pWindow) return NULL;
2400 if (hCtl)
2401 {
2402 pWindow = ValidateHwnd( hCtl );
2403 if (!pWindow) return NULL;
2404 }
2405
2406 /* Undocumented but tested under Win2000 and WinME */
2407 if (hDlg == hCtl) hCtl = NULL;
2408
2409 /* Contrary to MSDN documentation, tested under Win2000 and WinME
2410 * NB GetLastError returns whatever was set before the function was
2411 * called.
2412 */
2413 if (!hCtl && bPrevious) return 0;
2414
2415 return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
2416 }
2417
2418
2419 #if 0
2420 BOOL
2421 WINAPI
2422 IsDialogMessage(
2423 HWND hDlg,
2424 LPMSG lpMsg)
2425 {
2426 return IsDialogMessageW(hDlg, lpMsg);
2427 }
2428 #endif
2429
2430 /***********************************************************************
2431 * DIALOG_FixOneChildOnChangeFocus
2432 *
2433 * Callback helper for DIALOG_FixChildrenOnChangeFocus
2434 */
2435
DIALOG_FixOneChildOnChangeFocus(HWND hwndChild,LPARAM lParam)2436 static BOOL CALLBACK DIALOG_FixOneChildOnChangeFocus (HWND hwndChild,
2437 LPARAM lParam)
2438 {
2439 /* If a default pushbutton then no longer default */
2440 if (DLGC_DEFPUSHBUTTON & SendMessageW (hwndChild, WM_GETDLGCODE, 0, 0))
2441 SendMessageW (hwndChild, BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
2442 return TRUE;
2443 }
2444
2445 /***********************************************************************
2446 * DIALOG_FixChildrenOnChangeFocus
2447 *
2448 * Following the change of focus that occurs for example after handling
2449 * a WM_KEYDOWN VK_TAB in IsDialogMessage, some tidying of the dialog's
2450 * children may be required.
2451 */
DIALOG_FixChildrenOnChangeFocus(HWND hwndDlg,HWND hwndNext)2452 static void DIALOG_FixChildrenOnChangeFocus (HWND hwndDlg, HWND hwndNext)
2453 {
2454 INT dlgcode_next = SendMessageW (hwndNext, WM_GETDLGCODE, 0, 0);
2455 /* INT dlgcode_dlg = SendMessageW (hwndDlg, WM_GETDLGCODE, 0, 0); */
2456 /* Windows does ask for this. I don't know why yet */
2457
2458 EnumChildWindows (hwndDlg, DIALOG_FixOneChildOnChangeFocus, 0);
2459
2460 /* If the button that is getting the focus WAS flagged as the default
2461 * pushbutton then ask the dialog what it thinks the default is and
2462 * set that in the default style.
2463 */
2464 if (dlgcode_next & DLGC_DEFPUSHBUTTON)
2465 {
2466 DWORD def_id = SendMessageW (hwndDlg, DM_GETDEFID, 0, 0);
2467 if (HIWORD(def_id) == DC_HASDEFID)
2468 {
2469 HWND hwndDef;
2470 def_id = LOWORD(def_id);
2471 hwndDef = GetDlgItem (hwndDlg, def_id);
2472 if (hwndDef)
2473 {
2474 INT dlgcode_def = SendMessageW (hwndDef, WM_GETDLGCODE, 0, 0);
2475 /* I know that if it is a button then it should already be a
2476 * UNDEFPUSHBUTTON, since we have just told the buttons to
2477 * change style. But maybe they ignored our request
2478 */
2479 if ((dlgcode_def & DLGC_BUTTON) &&
2480 (dlgcode_def & DLGC_UNDEFPUSHBUTTON))
2481 {
2482 SendMessageW (hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
2483 }
2484 }
2485 }
2486 }
2487 else if ((dlgcode_next & DLGC_BUTTON) && (dlgcode_next & DLGC_UNDEFPUSHBUTTON))
2488 {
2489 SendMessageW (hwndNext, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
2490 /* I wonder why it doesn't send a DM_SETDEFID */
2491 }
2492 }
2493
2494 /***********************************************************************
2495 * DIALOG_IdToHwnd
2496 *
2497 * A recursive version of GetDlgItem
2498 *
2499 * RETURNS
2500 * The HWND for a Child ID.
2501 */
DIALOG_IdToHwnd(HWND hwndDlg,INT id)2502 static HWND DIALOG_IdToHwnd( HWND hwndDlg, INT id )
2503 {
2504 int i;
2505 HWND *list = WIN_ListChildren( hwndDlg );
2506 HWND ret = 0;
2507
2508 if (!list) return 0;
2509
2510 for (i = 0; list[i]; i++)
2511 {
2512 if (GetWindowLongPtrW( list[i], GWLP_ID ) == id)
2513 {
2514 ret = list[i];
2515 break;
2516 }
2517
2518 /* Recurse into every child */
2519 if ((ret = DIALOG_IdToHwnd( list[i], id ))) break;
2520 }
2521
2522 HeapFree( GetProcessHeap(), 0, list );
2523 return ret;
2524 }
2525
2526
2527 /*
2528 * @implemented
2529 */
2530 BOOL
2531 WINAPI
IsDialogMessageW(HWND hDlg,LPMSG lpMsg)2532 IsDialogMessageW(
2533 HWND hDlg,
2534 LPMSG lpMsg)
2535 {
2536 INT dlgCode = 0;
2537
2538 if (!IsWindow( hDlg ))
2539 return FALSE;
2540
2541 if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2542
2543 if (hDlg == GetDesktopWindow()) return FALSE;
2544 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2545
2546 hDlg = DIALOG_FindMsgDestination(hDlg);
2547
2548 switch(lpMsg->message)
2549 {
2550 case WM_KEYDOWN:
2551 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2552 if (dlgCode & DLGC_WANTMESSAGE) break;
2553
2554 switch(lpMsg->wParam)
2555 {
2556 case VK_TAB:
2557 if (!(dlgCode & DLGC_WANTTAB))
2558 {
2559 BOOL fIsDialog = TRUE;
2560 WND *pWnd = ValidateHwnd(hDlg);
2561
2562 if (pWnd && TestWindowProcess(pWnd))
2563 {
2564 fIsDialog = (GETDLGINFO(hDlg) != NULL);
2565 }
2566
2567 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
2568
2569 /* I am not sure under which circumstances the TAB is handled
2570 * each way. All I do know is that it does not always simply
2571 * send WM_NEXTDLGCTL. (Personally I have never yet seen it
2572 * do so but I presume someone has)
2573 */
2574 if (fIsDialog)
2575 SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2576 else
2577 {
2578 /* It would appear that GetNextDlgTabItem can handle being
2579 * passed hwndDlg rather than NULL but that is undocumented
2580 * so let's do it properly
2581 */
2582 HWND hwndFocus = GetFocus();
2583 HWND hwndNext = GetNextDlgTabItem (hDlg,
2584 hwndFocus == hDlg ? NULL : hwndFocus,
2585 GetKeyState (VK_SHIFT) & 0x8000);
2586 if (hwndNext)
2587 {
2588 dlgCode = SendMessageW (hwndNext, WM_GETDLGCODE,
2589 lpMsg->wParam, (LPARAM)lpMsg);
2590 if (dlgCode & DLGC_HASSETSEL)
2591 {
2592 INT maxlen = 1 + SendMessageW (hwndNext, WM_GETTEXTLENGTH, 0, 0);
2593 WCHAR *buffer = HeapAlloc (GetProcessHeap(), 0, maxlen * sizeof(WCHAR));
2594 if (buffer)
2595 {
2596 SIZE_T length;
2597 SendMessageW (hwndNext, WM_GETTEXT, maxlen, (LPARAM) buffer);
2598 length = strlenW (buffer);
2599 HeapFree (GetProcessHeap(), 0, buffer);
2600 SendMessageW (hwndNext, EM_SETSEL, 0, length);
2601 }
2602 }
2603 SetFocus (hwndNext);
2604 DIALOG_FixChildrenOnChangeFocus (hDlg, hwndNext);
2605 }
2606 else
2607 return FALSE;
2608 }
2609 return TRUE;
2610 }
2611 break;
2612
2613 case VK_RIGHT:
2614 case VK_DOWN:
2615 case VK_LEFT:
2616 case VK_UP:
2617 if (!(dlgCode & DLGC_WANTARROWS))
2618 {
2619 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2620
2621 /* Skip STATIC elements when arrow-moving through a list of controls */
2622 HWND hwndNext, hwndFirst = lpMsg->hwnd;
2623 for (hwndNext = GetNextDlgGroupItem(hDlg, hwndFirst, fPrevious);
2624 hwndNext && hwndFirst != hwndNext;
2625 hwndNext = GetNextDlgGroupItem(hDlg, hwndNext, fPrevious))
2626 {
2627 if (!(SendMessageW(hwndNext, WM_GETDLGCODE, 0, 0) & DLGC_STATIC))
2628 break;
2629 }
2630
2631 if (hwndNext &&
2632 ((SendMessageW(hwndNext, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg) &
2633 (DLGC_BUTTON | DLGC_RADIOBUTTON)) == (DLGC_BUTTON | DLGC_RADIOBUTTON)))
2634 {
2635 SetFocus( hwndNext );
2636 if ((GetWindowLongW( hwndNext, GWL_STYLE ) & BS_TYPEMASK) == BS_AUTORADIOBUTTON &&
2637 SendMessageW( hwndNext, BM_GETCHECK, 0, 0 ) != BST_CHECKED)
2638 SendMessageW(hwndNext, BM_CLICK, 0, 0);
2639 }
2640 else
2641 SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2642 return TRUE;
2643 }
2644 break;
2645
2646 case VK_CANCEL:
2647 case VK_ESCAPE:
2648 SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2649 return TRUE;
2650
2651 case VK_EXECUTE:
2652 case VK_RETURN:
2653 {
2654 DWORD dw;
2655 HWND hwndFocus = GetFocus();
2656 if (IsChild( hDlg, hwndFocus ) &&
2657 (SendMessageW (hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
2658 {
2659 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( GetDlgCtrlID( hwndFocus ), BN_CLICKED ), (LPARAM)hwndFocus );
2660 }
2661 else if (DC_HASDEFID == HIWORD(dw = SendMessageW (hDlg, DM_GETDEFID, 0, 0)))
2662 {
2663 HWND hwndDef = DIALOG_IdToHwnd(hDlg, LOWORD(dw));
2664 if (!hwndDef || IsWindowEnabled(hwndDef))
2665 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), (LPARAM)hwndDef);
2666 }
2667 else
2668 {
2669 SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2670 }
2671 }
2672 return TRUE;
2673 }
2674 break;
2675
2676 case WM_CHAR:
2677 /* FIXME Under what circumstances does WM_GETDLGCODE get sent?
2678 * It does NOT get sent in the test program I have
2679 */
2680 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2681 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2682 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2683 /* drop through */
2684
2685 case WM_SYSCHAR:
2686 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2687 {
2688 /* don't translate or dispatch */
2689 return TRUE;
2690 }
2691 break;
2692 //// ReactOS
2693 case WM_SYSKEYDOWN:
2694 /* If the ALT key is being pressed display the keyboard cues */
2695 if ( HIWORD(lpMsg->lParam) & KF_ALTDOWN &&
2696 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) )
2697 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0);
2698 break;
2699
2700 case WM_SYSCOMMAND:
2701 /* If the ALT key is being pressed display the keyboard cues */
2702 if ( lpMsg->wParam == SC_KEYMENU &&
2703 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) )
2704 {
2705 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0);
2706 }
2707 break;
2708 }
2709
2710 TranslateMessage( lpMsg );
2711 DispatchMessageW( lpMsg );
2712 return TRUE;
2713 }
2714
2715
2716 /*
2717 * @implemented
2718 */
2719 UINT
2720 WINAPI
IsDlgButtonChecked(HWND hDlg,int nIDButton)2721 IsDlgButtonChecked(
2722 HWND hDlg,
2723 int nIDButton)
2724 {
2725 return (UINT)SendDlgItemMessageW( hDlg, nIDButton, BM_GETCHECK, 0, 0 );
2726 }
2727
2728
2729 /*
2730 * @implemented
2731 */
2732 BOOL
2733 WINAPI
MapDialogRect(HWND hDlg,LPRECT lpRect)2734 MapDialogRect(
2735 HWND hDlg,
2736 LPRECT lpRect)
2737 {
2738 DIALOGINFO * dlgInfo;
2739 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
2740 lpRect->left = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4);
2741 lpRect->right = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4);
2742 lpRect->top = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8);
2743 lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8);
2744 return TRUE;
2745 }
2746
2747
2748 /*
2749 * @implemented
2750 */
2751 LRESULT
2752 WINAPI
SendDlgItemMessageA(HWND hDlg,int nIDDlgItem,UINT Msg,WPARAM wParam,LPARAM lParam)2753 SendDlgItemMessageA(
2754 HWND hDlg,
2755 int nIDDlgItem,
2756 UINT Msg,
2757 WPARAM wParam,
2758 LPARAM lParam)
2759 {
2760 HWND hwndCtrl;
2761 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS
2762 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2763 if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam );
2764 else return 0;
2765 }
2766
2767
2768 /*
2769 * @implemented
2770 */
2771 LRESULT
2772 WINAPI
SendDlgItemMessageW(HWND hDlg,int nIDDlgItem,UINT Msg,WPARAM wParam,LPARAM lParam)2773 SendDlgItemMessageW(
2774 HWND hDlg,
2775 int nIDDlgItem,
2776 UINT Msg,
2777 WPARAM wParam,
2778 LPARAM lParam)
2779 {
2780 HWND hwndCtrl;
2781 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS
2782 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2783 if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam );
2784 else return 0;
2785 }
2786
2787
2788 /*
2789 * @implemented
2790 */
2791 BOOL
2792 WINAPI
SetDlgItemInt(HWND hDlg,int nIDDlgItem,UINT uValue,BOOL bSigned)2793 SetDlgItemInt(
2794 HWND hDlg,
2795 int nIDDlgItem,
2796 UINT uValue,
2797 BOOL bSigned)
2798 {
2799 char str[20];
2800
2801 if (bSigned) sprintf( str, "%d", (INT)uValue );
2802 else sprintf( str, "%u", uValue );
2803 SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str );
2804 return TRUE;
2805 }
2806
2807
2808 /*
2809 * @implemented
2810 */
2811 BOOL
2812 WINAPI
SetDlgItemTextA(HWND hDlg,int nIDDlgItem,LPCSTR lpString)2813 SetDlgItemTextA(
2814 HWND hDlg,
2815 int nIDDlgItem,
2816 LPCSTR lpString)
2817 {
2818 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes
2819 if (hwndCtrl) return SetWindowTextA( hwndCtrl, lpString );
2820 return FALSE;
2821 }
2822
2823
2824 /*
2825 * @implemented
2826 */
2827 BOOL
2828 WINAPI
SetDlgItemTextW(HWND hDlg,int nIDDlgItem,LPCWSTR lpString)2829 SetDlgItemTextW(
2830 HWND hDlg,
2831 int nIDDlgItem,
2832 LPCWSTR lpString)
2833 {
2834 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes
2835 if (hwndCtrl) return SetWindowTextW( hwndCtrl, lpString );
2836 return FALSE;
2837 }
2838
2839
2840 /*
2841 * @implemented
2842 */
2843 BOOL
2844 WINAPI
CheckDlgButton(HWND hDlg,int nIDButton,UINT uCheck)2845 CheckDlgButton(
2846 HWND hDlg,
2847 int nIDButton,
2848 UINT uCheck)
2849 {
2850 SendDlgItemMessageW( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 );
2851 return TRUE;
2852 }
2853
CheckRB(HWND hwnd,LPARAM lParam)2854 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam)
2855 {
2856 LONG lChildID = GetWindowLongPtrW(hwnd, GWLP_ID);
2857 RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam;
2858
2859 if((lChildID >= lpRadioGroup->firstID) &&
2860 (lChildID <= lpRadioGroup->lastID))
2861 {
2862 if (lChildID == lpRadioGroup->checkID)
2863 {
2864 SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2865 }
2866 else
2867 {
2868 SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2869 }
2870 }
2871
2872 return TRUE;
2873 }
2874
2875 /*
2876 * @implemented
2877 */
2878 BOOL
2879 WINAPI
CheckRadioButton(HWND hDlg,int nIDFirstButton,int nIDLastButton,int nIDCheckButton)2880 CheckRadioButton(
2881 HWND hDlg,
2882 int nIDFirstButton,
2883 int nIDLastButton,
2884 int nIDCheckButton)
2885 {
2886 RADIOGROUP radioGroup;
2887
2888 radioGroup.firstID = nIDFirstButton;
2889 radioGroup.lastID = nIDLastButton;
2890 radioGroup.checkID = nIDCheckButton;
2891
2892 return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup);
2893 }
2894