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