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