3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/dialog.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * Steven Edwards (Steven_Ed4153@yahoo.com)
28 * 07-26-2003 Code ported from wine
29 * 09-05-2001 CSH Created
32 /* INCLUDES ******************************************************************/
42 #include "user32/regcontrol.h"
43 #include "../controls/controls.h"
45 /* MACROS/DEFINITIONS ********************************************************/
48 #define DF_OWNERENABLED 0x0002
49 #define CW_USEDEFAULT16 ((short)0x8000)
51 #define GETDLGINFO(hwnd) (DIALOGINFO*)GetWindowLongW((hwnd), DWL_INIT)
52 #define SETDLGINFO(hwnd, info) SetWindowLongW((hwnd), DWL_INIT, (LONG)(info))
53 #define GET_WORD(ptr) (*(WORD *)(ptr))
54 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
55 #define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
56 #define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
57 #define DIALOG_CLASS_ATOMA MAKEINTATOMA(32770) /* Dialog */
58 #define DIALOG_CLASS_ATOMW MAKEINTATOMW(32770) /* Dialog */
60 /* INTERNAL STRUCTS **********************************************************/
62 /* Dialog info structure */
65 HWND hwndFocus
; /* Current control with focus */
66 HFONT hUserFont
; /* Dialog font */
67 HMENU hMenu
; /* Dialog menu */
68 UINT xBaseUnit
; /* Dialog units (depends on the font) */
70 INT idResult
; /* EndDialog() result / default pushbutton ID */
71 UINT flags
; /* EndDialog() called for this dialog */
74 /* Dialog control information */
112 /* GetDlgItem structure */
119 /* CheckRadioButton structure */
128 /*********************************************************************
129 * dialog class descriptor
131 const struct builtin_class_descr DIALOG_builtin_class
=
133 DIALOG_CLASS_ATOMW
, /* name */
134 CS_SAVEBITS
| CS_DBLCLKS
, /* style */
135 (WNDPROC
) DefDlgProcW
, /* procW */
136 (WNDPROC
) DefDlgProcA
, /* procA */
137 DWL_INIT
+ sizeof(LONG
), /* extra */
138 (LPCWSTR
) IDC_ARROW
, /* cursor */
143 /* INTERNAL FUNCTIONS ********************************************************/
145 /***********************************************************************
148 * Despite most of MSDN insisting that the horizontal base unit is
149 * tmAveCharWidth it isn't. Knowledge base article Q145994
150 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
151 * says that we should take the average of the 52 English upper and lower
154 BOOL
DIALOG_GetCharSize( HDC hDC
, HFONT hFont
, SIZE
* pSize
)
157 char *alphabet
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
161 if(!hDC
) return FALSE
;
163 if(hFont
) hFontPrev
= SelectObject(hDC
, hFont
);
164 if(!GetTextMetricsA(hDC
, &tm
)) return FALSE
;
165 if(!GetTextExtentPointA(hDC
, alphabet
, 52, &sz
)) return FALSE
;
167 pSize
->cy
= tm
.tmHeight
;
168 pSize
->cx
= (sz
.cx
/ 26 + 1) / 2;
170 if (hFontPrev
) SelectObject(hDC
, hFontPrev
);
175 /***********************************************************************
178 * Helper function for modal dialogs to enable again the
179 * owner of the dialog box.
181 void DIALOG_EnableOwner( HWND hOwner
)
183 /* Owner must be a top-level window */
185 hOwner
= GetAncestor( hOwner
, GA_ROOT
);
187 EnableWindow( hOwner
, TRUE
);
190 /***********************************************************************
191 * DIALOG_DisableOwner
193 * Helper function for modal dialogs to disable the
194 * owner of the dialog box. Returns TRUE if owner was enabled.
196 BOOL
DIALOG_DisableOwner( HWND hOwner
)
198 /* Owner must be a top-level window */
200 hOwner
= GetAncestor( hOwner
, GA_ROOT
);
201 if (!hOwner
) return FALSE
;
202 if (IsWindowEnabled( hOwner
))
204 EnableWindow( hOwner
, FALSE
);
211 /***********************************************************************
212 * DIALOG_GetControl32
214 * Return the class and text of the control pointed to by ptr,
215 * fill the header structure and return a pointer to the next control.
217 static const WORD
*DIALOG_GetControl32( const WORD
*p
, DLG_CONTROL_INFO
*info
,
222 info
->helpId
= GET_DWORD(p
); p
+= 2;
223 info
->exStyle
= GET_DWORD(p
); p
+= 2;
224 info
->style
= GET_DWORD(p
); p
+= 2;
229 info
->style
= GET_DWORD(p
); p
+= 2;
230 info
->exStyle
= GET_DWORD(p
); p
+= 2;
232 info
->x
= GET_WORD(p
); p
++;
233 info
->y
= GET_WORD(p
); p
++;
234 info
->cx
= GET_WORD(p
); p
++;
235 info
->cy
= GET_WORD(p
); p
++;
239 /* id is a DWORD for DIALOGEX */
240 info
->id
= GET_DWORD(p
);
245 info
->id
= GET_WORD(p
);
249 if (GET_WORD(p
) == 0xffff)
251 static const WCHAR class_names
[6][10] =
253 { 'B','u','t','t','o','n', }, /* 0x80 */
254 { 'E','d','i','t', }, /* 0x81 */
255 { 'S','t','a','t','i','c', }, /* 0x82 */
256 { 'L','i','s','t','B','o','x', }, /* 0x83 */
257 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
258 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
260 WORD id
= GET_WORD(p
+1);
261 /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
262 if ((id
>= 0x80) && (id
<= 0x85)) id
-= 0x80;
264 info
->className
= class_names
[id
];
267 info
->className
= NULL
;
268 /* FIXME: load other classes here? */
274 info
->className
= (LPCWSTR
)p
;
275 p
+= wcslen( info
->className
) + 1;
278 if (GET_WORD(p
) == 0xffff) /* Is it an integer id? */
280 info
->windowName
= HeapAlloc( GetProcessHeap(), 0, 10 );
281 swprintf((LPWSTR
)info
->windowName
, L
"#%d", GET_WORD(p
+ 1));
282 info
->windowNameFree
= TRUE
;
287 info
->windowName
= (LPCWSTR
)p
;
288 info
->windowNameFree
= FALSE
;
289 p
+= wcslen( info
->windowName
) + 1;
295 p
+= GET_WORD(p
) / sizeof(WORD
);
297 else info
->data
= NULL
;
300 /* Next control is on dword boundary */
301 return (const WORD
*)((((int)p
) + 3) & ~3);
304 /***********************************************************************
305 * DIALOG_CreateControls32
307 * Create the control windows for a dialog.
309 static BOOL
DIALOG_CreateControls32( HWND hwnd
, LPCSTR
template, const DLG_TEMPLATE
*dlgTemplate
,
310 HINSTANCE hInst
, BOOL unicode
)
312 DIALOGINFO
* dlgInfo
;
313 DLG_CONTROL_INFO info
;
314 HWND hwndCtrl
, hwndDefButton
= 0;
315 INT items
= dlgTemplate
->nbItems
;
317 if (!(dlgInfo
= GETDLGINFO(hwnd
))) return -1;
321 template = (LPCSTR
)DIALOG_GetControl32( (WORD
*)template, &info
,
322 dlgTemplate
->dialogEx
);
324 if (info
.style
& WS_BORDER
)
326 info
.style
&= ~WS_BORDER
;
327 info
.exStyle
|= WS_EX_CLIENTEDGE
;
331 hwndCtrl
= CreateWindowExW( info
.exStyle
| WS_EX_NOPARENTNOTIFY
,
332 info
.className
, info
.windowName
,
333 info
.style
| WS_CHILD
,
334 MulDiv(info
.x
, dlgInfo
->xBaseUnit
, 4),
335 MulDiv(info
.y
, dlgInfo
->yBaseUnit
, 8),
336 MulDiv(info
.cx
, dlgInfo
->xBaseUnit
, 4),
337 MulDiv(info
.cy
, dlgInfo
->yBaseUnit
, 8),
338 hwnd
, (HMENU
)info
.id
,
339 hInst
, (LPVOID
)info
.data
);
343 LPSTR
class = (LPSTR
)info
.className
;
344 LPSTR caption
= (LPSTR
)info
.windowName
;
348 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
.className
, -1, NULL
, 0, NULL
, NULL
);
349 class = HeapAlloc( GetProcessHeap(), 0, len
);
350 WideCharToMultiByte( CP_ACP
, 0, info
.className
, -1, class, len
, NULL
, NULL
);
354 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
.windowName
, -1, NULL
, 0, NULL
, NULL
);
355 caption
= HeapAlloc( GetProcessHeap(), 0, len
);
356 WideCharToMultiByte( CP_ACP
, 0, info
.windowName
, -1, caption
, len
, NULL
, NULL
);
358 hwndCtrl
= CreateWindowExA( info
.exStyle
| WS_EX_NOPARENTNOTIFY
,
359 class, caption
, info
.style
| WS_CHILD
,
360 MulDiv(info
.x
, dlgInfo
->xBaseUnit
, 4),
361 MulDiv(info
.y
, dlgInfo
->yBaseUnit
, 8),
362 MulDiv(info
.cx
, dlgInfo
->xBaseUnit
, 4),
363 MulDiv(info
.cy
, dlgInfo
->yBaseUnit
, 8),
364 hwnd
, (HMENU
)info
.id
,
365 hInst
, (LPVOID
)info
.data
);
366 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
367 if (HIWORD(caption
)) HeapFree( GetProcessHeap(), 0, caption
);
370 if (info
.windowNameFree
)
372 HeapFree( GetProcessHeap(), 0, (LPVOID
)info
.windowName
);
377 if (dlgTemplate
->style
& DS_NOFAILCREATE
) continue;
381 /* Send initialisation messages to the control */
382 if (dlgInfo
->hUserFont
) SendMessageA( hwndCtrl
, WM_SETFONT
,
383 (WPARAM
)dlgInfo
->hUserFont
, 0 );
384 if (SendMessageA(hwndCtrl
, WM_GETDLGCODE
, 0, 0) & DLGC_DEFPUSHBUTTON
)
386 /* If there's already a default push-button, set it back */
387 /* to normal and use this one instead. */
389 SendMessageA( hwndDefButton
, BM_SETSTYLE
, BS_PUSHBUTTON
, FALSE
);
390 hwndDefButton
= hwndCtrl
;
391 dlgInfo
->idResult
= GetWindowLongA( hwndCtrl
, GWL_ID
);
397 /***********************************************************************
398 * DIALOG_FindMsgDestination
400 * The messages that IsDialogMessage sends may not go to the dialog
401 * calling IsDialogMessage if that dialog is a child, and it has the
402 * DS_CONTROL style set.
403 * We propagate up until we hit one that does not have DS_CONTROL, or
404 * whose parent is not a dialog.
406 * This is undocumented behaviour.
408 static HWND
DIALOG_FindMsgDestination( HWND hwndDlg
)
410 while (GetWindowLongA(hwndDlg
, GWL_STYLE
) & DS_CONTROL
)
412 HWND hParent
= GetParent(hwndDlg
);
415 if (!IsWindow(hParent
)) break;
417 if (!GETDLGINFO(hParent
)) /* TODO: Correct? */
428 /***********************************************************************
429 * DIALOG_IsAccelerator
431 static BOOL
DIALOG_IsAccelerator( HWND hwnd
, HWND hwndDlg
, WPARAM wParam
)
433 HWND hwndControl
= hwnd
;
440 DWORD style
= GetWindowLongW( hwndControl
, GWL_STYLE
);
441 if ((style
& (WS_VISIBLE
| WS_DISABLED
)) == WS_VISIBLE
)
443 dlgCode
= SendMessageA( hwndControl
, WM_GETDLGCODE
, 0, 0 );
444 if ( (dlgCode
& (DLGC_BUTTON
| DLGC_STATIC
)) &&
445 GetWindowTextW( hwndControl
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
447 /* find the accelerator key */
448 LPWSTR p
= buffer
- 2;
452 p
= wcschr( p
+ 2, '&' );
454 while (p
!= NULL
&& p
[1] == '&');
456 /* and check if it's the one we're looking for */
457 /* FIXME: usage of towupper correct? */
458 if (p
!= NULL
&& towupper( p
[1] ) == towupper( wParam
) )
460 if ((dlgCode
& DLGC_STATIC
) || (style
& 0x0f) == BS_GROUPBOX
)
462 /* set focus to the control */
463 SendMessageA( hwndDlg
, WM_NEXTDLGCTL
, (WPARAM
)hwndControl
, 1);
464 /* and bump it on to next */
465 SendMessageA( hwndDlg
, WM_NEXTDLGCTL
, 0, 0);
467 else if (dlgCode
& DLGC_BUTTON
)
469 /* send BM_CLICK message to the control */
470 SendMessageA( hwndControl
, BM_CLICK
, 0, 0 );
475 hwndNext
= GetWindow( hwndControl
, GW_CHILD
);
479 if (!hwndNext
) hwndNext
= GetWindow( hwndControl
, GW_HWNDNEXT
);
481 while (!hwndNext
&& hwndControl
)
483 hwndControl
= GetParent( hwndControl
);
484 if (hwndControl
== hwndDlg
)
486 if(hwnd
==hwndDlg
) /* prevent endless loop */
491 hwndNext
= GetWindow( hwndDlg
, GW_CHILD
);
494 hwndNext
= GetWindow( hwndControl
, GW_HWNDNEXT
);
496 hwndControl
= hwndNext
;
498 while (hwndControl
&& (hwndControl
!= hwnd
));
503 /***********************************************************************
506 INT
DIALOG_DoDialogBox( HWND hwnd
, HWND owner
)
508 DIALOGINFO
* dlgInfo
;
511 HWND ownerMsg
= GetAncestor( owner
, GA_ROOT
);
512 if (!(dlgInfo
= GETDLGINFO(hwnd
))) return -1;
514 if (!(dlgInfo
->flags
& DF_END
)) /* was EndDialog called in WM_INITDIALOG ? */
516 ShowWindow( hwnd
, SW_SHOW
);
519 if (!(GetWindowLongW( hwnd
, GWL_STYLE
) & DS_NOIDLEMSG
))
521 if (!PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
))
523 /* No message present -> send ENTERIDLE and wait */
524 SendMessageW( ownerMsg
, WM_ENTERIDLE
, MSGF_DIALOGBOX
, (LPARAM
)hwnd
);
525 if (!GetMessageW( &msg
, 0, 0, 0 )) break;
528 else if (!GetMessageW( &msg
, 0, 0, 0 )) break;
530 if (!IsWindow( hwnd
)) return -1;
531 if (!(dlgInfo
->flags
& DF_END
) && !IsDialogMessageW( hwnd
, &msg
))
533 TranslateMessage( &msg
);
534 DispatchMessageW( &msg
);
536 if (dlgInfo
->flags
& DF_END
) break;
539 if (dlgInfo
->flags
& DF_OWNERENABLED
) DIALOG_EnableOwner( owner
);
540 retval
= dlgInfo
->idResult
;
541 DestroyWindow( hwnd
);
545 /***********************************************************************
546 * DIALOG_ParseTemplate32
548 * Fill a DLG_TEMPLATE structure from the dialog template, and return
549 * a pointer to the first control.
551 static LPCSTR
DIALOG_ParseTemplate32( LPCSTR
template, DLG_TEMPLATE
* result
)
553 const WORD
*p
= (const WORD
*)template;
555 result
->style
= GET_DWORD(p
); p
+= 2;
556 if (result
->style
== 0xffff0001) /* DIALOGEX resource */
558 result
->dialogEx
= TRUE
;
559 result
->helpId
= GET_DWORD(p
); p
+= 2;
560 result
->exStyle
= GET_DWORD(p
); p
+= 2;
561 result
->style
= GET_DWORD(p
); p
+= 2;
565 result
->dialogEx
= FALSE
;
567 result
->exStyle
= GET_DWORD(p
); p
+= 2;
569 result
->nbItems
= GET_WORD(p
); p
++;
570 result
->x
= GET_WORD(p
); p
++;
571 result
->y
= GET_WORD(p
); p
++;
572 result
->cx
= GET_WORD(p
); p
++;
573 result
->cy
= GET_WORD(p
); p
++;
575 /* Get the menu name */
580 result
->menuName
= NULL
;
584 result
->menuName
= (LPCWSTR
)(UINT
)GET_WORD( p
+ 1 );
588 result
->menuName
= (LPCWSTR
)p
;
589 p
+= wcslen( result
->menuName
) + 1;
593 /* Get the class name */
598 result
->className
= DIALOG_CLASS_ATOMW
;
602 result
->className
= (LPCWSTR
)(UINT
)GET_WORD( p
+ 1 );
606 result
->className
= (LPCWSTR
)p
;
607 p
+= wcslen( result
->className
) + 1;
611 /* Get the window caption */
613 result
->caption
= (LPCWSTR
)p
;
614 p
+= wcslen( result
->caption
) + 1;
616 /* Get the font name */
618 if (result
->style
& DS_SETFONT
)
620 result
->pointSize
= GET_WORD(p
);
622 if (result
->dialogEx
)
624 result
->weight
= GET_WORD(p
); p
++;
625 result
->italic
= LOBYTE(GET_WORD(p
)); p
++;
629 result
->weight
= FW_DONTCARE
;
630 result
->italic
= FALSE
;
632 result
->faceName
= (LPCWSTR
)p
;
633 p
+= wcslen( result
->faceName
) + 1;
637 result
->pointSize
= 0;
638 result
->weight
= FW_DONTCARE
;
639 result
->italic
= FALSE
;
640 result
->faceName
= NULL
;
643 /* First control is on dword boundary */
644 return (LPCSTR
)((((int)p
) + 3) & ~3);
647 /***********************************************************************
648 * DIALOG_CreateIndirect
649 * Creates a dialog box window
651 * modal = TRUE if we are called from a modal dialog box.
652 * (it's more compatible to do it here, as under Windows the owner
653 * is never disabled if the dialog fails because of an invalid template)
655 static HWND
DIALOG_CreateIndirect( HINSTANCE hInst
, LPCVOID dlgTemplate
,
656 HWND owner
, DLGPROC dlgProc
, LPARAM param
,
657 BOOL unicode
, BOOL modal
)
661 DLG_TEMPLATE
template;
662 DIALOGINFO
* dlgInfo
;
663 DWORD units
= GetDialogBaseUnits();
664 BOOL ownerEnabled
= TRUE
;
666 /* Parse dialog template */
668 if (!dlgTemplate
) return 0;
669 dlgTemplate
= DIALOG_ParseTemplate32( dlgTemplate
, &template );
671 /* Initialise dialog extra data */
673 if (!(dlgInfo
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dlgInfo
) ))) return 0;
674 dlgInfo
->hwndFocus
= 0;
675 dlgInfo
->hUserFont
= 0;
677 dlgInfo
->xBaseUnit
= LOWORD(units
);
678 dlgInfo
->yBaseUnit
= HIWORD(units
);
679 dlgInfo
->idResult
= 0;
681 //dlgInfo->hDialogHeap = 0;
685 if (template.menuName
) dlgInfo
->hMenu
= LoadMenuW( hInst
, template.menuName
);
687 /* Create custom font if needed */
689 if (template.style
& DS_SETFONT
)
691 /* We convert the size to pixels and then make it -ve. This works
692 * for both +ve and -ve template.pointSize */
696 pixels
= MulDiv(template.pointSize
, GetDeviceCaps(dc
, LOGPIXELSY
), 72);
697 dlgInfo
->hUserFont
= CreateFontW( -pixels
, 0, 0, 0, template.weight
,
698 template.italic
, FALSE
, FALSE
, DEFAULT_CHARSET
, 0, 0,
699 PROOF_QUALITY
, FF_DONTCARE
,
701 if (dlgInfo
->hUserFont
)
704 if (DIALOG_GetCharSize( dc
, dlgInfo
->hUserFont
, &charSize
))
706 dlgInfo
->xBaseUnit
= charSize
.cx
;
707 dlgInfo
->yBaseUnit
= charSize
.cy
;
713 /* Create dialog main window */
715 rect
.left
= rect
.top
= 0;
716 rect
.right
= MulDiv(template.cx
, dlgInfo
->xBaseUnit
, 4);
717 rect
.bottom
= MulDiv(template.cy
, dlgInfo
->yBaseUnit
, 8);
718 if (template.style
& WS_CHILD
)
719 template.style
&= ~(WS_CAPTION
|WS_SYSMENU
);
720 if (template.style
& DS_MODALFRAME
)
721 template.exStyle
|= WS_EX_DLGMODALFRAME
;
722 if (template.style
& DS_CONTROL
)
723 template.exStyle
|= WS_EX_CONTROLPARENT
;
724 AdjustWindowRectEx( &rect
, template.style
, (dlgInfo
->hMenu
!= 0), template.exStyle
);
725 rect
.right
-= rect
.left
;
726 rect
.bottom
-= rect
.top
;
728 if (template.x
== CW_USEDEFAULT16
)
730 rect
.left
= rect
.top
= CW_USEDEFAULT
;
734 if (template.style
& DS_CENTER
)
736 rect
.left
= (GetSystemMetrics(SM_CXSCREEN
) - rect
.right
) / 2;
737 rect
.top
= (GetSystemMetrics(SM_CYSCREEN
) - rect
.bottom
) / 2;
741 rect
.left
+= MulDiv(template.x
, dlgInfo
->xBaseUnit
, 4);
742 rect
.top
+= MulDiv(template.y
, dlgInfo
->yBaseUnit
, 8);
744 if ( !(template.style
& WS_CHILD
) )
748 if( !(template.style
& DS_ABSALIGN
) )
749 ClientToScreen( owner
, (POINT
*)&rect
);
751 /* try to fit it into the desktop */
753 if( (dX
= rect
.left
+ rect
.right
+ GetSystemMetrics(SM_CXDLGFRAME
)
754 - GetSystemMetrics(SM_CXSCREEN
)) > 0 ) rect
.left
-= dX
;
755 if( (dY
= rect
.top
+ rect
.bottom
+ GetSystemMetrics(SM_CYDLGFRAME
)
756 - GetSystemMetrics(SM_CYSCREEN
)) > 0 ) rect
.top
-= dY
;
757 if( rect
.left
< 0 ) rect
.left
= 0;
758 if( rect
.top
< 0 ) rect
.top
= 0;
764 ownerEnabled
= DIALOG_DisableOwner( owner
);
765 if (ownerEnabled
) dlgInfo
->flags
|= DF_OWNERENABLED
;
770 hwnd
= CreateWindowExW(template.exStyle
, template.className
, template.caption
,
771 template.style
& ~WS_VISIBLE
,
772 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
,
773 owner
, dlgInfo
->hMenu
, hInst
, NULL
);
777 LPSTR
class = (LPSTR
)template.className
;
778 LPSTR caption
= (LPSTR
)template.caption
;
782 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, template.className
, -1, NULL
, 0, NULL
, NULL
);
783 class = HeapAlloc( GetProcessHeap(), 0, len
);
784 WideCharToMultiByte( CP_ACP
, 0, template.className
, -1, class, len
, NULL
, NULL
);
788 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, template.caption
, -1, NULL
, 0, NULL
, NULL
);
789 caption
= HeapAlloc( GetProcessHeap(), 0, len
);
790 WideCharToMultiByte( CP_ACP
, 0, template.caption
, -1, caption
, len
, NULL
, NULL
);
792 hwnd
= CreateWindowExA(template.exStyle
, class, caption
,
793 template.style
& ~WS_VISIBLE
,
794 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
,
795 owner
, dlgInfo
->hMenu
, hInst
, NULL
);
796 if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
797 if (HIWORD(caption
)) HeapFree( GetProcessHeap(), 0, caption
);
802 if (dlgInfo
->hUserFont
) DeleteObject( dlgInfo
->hUserFont
);
803 if (dlgInfo
->hMenu
) DestroyMenu( dlgInfo
->hMenu
);
804 if (modal
&& (dlgInfo
->flags
& DF_OWNERENABLED
)) DIALOG_EnableOwner(owner
);
805 HeapFree( GetProcessHeap(), 0, dlgInfo
);
810 SetWindowContextHelpId( hwnd
, template.helpId
);
814 SETDLGINFO(hwnd
, dlgInfo
); /* maybe SetPropW? */
815 SetWindowLongW( hwnd
, DWL_DLGPROC
, (LONG
)dlgProc
);
819 SETDLGINFO(hwnd
, dlgInfo
);
820 SetWindowLongA( hwnd
, DWL_DLGPROC
, (LONG
)dlgProc
);
823 if (dlgInfo
->hUserFont
)
824 SendMessageA( hwnd
, WM_SETFONT
, (WPARAM
)dlgInfo
->hUserFont
, 0 );
826 /* Create controls */
828 if (DIALOG_CreateControls32( hwnd
, dlgTemplate
, &template, hInst
, unicode
))
830 /* Send initialisation messages and set focus */
832 if (SendMessageW( hwnd
, WM_INITDIALOG
, (WPARAM
)dlgInfo
->hwndFocus
, param
))
834 /* By returning TRUE, app has requested a default focus assignment */
835 dlgInfo
->hwndFocus
= GetNextDlgTabItem( hwnd
, 0, FALSE
);
836 if( dlgInfo
->hwndFocus
)
837 SetFocus( dlgInfo
->hwndFocus
);
840 if (template.style
& WS_VISIBLE
&& !(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
))
842 ShowWindow( hwnd
, SW_SHOWNORMAL
); /* SW_SHOW doesn't always work */
847 if( IsWindow(hwnd
) ) DestroyWindow( hwnd
);
848 if (modal
&& ownerEnabled
) DIALOG_EnableOwner(owner
);
852 /***********************************************************************
855 * Set the focus to a control of the dialog, selecting the text if
856 * the control is an edit dialog.
858 static void DEFDLG_SetFocus( HWND hwndDlg
, HWND hwndCtrl
)
860 HWND hwndPrev
= GetFocus();
862 if (IsChild( hwndDlg
, hwndPrev
))
864 if (SendMessageW( hwndPrev
, WM_GETDLGCODE
, 0, 0 ) & DLGC_HASSETSEL
)
865 SendMessageW( hwndPrev
, EM_SETSEL
, -1, 0 );
867 if (SendMessageW( hwndCtrl
, WM_GETDLGCODE
, 0, 0 ) & DLGC_HASSETSEL
)
868 SendMessageW( hwndCtrl
, EM_SETSEL
, 0, -1 );
869 SetFocus( hwndCtrl
);
872 /***********************************************************************
875 static void DEFDLG_SaveFocus( HWND hwnd
)
878 HWND hwndFocus
= GetFocus();
880 if (!hwndFocus
|| !IsChild( hwnd
, hwndFocus
)) return;
881 if (!(infoPtr
= GETDLGINFO(hwnd
))) return;
882 infoPtr
->hwndFocus
= hwndFocus
;
883 /* Remove default button */
886 /***********************************************************************
887 * DEFDLG_RestoreFocus
889 static void DEFDLG_RestoreFocus( HWND hwnd
)
893 if (IsIconic( hwnd
)) return;
894 if (!(infoPtr
= GETDLGINFO(hwnd
))) return;
895 if (!IsWindow( infoPtr
->hwndFocus
)) return;
896 /* Don't set the focus back to controls if EndDialog is already called.*/
897 if (!(infoPtr
->flags
& DF_END
))
899 DEFDLG_SetFocus( hwnd
, infoPtr
->hwndFocus
);
902 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
903 sometimes losing focus when receiving WM_SETFOCUS messages. */
906 /***********************************************************************
907 * DEFDLG_FindDefButton
909 * Find the current default push-button.
911 static HWND
DEFDLG_FindDefButton( HWND hwndDlg
)
913 HWND hwndChild
= GetWindow( hwndDlg
, GW_CHILD
);
916 if (SendMessageW( hwndChild
, WM_GETDLGCODE
, 0, 0 ) & DLGC_DEFPUSHBUTTON
)
918 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
923 /***********************************************************************
924 * DEFDLG_SetDefButton
926 * Set the new default button to be hwndNew.
928 static BOOL
DEFDLG_SetDefButton( HWND hwndDlg
, DIALOGINFO
*dlgInfo
,
931 DWORD dlgcode
=0; /* initialize just to avoid a warning */
933 !((dlgcode
=SendMessageW(hwndNew
, WM_GETDLGCODE
, 0, 0 ))
934 & (DLGC_UNDEFPUSHBUTTON
| DLGC_BUTTON
)))
935 return FALSE
; /* Destination is not a push button */
937 if (dlgInfo
->idResult
) /* There's already a default pushbutton */
939 HWND hwndOld
= GetDlgItem( hwndDlg
, dlgInfo
->idResult
);
940 if (SendMessageA( hwndOld
, WM_GETDLGCODE
, 0, 0) & DLGC_DEFPUSHBUTTON
)
941 SendMessageA( hwndOld
, BM_SETSTYLE
, BS_PUSHBUTTON
, TRUE
);
945 if(dlgcode
==DLGC_UNDEFPUSHBUTTON
)
946 SendMessageA( hwndNew
, BM_SETSTYLE
, BS_DEFPUSHBUTTON
, TRUE
);
947 dlgInfo
->idResult
= GetDlgCtrlID( hwndNew
);
949 else dlgInfo
->idResult
= 0;
953 /***********************************************************************
956 * Implementation of DefDlgProc(). Only handle messages that need special
957 * handling for dialogs.
959 static LRESULT
DEFDLG_Proc( HWND hwnd
, UINT msg
, WPARAM wParam
,
960 LPARAM lParam
, DIALOGINFO
*dlgInfo
)
966 HBRUSH brush
= (HBRUSH
)SendMessageW( hwnd
, WM_CTLCOLORDLG
, wParam
, (LPARAM
)hwnd
);
967 if (!brush
) brush
= (HBRUSH
)DefWindowProcW( hwnd
, WM_CTLCOLORDLG
, wParam
, (LPARAM
)hwnd
);
971 HDC hdc
= (HDC
)wParam
;
972 GetClientRect( hwnd
, &rect
);
973 DPtoLP( hdc
, (LPPOINT
)&rect
, 2 );
974 FillRect( hdc
, &rect
, brush
);
979 if ((dlgInfo
= GETDLGINFO(hwnd
)))
981 /* Free dialog heap (if created) */
982 /*if (dlgInfo->hDialogHeap)
984 GlobalUnlock16(dlgInfo->hDialogHeap);
985 GlobalFree16(dlgInfo->hDialogHeap);
987 if (dlgInfo
->hUserFont
) DeleteObject( dlgInfo
->hUserFont
);
988 if (dlgInfo
->hMenu
) DestroyMenu( dlgInfo
->hMenu
);
989 HeapFree( GetProcessHeap(), 0, dlgInfo
);
991 /* Window clean-up */
992 return DefWindowProcA( hwnd
, msg
, wParam
, lParam
);
995 if (!wParam
) DEFDLG_SaveFocus( hwnd
);
996 return DefWindowProcA( hwnd
, msg
, wParam
, lParam
);
999 if (wParam
) DEFDLG_RestoreFocus( hwnd
);
1000 else DEFDLG_SaveFocus( hwnd
);
1004 DEFDLG_RestoreFocus( hwnd
);
1008 if (dlgInfo
&& !(dlgInfo
->flags
& DF_END
))
1009 DEFDLG_SetDefButton( hwnd
, dlgInfo
, wParam
? GetDlgItem( hwnd
, wParam
) : 0 );
1013 if (dlgInfo
&& !(dlgInfo
->flags
& DF_END
))
1016 if (dlgInfo
->idResult
)
1017 return MAKELONG( dlgInfo
->idResult
, DC_HASDEFID
);
1018 if ((hwndDefId
= DEFDLG_FindDefButton( hwnd
)))
1019 return MAKELONG( GetDlgCtrlID( hwndDefId
), DC_HASDEFID
);
1026 HWND hwndDest
= (HWND
)wParam
;
1028 hwndDest
= GetNextDlgTabItem(hwnd
, GetFocus(), wParam
);
1029 if (hwndDest
) DEFDLG_SetFocus( hwnd
, hwndDest
);
1030 DEFDLG_SetDefButton( hwnd
, dlgInfo
, hwndDest
);
1034 case WM_ENTERMENULOOP
:
1035 case WM_LBUTTONDOWN
:
1036 case WM_NCLBUTTONDOWN
:
1038 HWND hwndFocus
= GetFocus();
1041 /* always make combo box hide its listbox control */
1042 if (!SendMessageA( hwndFocus
, CB_SHOWDROPDOWN
, FALSE
, 0 ))
1043 SendMessageA( GetParent(hwndFocus
), CB_SHOWDROPDOWN
, FALSE
, 0 );
1046 return DefWindowProcA( hwnd
, msg
, wParam
, lParam
);
1049 return dlgInfo
? (LRESULT
)dlgInfo
->hUserFont
: 0;
1052 PostMessageA( hwnd
, WM_COMMAND
, MAKEWPARAM(IDCANCEL
, BN_CLICKED
),
1053 (LPARAM
)GetDlgItem( hwnd
, IDCANCEL
) );
1056 case WM_NOTIFYFORMAT
:
1057 return DefWindowProcA( hwnd
, msg
, wParam
, lParam
);
1062 /***********************************************************************
1065 static LRESULT
DEFDLG_Epilog(HWND hwnd
, UINT msg
, BOOL fResult
)
1067 // TODO: where's wine's WM_CTLCOLOR from?
1068 if ((msg
>= WM_CTLCOLORMSGBOX
&& msg
<= WM_CTLCOLORSTATIC
) ||
1069 /*msg == WM_CTLCOLOR || */ msg
== WM_COMPAREITEM
||
1070 msg
== WM_VKEYTOITEM
|| msg
== WM_CHARTOITEM
||
1071 msg
== WM_QUERYDRAGICON
|| msg
== WM_INITDIALOG
)
1074 return GetWindowLongA( hwnd
, DWL_MSGRESULT
);
1077 /***********************************************************************
1078 * DIALOG_GetNextTabItem
1080 * Helper for GetNextDlgTabItem
1082 static HWND
DIALOG_GetNextTabItem( HWND hwndMain
, HWND hwndDlg
, HWND hwndCtrl
, BOOL fPrevious
)
1086 UINT wndSearch
= fPrevious
? GW_HWNDPREV
: GW_HWNDNEXT
;
1088 HWND hChildFirst
= 0;
1092 hChildFirst
= GetWindow(hwndDlg
,GW_CHILD
);
1093 if(fPrevious
) hChildFirst
= GetWindow(hChildFirst
,GW_HWNDLAST
);
1095 else if (IsChild( hwndMain
, hwndCtrl
))
1097 hChildFirst
= GetWindow(hwndCtrl
,wndSearch
);
1100 if(GetParent(hwndCtrl
) != hwndMain
)
1101 hChildFirst
= GetWindow(GetParent(hwndCtrl
),wndSearch
);
1105 hChildFirst
= GetWindow(hwndCtrl
,GW_HWNDLAST
);
1107 hChildFirst
= GetWindow(hwndCtrl
,GW_HWNDFIRST
);
1117 dsStyle
= GetWindowLongA(hChildFirst
,GWL_STYLE
);
1118 exStyle
= GetWindowLongA(hChildFirst
,GWL_EXSTYLE
);
1119 if( (dsStyle
& DS_CONTROL
|| exStyle
& WS_EX_CONTROLPARENT
) && (dsStyle
& WS_VISIBLE
) && !(dsStyle
& WS_DISABLED
))
1124 else if( (dsStyle
& WS_TABSTOP
) && (dsStyle
& WS_VISIBLE
) && !(dsStyle
& WS_DISABLED
))
1126 hChildFirst
= GetWindow(hChildFirst
,wndSearch
);
1131 retWnd
= DIALOG_GetNextTabItem(hwndMain
,hChildFirst
,NULL
,fPrevious
);
1133 retWnd
= hChildFirst
;
1136 hChildFirst
= GetWindow(hChildFirst
,wndSearch
);
1138 if(!retWnd
&& hwndCtrl
)
1140 HWND hParent
= GetParent(hwndCtrl
);
1143 if(hParent
== hwndMain
) break;
1144 retWnd
= DIALOG_GetNextTabItem(hwndMain
,GetParent(hParent
),hParent
,fPrevious
);
1146 hParent
= GetParent(hParent
);
1149 retWnd
= DIALOG_GetNextTabItem(hwndMain
,hwndMain
,NULL
,fPrevious
);
1154 /**********************************************************************
1157 * Helper function for DlgDirList*
1159 static INT
DIALOG_DlgDirList( HWND hDlg
, LPSTR spec
, INT idLBox
,
1160 INT idStatic
, UINT attrib
, BOOL combo
)
1163 LPSTR orig_spec
= spec
;
1166 #define SENDMSG(msg,wparam,lparam) \
1167 ((attrib & DDL_POSTMSGS) ? PostMessageA( hwnd, msg, wparam, lparam ) \
1168 : SendMessageA( hwnd, msg, wparam, lparam ))
1170 DPRINT("%p '%s' %d %d %04x\n",
1171 hDlg
, spec
? spec
: "NULL", idLBox
, idStatic
, attrib
);
1173 /* If the path exists and is a directory, chdir to it */
1174 if (!spec
|| !spec
[0] || SetCurrentDirectoryA( spec
)) spec
= any
;
1179 if ((p2
= strrchr( p
, '\\' ))) p
= p2
;
1180 if ((p2
= strrchr( p
, '/' ))) p
= p2
;
1185 if (!SetCurrentDirectoryA( spec
))
1187 *p
= sep
; /* Restore the original spec */
1194 DPRINT( "mask=%s\n", spec
);
1196 if (idLBox
&& ((hwnd
= GetDlgItem( hDlg
, idLBox
)) != 0))
1198 SENDMSG( combo
? CB_RESETCONTENT
: LB_RESETCONTENT
, 0, 0 );
1199 if (attrib
& DDL_DIRECTORY
)
1201 if (!(attrib
& DDL_EXCLUSIVE
))
1203 if (SENDMSG( combo
? CB_DIR
: LB_DIR
,
1204 attrib
& ~(DDL_DIRECTORY
| DDL_DRIVES
),
1205 (LPARAM
)spec
) == LB_ERR
)
1208 if (SENDMSG( combo
? CB_DIR
: LB_DIR
,
1209 (attrib
& (DDL_DIRECTORY
| DDL_DRIVES
)) | DDL_EXCLUSIVE
,
1210 (LPARAM
)"*.*" ) == LB_ERR
)
1215 if (SENDMSG( combo
? CB_DIR
: LB_DIR
, attrib
,
1216 (LPARAM
)spec
) == LB_ERR
)
1221 if (idStatic
&& ((hwnd
= GetDlgItem( hDlg
, idStatic
)) != 0))
1223 char temp
[MAX_PATH
];
1224 GetCurrentDirectoryA( sizeof(temp
), temp
);
1226 /* Can't use PostMessage() here, because the string is on the stack */
1227 SetDlgItemTextA( hDlg
, idStatic
, temp
);
1230 if (orig_spec
&& (spec
!= orig_spec
))
1232 /* Update the original file spec */
1234 while ((*orig_spec
++ = *p
++));
1241 /* Hack - We dont define this anywhere and we shouldn't
1242 * Its only used to port buggy WINE code in to our buggy code.
1243 * Make it go away - sedwards
1246 /* DO NOT USE IT!! it will go away soon */
1247 inline static LPSTR
HEAP_strdupWtoA( HANDLE heap
, DWORD flags
, LPCWSTR str
)
1252 if (!str
) return NULL
;
1253 len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
1254 ret
= RtlAllocateHeap(GetProcessHeap(), flags
, len
);
1255 if(ret
) WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
1259 /**********************************************************************
1260 * DIALOG_DlgDirListW
1262 * Helper function for DlgDirList*W
1264 static INT
DIALOG_DlgDirListW( HWND hDlg
, LPWSTR spec
, INT idLBox
,
1265 INT idStatic
, UINT attrib
, BOOL combo
)
1269 LPSTR specA
= HEAP_strdupWtoA( GetProcessHeap(), 0, spec
);
1270 INT ret
= DIALOG_DlgDirList( hDlg
, specA
, idLBox
, idStatic
,
1272 MultiByteToWideChar( CP_ACP
, 0, specA
, -1, spec
, 0x7fffffff );
1273 HeapFree( GetProcessHeap(), 0, specA
);
1276 return DIALOG_DlgDirList( hDlg
, NULL
, idLBox
, idStatic
, attrib
, combo
);
1279 /**********************************************************************
1280 * DIALOG_DlgDirSelect
1282 * Helper function for DlgDirSelect*
1284 static BOOL
DIALOG_DlgDirSelect( HWND hwnd
, LPSTR str
, INT len
,
1285 INT id
, BOOL unicode
, BOOL combo
)
1290 HWND listbox
= GetDlgItem( hwnd
, id
);
1292 DPRINT("%p '%s' %d\n", hwnd
, str
, id
);
1293 if (!listbox
) return FALSE
;
1295 item
= SendMessageA(listbox
, combo
? CB_GETCURSEL
: LB_GETCURSEL
, 0, 0 );
1296 if (item
== LB_ERR
) return FALSE
;
1297 size
= SendMessageA(listbox
, combo
? CB_GETLBTEXTLEN
: LB_GETTEXTLEN
, 0, 0 );
1298 if (size
== LB_ERR
) return FALSE
;
1300 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
+1 ))) return FALSE
;
1302 SendMessageA( listbox
, combo
? CB_GETLBTEXT
: LB_GETTEXT
, item
, (LPARAM
)buffer
);
1304 if ((ret
= (buffer
[0] == '['))) /* drive or directory */
1306 if (buffer
[1] == '-') /* drive */
1314 buffer
[strlen(buffer
)-1] = '\\';
1322 if (len
> 0 && !MultiByteToWideChar( CP_ACP
, 0, ptr
, -1, (LPWSTR
)str
, len
))
1323 ((LPWSTR
)str
)[len
-1] = 0;
1325 else lstrcpynA( str
, ptr
, len
);
1326 HeapFree( GetProcessHeap(), 0, buffer
);
1327 DPRINT("Returning %d '%s'\n", ret
, str
);
1331 /***********************************************************************
1332 * GetDlgItemEnumProc
1334 * Callback for GetDlgItem
1336 BOOL CALLBACK
GetDlgItemEnumProc (HWND hwnd
, LPARAM lParam
)
1338 GETDLGITEMINFO
* info
= (GETDLGITEMINFO
*)lParam
;
1339 if(info
->nIDDlgItem
== GetWindowLongW( hwnd
, GWL_ID
))
1341 info
->control
= hwnd
;
1348 /* FUNCTIONS *****************************************************************/
1355 CreateDialogIndirectParamA(
1356 HINSTANCE hInstance
,
1357 LPCDLGTEMPLATE lpTemplate
,
1359 DLGPROC lpDialogFunc
,
1362 return DIALOG_CreateIndirect( hInstance
, lpTemplate
, hWndParent
, lpDialogFunc
, lParamInit
, FALSE
, FALSE
);
1371 CreateDialogIndirectParamAorW(
1372 HINSTANCE hInstance
,
1373 LPCDLGTEMPLATE lpTemplate
,
1375 DLGPROC lpDialogFunc
,
1379 This function might be obsolete since I don't think it is exported by NT
1380 Also wine has one more parameter identifying weather it should call
1381 the function with unicode or not */
1392 CreateDialogIndirectParamW(
1393 HINSTANCE hInstance
,
1394 LPCDLGTEMPLATE lpTemplate
,
1396 DLGPROC lpDialogFunc
,
1399 return DIALOG_CreateIndirect( hInstance
, lpTemplate
, hWndParent
, lpDialogFunc
, lParamInit
, TRUE
, FALSE
);
1409 HINSTANCE hInstance
,
1410 LPCSTR lpTemplateName
,
1412 DLGPROC lpDialogFunc
,
1418 if (!(hrsrc
= FindResourceA( hInstance
, lpTemplateName
, (LPCSTR
)RT_DIALOG
))) return 0;
1419 if (!(ptr
= (LPCDLGTEMPLATE
)LoadResource(hInstance
, hrsrc
))) return 0;
1420 return CreateDialogIndirectParamA( hInstance
, ptr
, hWndParent
, lpDialogFunc
, dwInitParam
);
1430 HINSTANCE hInstance
,
1431 LPCWSTR lpTemplateName
,
1433 DLGPROC lpDialogFunc
,
1439 if (!(hrsrc
= FindResourceW( hInstance
, lpTemplateName
, (LPCWSTR
)RT_DIALOG
))) return 0;
1440 if (!(ptr
= (LPCDLGTEMPLATE
)LoadResource(hInstance
, hrsrc
))) return 0;
1441 return CreateDialogIndirectParamW( hInstance
, ptr
, hWndParent
, lpDialogFunc
, dwInitParam
);
1457 BOOL result
= FALSE
;
1458 DIALOGINFO
* dlgInfo
;
1460 /* if there's no dialog info property then call default windows proc?? */
1461 if (!(dlgInfo
= GETDLGINFO(hDlg
)))
1462 return DefWindowProcA( hDlg
, Msg
, wParam
, lParam
);
1464 SetWindowLongW( hDlg
, DWL_MSGRESULT
, 0 );
1466 if ((dlgproc
= (WNDPROC
)GetWindowLongA( hDlg
, DWL_DLGPROC
)))
1468 /* Call dialog procedure */
1469 result
= CallWindowProcA( dlgproc
, hDlg
, Msg
, wParam
, lParam
);
1472 if (!result
&& IsWindow(hDlg
))
1474 /* callback didn't process this message */
1488 case WM_ENTERMENULOOP
:
1489 case WM_LBUTTONDOWN
:
1490 case WM_NCLBUTTONDOWN
:
1491 return DEFDLG_Proc( hDlg
, Msg
, wParam
, lParam
, dlgInfo
);
1494 case WM_COMPAREITEM
:
1499 return DefWindowProcA( hDlg
, Msg
, wParam
, lParam
);
1502 return DEFDLG_Epilog(hDlg
, Msg
, result
);
1518 BOOL result
= FALSE
;
1519 DIALOGINFO
* dlgInfo
;
1521 /* if there's no dialog info property then call default windows proc?? */
1522 if (!(dlgInfo
= GETDLGINFO(hDlg
)))
1523 return DefWindowProcW( hDlg
, Msg
, wParam
, lParam
);
1525 SetWindowLongW( hDlg
, DWL_MSGRESULT
, 0 );
1527 if ((dlgproc
= (WNDPROC
)GetWindowLongW( hDlg
, DWL_DLGPROC
)))
1529 /* Call dialog procedure */
1530 result
= CallWindowProcW( dlgproc
, hDlg
, Msg
, wParam
, lParam
);
1533 if (!result
&& IsWindow(hDlg
))
1535 /* callback didn't process this message */
1549 case WM_ENTERMENULOOP
:
1550 case WM_LBUTTONDOWN
:
1551 case WM_NCLBUTTONDOWN
:
1552 return DEFDLG_Proc( hDlg
, Msg
, wParam
, lParam
, dlgInfo
);
1555 case WM_COMPAREITEM
:
1560 return DefWindowProcW( hDlg
, Msg
, wParam
, lParam
);
1563 return DEFDLG_Epilog(hDlg
, Msg
, result
);
1572 DialogBoxIndirectParamA(
1573 HINSTANCE hInstance
,
1574 LPCDLGTEMPLATE hDialogTemplate
,
1576 DLGPROC lpDialogFunc
,
1579 HWND hwnd
= DIALOG_CreateIndirect( hInstance
, hDialogTemplate
, hWndParent
, lpDialogFunc
, dwInitParam
, FALSE
, TRUE
);
1580 if (hwnd
) return DIALOG_DoDialogBox( hwnd
, hWndParent
);
1590 DialogBoxIndirectParamAorW(
1591 HINSTANCE hInstance
,
1592 LPCDLGTEMPLATE hDialogTemplate
,
1594 DLGPROC lpDialogFunc
,
1598 This function might be obsolete since I don't think it is exported by NT
1599 Also wine has one more parameter identifying weather it should call
1600 the function with unicode or not */
1602 return (INT_PTR
)NULL
;
1611 DialogBoxIndirectParamW(
1612 HINSTANCE hInstance
,
1613 LPCDLGTEMPLATE hDialogTemplate
,
1615 DLGPROC lpDialogFunc
,
1618 HWND hwnd
= DIALOG_CreateIndirect( hInstance
, hDialogTemplate
, hWndParent
, lpDialogFunc
, dwInitParam
, TRUE
, TRUE
);
1619 if (hwnd
) return DIALOG_DoDialogBox( hwnd
, hWndParent
);
1630 HINSTANCE hInstance
,
1631 LPCSTR lpTemplateName
,
1633 DLGPROC lpDialogFunc
,
1640 if (!(hrsrc
= FindResourceA( hInstance
, lpTemplateName
, (LPCSTR
)RT_DIALOG
))) return 0;
1641 if (!(ptr
= (LPCDLGTEMPLATE
)LoadResource(hInstance
, hrsrc
))) return 0;
1642 hwnd
= DIALOG_CreateIndirect(hInstance
, ptr
, hWndParent
, lpDialogFunc
, dwInitParam
, FALSE
, TRUE
);
1643 if (hwnd
) return DIALOG_DoDialogBox(hwnd
, hWndParent
);
1654 HINSTANCE hInstance
,
1655 LPCWSTR lpTemplateName
,
1657 DLGPROC lpDialogFunc
,
1664 if (!(hrsrc
= FindResourceW( hInstance
, lpTemplateName
, (LPCWSTR
)RT_DIALOG
))) return 0;
1665 if (!(ptr
= (LPCDLGTEMPLATE
)LoadResource(hInstance
, hrsrc
))) return 0;
1666 hwnd
= DIALOG_CreateIndirect(hInstance
, ptr
, hWndParent
, lpDialogFunc
, dwInitParam
, TRUE
, TRUE
);
1667 if (hwnd
) return DIALOG_DoDialogBox(hwnd
, hWndParent
);
1684 return DIALOG_DlgDirList( hDlg
, lpPathSpec
, nIDListBox
, nIDStaticPath
, uFileType
, FALSE
);
1693 DlgDirListComboBoxA(
1710 DlgDirListComboBoxW(
1734 return DIALOG_DlgDirListW( hDlg
, lpPathSpec
, nIDListBox
, nIDStaticPath
, uFileType
, FALSE
);
1743 DlgDirSelectComboBoxExA(
1759 DlgDirSelectComboBoxExW(
1781 return DIALOG_DlgDirSelect( hDlg
, lpString
, nCount
, nIDListBox
, FALSE
, FALSE
);
1796 return DIALOG_DlgDirSelect( hDlg
, (LPSTR
)lpString
, nCount
, nIDListBox
, TRUE
, FALSE
);
1809 BOOL wasEnabled
= TRUE
;
1810 DIALOGINFO
* dlgInfo
;
1813 if (!(dlgInfo
= GETDLGINFO(hDlg
))) return FALSE
;
1815 dlgInfo
->idResult
= nResult
;
1816 dlgInfo
->flags
|= DF_END
;
1817 wasEnabled
= (dlgInfo
->flags
& DF_OWNERENABLED
);
1819 if (wasEnabled
&& (owner
= GetWindow( hDlg
, GW_OWNER
)))
1820 DIALOG_EnableOwner( owner
);
1822 /* Windows sets the focus to the dialog itself in EndDialog */
1824 if (IsChild(hDlg
, GetFocus()))
1827 /* Don't have to send a ShowWindow(SW_HIDE), just do
1828 SetWindowPos with SWP_HIDEWINDOW as done in Windows */
1830 SetWindowPos(hDlg
, NULL
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
1831 | SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_HIDEWINDOW
);
1833 /* unblock dialog loop */
1834 PostMessageA(hDlg
, WM_NULL
, 0, 0);
1844 GetDialogBaseUnits(VOID
)
1853 if ((hdc
= GetDC(0)))
1855 if (DIALOG_GetCharSize( hdc
, 0, &size
)) units
= MAKELONG( size
.cx
, size
.cy
);
1856 ReleaseDC( 0, hdc
);
1871 return GetWindowLongW( hwndCtl
, GWL_ID
);
1884 GETDLGITEMINFO info
;
1885 info
.nIDDlgItem
= nIDDlgItem
;
1887 if(hDlg
&& !EnumChildWindows(hDlg
, (ENUMWINDOWSPROC
)&GetDlgItemEnumProc
, (LPARAM
)&info
))
1888 return info
.control
;
1909 if (lpTranslated
) *lpTranslated
= FALSE
;
1910 if (!SendDlgItemMessageA(hDlg
, nIDDlgItem
, WM_GETTEXT
, sizeof(str
), (LPARAM
)str
))
1914 result
= strtol( str
, &endptr
, 10 );
1915 if (!endptr
|| (endptr
== str
)) /* Conversion was unsuccessful */
1918 if (((result
== LONG_MIN
) || (result
== LONG_MAX
))/* && (errno == ERANGE) */)
1923 result
= strtoul( str
, &endptr
, 10 );
1924 if (!endptr
|| (endptr
== str
)) /* Conversion was unsuccessful */
1927 if ((result
== LONG_MAX
)/* && (errno == ERANGE) */) return 0;
1929 if (lpTranslated
) *lpTranslated
= TRUE
;
1930 return (UINT
)result
;
1945 return (UINT
)SendDlgItemMessageA( hDlg
, nIDDlgItem
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1960 return (UINT
)SendDlgItemMessageW( hDlg
, nIDDlgItem
, WM_GETTEXT
, nMaxCount
, (LPARAM
)lpString
);
1969 GetNextDlgGroupItem(
1974 HWND hwnd
, retvalue
;
1978 /* if the hwndCtrl is the child of the control in the hwndDlg,
1979 * then the hwndDlg has to be the parent of the hwndCtrl */
1980 if(GetParent(hCtl
) != hDlg
&& GetParent(GetParent(hCtl
)) == hDlg
)
1981 hDlg
= GetParent(hCtl
);
1986 /* Make sure hwndCtrl is a top-level child */
1987 HWND parent
= GetParent( hCtl
);
1988 while (parent
&& parent
!= hDlg
) parent
= GetParent(parent
);
1989 if (parent
!= hDlg
) return 0;
1993 /* No ctrl specified -> start from the beginning */
1994 if (!(hCtl
= GetWindow( hDlg
, GW_CHILD
))) return 0;
1995 if (bPrevious
) hCtl
= GetWindow( hCtl
, GW_HWNDLAST
);
1999 hwnd
= GetWindow( hCtl
, GW_HWNDNEXT
);
2002 if (!hwnd
|| (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_GROUP
))
2004 /* Wrap-around to the beginning of the group */
2007 hwnd
= GetWindow( hDlg
, GW_CHILD
);
2008 for (tmp
= hwnd
; tmp
; tmp
= GetWindow( tmp
, GW_HWNDNEXT
) )
2010 if (GetWindowLongW( tmp
, GWL_STYLE
) & WS_GROUP
) hwnd
= tmp
;
2011 if (tmp
== hCtl
) break;
2014 if (hwnd
== hCtl
) break;
2015 if ((GetWindowLongW( hwnd
, GWL_STYLE
) & (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
)
2018 if (!bPrevious
) break;
2020 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
2036 return DIALOG_GetNextTabItem(hDlg
, hDlg
, hCtl
, bPrevious
);
2046 return IsDialogMessageW(hDlg
, lpMsg
);
2063 //if (CallMsgFilterA( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2065 if ((hDlg
!= lpMsg
->hwnd
) && !IsChild( hDlg
, lpMsg
->hwnd
)) return FALSE
;
2067 hDlg
= DIALOG_FindMsgDestination(hDlg
);
2069 switch(lpMsg
->message
)
2072 dlgCode
= SendMessageA( lpMsg
->hwnd
, WM_GETDLGCODE
, lpMsg
->wParam
, (LPARAM
)lpMsg
);
2073 if (dlgCode
& DLGC_WANTMESSAGE
) break;
2075 switch(lpMsg
->wParam
)
2078 if (!(dlgCode
& DLGC_WANTTAB
))
2080 SendMessageA( hDlg
, WM_NEXTDLGCTL
, (GetKeyState(VK_SHIFT
) & 0x8000), 0 );
2089 if (!(dlgCode
& DLGC_WANTARROWS
))
2091 BOOL fPrevious
= (lpMsg
->wParam
== VK_LEFT
|| lpMsg
->wParam
== VK_UP
);
2092 HWND hwndNext
= GetNextDlgGroupItem (hDlg
, GetFocus(), fPrevious
);
2093 SendMessageA( hDlg
, WM_NEXTDLGCTL
, (WPARAM
)hwndNext
, 1 );
2100 SendMessageA( hDlg
, WM_COMMAND
, IDCANCEL
, (LPARAM
)GetDlgItem( hDlg
, IDCANCEL
) );
2106 DWORD dw
= SendMessageA( hDlg
, DM_GETDEFID
, 0, 0 );
2107 if (HIWORD(dw
) == DC_HASDEFID
)
2109 SendMessageA( hDlg
, WM_COMMAND
, MAKEWPARAM( LOWORD(dw
), BN_CLICKED
),
2110 (LPARAM
)GetDlgItem(hDlg
, LOWORD(dw
)));
2114 SendMessageA( hDlg
, WM_COMMAND
, IDOK
, (LPARAM
)GetDlgItem( hDlg
, IDOK
) );
2123 dlgCode
= SendMessageA( lpMsg
->hwnd
, WM_GETDLGCODE
, lpMsg
->wParam
, (LPARAM
)lpMsg
);
2124 if (dlgCode
& (DLGC_WANTCHARS
|DLGC_WANTMESSAGE
)) break;
2125 if (lpMsg
->wParam
== '\t' && (dlgCode
& DLGC_WANTTAB
)) break;
2129 if (DIALOG_IsAccelerator( lpMsg
->hwnd
, hDlg
, lpMsg
->wParam
))
2131 /* don't translate or dispatch */
2137 TranslateMessage( lpMsg
);
2138 DispatchMessageA( lpMsg
);
2155 //if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2157 if ((hDlg
!= lpMsg
->hwnd
) && !IsChild( hDlg
, lpMsg
->hwnd
)) return FALSE
;
2159 hDlg
= DIALOG_FindMsgDestination(hDlg
);
2161 switch(lpMsg
->message
)
2164 dlgCode
= SendMessageW( lpMsg
->hwnd
, WM_GETDLGCODE
, lpMsg
->wParam
, (LPARAM
)lpMsg
);
2165 if (dlgCode
& DLGC_WANTMESSAGE
) break;
2167 switch(lpMsg
->wParam
)
2170 if (!(dlgCode
& DLGC_WANTTAB
))
2172 SendMessageW( hDlg
, WM_NEXTDLGCTL
, (GetKeyState(VK_SHIFT
) & 0x8000), 0 );
2181 if (!(dlgCode
& DLGC_WANTARROWS
))
2183 BOOL fPrevious
= (lpMsg
->wParam
== VK_LEFT
|| lpMsg
->wParam
== VK_UP
);
2184 HWND hwndNext
= GetNextDlgGroupItem (hDlg
, GetFocus(), fPrevious
);
2185 SendMessageW( hDlg
, WM_NEXTDLGCTL
, (WPARAM
)hwndNext
, 1 );
2192 SendMessageW( hDlg
, WM_COMMAND
, IDCANCEL
, (LPARAM
)GetDlgItem( hDlg
, IDCANCEL
) );
2198 DWORD dw
= SendMessageW( hDlg
, DM_GETDEFID
, 0, 0 );
2199 if (HIWORD(dw
) == DC_HASDEFID
)
2201 SendMessageW( hDlg
, WM_COMMAND
, MAKEWPARAM( LOWORD(dw
), BN_CLICKED
),
2202 (LPARAM
)GetDlgItem(hDlg
, LOWORD(dw
)));
2206 SendMessageW( hDlg
, WM_COMMAND
, IDOK
, (LPARAM
)GetDlgItem( hDlg
, IDOK
) );
2215 dlgCode
= SendMessageW( lpMsg
->hwnd
, WM_GETDLGCODE
, lpMsg
->wParam
, (LPARAM
)lpMsg
);
2216 if (dlgCode
& (DLGC_WANTCHARS
|DLGC_WANTMESSAGE
)) break;
2217 if (lpMsg
->wParam
== '\t' && (dlgCode
& DLGC_WANTTAB
)) break;
2221 if (DIALOG_IsAccelerator( lpMsg
->hwnd
, hDlg
, lpMsg
->wParam
))
2223 /* don't translate or dispatch */
2229 TranslateMessage( lpMsg
);
2230 DispatchMessageW( lpMsg
);
2244 return (UINT
)SendDlgItemMessageA( hDlg
, nIDButton
, BM_GETCHECK
, 0, 0 );
2257 DIALOGINFO
* dlgInfo
;
2258 if (!(dlgInfo
= GETDLGINFO(hDlg
))) return FALSE
;
2259 lpRect
->left
= MulDiv(lpRect
->left
, dlgInfo
->xBaseUnit
, 4);
2260 lpRect
->right
= MulDiv(lpRect
->right
, dlgInfo
->xBaseUnit
, 4);
2261 lpRect
->top
= MulDiv(lpRect
->top
, dlgInfo
->yBaseUnit
, 8);
2262 lpRect
->bottom
= MulDiv(lpRect
->bottom
, dlgInfo
->yBaseUnit
, 8);
2272 SendDlgItemMessageA(
2279 HWND hwndCtrl
= GetDlgItem( hDlg
, nIDDlgItem
);
2280 if (hwndCtrl
) return SendMessageA( hwndCtrl
, Msg
, wParam
, lParam
);
2290 SendDlgItemMessageW(
2297 HWND hwndCtrl
= GetDlgItem( hDlg
, nIDDlgItem
);
2298 if (hwndCtrl
) return SendMessageW( hwndCtrl
, Msg
, wParam
, lParam
);
2316 if (bSigned
) sprintf( str
, "%d", (INT
)uValue
);
2317 else sprintf( str
, "%u", uValue
);
2318 SendDlgItemMessageA( hDlg
, nIDDlgItem
, WM_SETTEXT
, 0, (LPARAM
)str
);
2333 return SendDlgItemMessageA( hDlg
, nIDDlgItem
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2347 return SendDlgItemMessageW( hDlg
, nIDDlgItem
, WM_SETTEXT
, 0, (LPARAM
)lpString
);
2361 SendDlgItemMessageA( hDlg
, nIDButton
, BM_SETCHECK
, uCheck
, 0 );
2365 static BOOL CALLBACK
CheckRB(HWND hwnd
, LPARAM lParam
)
2367 LONG lChildID
= GetWindowLongW(hwnd
, GWL_ID
);
2368 RADIOGROUP
*lpRadioGroup
= (RADIOGROUP
*)lParam
;
2370 if((lChildID
>= lpRadioGroup
->firstID
) &&
2371 (lChildID
<= lpRadioGroup
->lastID
))
2373 if (lChildID
== lpRadioGroup
->checkID
)
2375 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2379 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2397 RADIOGROUP radioGroup
;
2399 radioGroup
.firstID
= nIDFirstButton
;
2400 radioGroup
.lastID
= nIDLastButton
;
2401 radioGroup
.checkID
= nIDCheckButton
;
2403 return EnumChildWindows(hDlg
, CheckRB
, (LPARAM
)&radioGroup
);