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