4 * Copyright 1993 Alexandre Julliard
7 /* #define DEBUG_DIALOG /* */
9 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
22 /* Dialog base units */
23 static WORD xBaseUnit
= 0, yBaseUnit
= 0;
26 /***********************************************************************
29 * Initialisation of the dialog manager.
36 /* Calculate the dialog base units */
38 if (!(hdc
= GetDC(GetDesktopWindow()))) return FALSE
;
39 GetTextMetrics( hdc
, &tm
);
41 xBaseUnit
= tm
.tmAveCharWidth
;
42 yBaseUnit
= tm
.tmHeight
;
44 printf( "DIALOG_Init: base units = %d,%d\n", xBaseUnit
, yBaseUnit
);
50 /***********************************************************************
53 * Return the class and text of the control pointed to by ptr,
54 * and return a pointer to the next control.
56 static DLGCONTROLHEADER
* DIALOG_GetControl( DLGCONTROLHEADER
* ptr
,
57 char ** class, char ** text
)
60 unsigned char * p
= (unsigned char *)ptr
;
61 p
+= 14; /* size of control header */
67 case 0x80: *class = "BUTTON"; break;
68 case 0x81: *class = "EDIT"; break;
69 case 0x82: *class = "STATIC"; break;
70 case 0x83: *class = "LISTBOX"; break;
71 case 0x84: *class = "SCROLLBAR"; break;
72 case 0x85: *class = "COMBOBOX"; break;
73 default: *class = ""; break;
81 /* FIXME: how can I determine if the resource id is an integer or a string ? */
83 /* *(DWORD*)text = (*p << 8) | *p;*/
84 *(DWORD
*)text
= 0xebeb;
90 return (DLGCONTROLHEADER
*)p
;
94 /***********************************************************************
95 * DIALOG_ParseTemplate
97 * Fill a DLGTEMPLATE structure from the dialog template, and return
98 * a pointer to the first control.
100 static DLGCONTROLHEADER
* DIALOG_ParseTemplate( LPCSTR
template,
101 DLGTEMPLATE
* result
)
103 unsigned char * p
= (unsigned char *)template;
105 result
->header
= (DLGTEMPLATEHEADER
*)p
;
108 result
->menuName
= p
;
109 if (*p
== 0xff) p
+= 3;
110 else p
+= strlen(p
) + 1;
112 if (*p
) result
->className
= p
;
113 else result
->className
= DIALOG_CLASS_NAME
;
119 if (result
->header
->style
& DS_SETFONT
)
121 result
->pointSize
= *(WORD
*)p
; p
+= sizeof(WORD
);
122 result
->faceName
= p
; p
+= strlen(p
) + 1;
125 return (DLGCONTROLHEADER
*)p
;
129 /***********************************************************************
130 * DIALOG_DisplayTemplate
133 static void DIALOG_DisplayTemplate( DLGTEMPLATE
* result
)
135 printf( "DIALOG %d, %d, %d, %d\n", result
->header
->x
, result
->header
->y
,
136 result
->header
->cx
, result
->header
->cy
);
137 printf( " STYLE %08x\n", result
->header
->style
);
138 printf( " CAPTION '%s'\n", result
->caption
);
139 printf( " CLASS '%s'\n", result
->className
);
140 if (result
->menuName
[0] == 0xff)
141 printf( " MENU %d\n", result
->menuName
[1] + 256*result
->menuName
[2] );
142 else printf( " MENU '%s'\n", result
->menuName
);
143 if (result
->header
->style
& DS_SETFONT
)
144 printf( " FONT %d,'%s'\n", result
->pointSize
, result
->faceName
);
146 #endif /* DEBUG_DIALOG */
149 /***********************************************************************
150 * CreateDialog (USER.89)
152 HWND
CreateDialog( HINSTANCE hInst
, LPCSTR dlgTemplate
,
153 HWND owner
, FARPROC dlgProc
)
155 return CreateDialogParam( hInst
, dlgTemplate
, owner
, dlgProc
, 0 );
159 /***********************************************************************
160 * CreateDialogParam (USER.241)
162 HWND
CreateDialogParam( HINSTANCE hInst
, LPCSTR dlgTemplate
,
163 HWND owner
, FARPROC dlgProc
, LPARAM param
)
170 printf( "CreateDialogParam: %d,'%x',%d,%p,%d\n",
171 hInst
, dlgTemplate
, owner
, dlgProc
, param
);
174 /* FIXME: MAKEINTRESOURCE should be replaced by RT_DIALOG */
175 if (!(hres
= FindResource( hInst
, dlgTemplate
, MAKEINTRESOURCE(0x8005) )))
177 if (!(hmem
= LoadResource( hInst
, hres
))) return 0;
178 if (!(data
= LockResource( hmem
))) hwnd
= 0;
179 else hwnd
= CreateDialogIndirectParam(hInst
, data
, owner
, dlgProc
, param
);
180 FreeResource( hmem
);
185 /***********************************************************************
186 * CreateDialogIndirect (USER.219)
188 HWND
CreateDialogIndirect( HINSTANCE hInst
, LPCSTR dlgTemplate
,
189 HWND owner
, FARPROC dlgProc
)
191 return CreateDialogIndirectParam( hInst
, dlgTemplate
, owner
, dlgProc
, 0 );
195 /***********************************************************************
196 * CreateDialogIndirectParam (USER.242)
198 HWND
CreateDialogIndirectParam( HINSTANCE hInst
, LPCSTR dlgTemplate
,
199 HWND owner
, FARPROC dlgProc
, LPARAM param
)
207 DLGTEMPLATE
template;
208 DLGCONTROLHEADER
* header
;
209 DIALOGINFO
* dlgInfo
;
211 WORD xUnit
= xBaseUnit
;
212 WORD yUnit
= yBaseUnit
;
216 /* Parse dialog template */
218 if (!dlgTemplate
) return 0;
219 header
= DIALOG_ParseTemplate( dlgTemplate
, &template );
221 DIALOG_DisplayTemplate( &template );
226 switch (template.menuName
[0])
232 hMenu
= LoadMenu( hInst
, MAKEINTRESOURCE( template.menuName
[1] +
233 256*template.menuName
[2] ));
236 hMenu
= LoadMenu( hInst
, template.menuName
);
240 /* Create custom font if needed */
242 if (template.header
->style
& DS_SETFONT
)
244 hFont
= CreateFont( template.pointSize
, 0, 0, 0, FW_DONTCARE
,
245 FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
, 0, 0,
246 DEFAULT_QUALITY
, FF_DONTCARE
, template.faceName
);
254 oldFont
= SelectObject( hdc
, hFont
);
255 GetTextMetrics( hdc
, &tm
);
256 SelectObject( hdc
, oldFont
);
258 xUnit
= tm
.tmAveCharWidth
;
263 /* Create dialog main window */
265 rect
.left
= rect
.top
= 0;
266 rect
.right
= template.header
->cx
* xUnit
/ 4;
267 rect
.bottom
= template.header
->cy
* yUnit
/ 8;
268 if (template.header
->style
& DS_MODALFRAME
) exStyle
|= WS_EX_DLGMODALFRAME
;
269 AdjustWindowRectEx( &rect
, template.header
->style
, hMenu
, exStyle
);
271 hwnd
= CreateWindowEx( exStyle
, template.className
, template.caption
,
272 template.header
->style
,
273 rect
.left
+ template.header
->x
* xUnit
/ 4,
274 rect
.top
+ template.header
->y
* yUnit
/ 8,
275 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
280 if (hFont
) DeleteObject( hFont
);
281 if (hMenu
) DestroyMenu( hMenu
);
285 /* Create control windows */
288 printf( " BEGIN\n" );
291 wndPtr
= WIN_FindWndPtr( hwnd
);
292 dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
293 dlgInfo
->hDialogHeap
= 0;
295 for (i
= 0; i
< template.header
->nbItems
; i
++)
297 DLGCONTROLHEADER
* next_header
;
299 next_header
= DIALOG_GetControl( header
, &class, &text
);
302 printf( " %s ", class);
303 if ((DWORD
*)text
< 0x10000)
304 printf("'%4X'", (DWORD
*)text
);
306 printf("'%s'", text
);
308 printf(" %d, %d, %d, %d, %d, %08x\n", header
->id
, header
->x
, header
->y
,
309 header
->cx
, header
->cy
, header
->style
);
312 if ((strcmp(class, "EDIT") == 0) &&
313 ((header
->style
& DS_LOCALEDIT
) != DS_LOCALEDIT
)) {
314 if (!dlgInfo
->hDialogHeap
) {
315 dlgInfo
->hDialogHeap
= GlobalAlloc(GMEM_FIXED
, 0x10000);
316 if (!dlgInfo
->hDialogHeap
) {
317 printf("CreateDialogIndirectParam: Insufficient memory ",
318 "to create heap for edit control\n");
321 dlgHeapBase
= GlobalLock(dlgInfo
->hDialogHeap
);
322 HEAP_Init(&dlgHeap
, dlgHeapBase
, 0x10000);
324 header
->style
|= WS_CHILD
;
325 CreateWindowEx( WS_EX_NOPARENTNOTIFY
,
326 class, text
, header
->style
,
327 header
->x
* xUnit
/ 4, header
->y
* yUnit
/ 8,
328 header
->cx
* xUnit
/ 4, header
->cy
* yUnit
/ 8,
329 hwnd
, header
->id
, HIWORD((LONG
)dlgHeapBase
), NULL
);
332 if ((strcmp(class, "STATIC") == 0) &
333 ((header
->style
& SS_ICON
) == SS_ICON
)) {
337 header
->style
|= WS_CHILD
;
338 CreateWindowEx( WS_EX_NOPARENTNOTIFY
,
339 class, text
, header
->style
,
340 header
->x
* xUnit
/ 4, header
->y
* yUnit
/ 8,
341 header
->cx
* xUnit
/ 4, header
->cy
* yUnit
/ 8,
342 hwnd
, header
->id
, hInst
, NULL
);
344 header
= next_header
;
351 /* Initialise dialog extra data */
353 dlgInfo
->dlgProc
= dlgProc
;
354 dlgInfo
->hUserFont
= hFont
;
355 dlgInfo
->hMenu
= hMenu
;
356 dlgInfo
->xBaseUnit
= xUnit
;
357 dlgInfo
->yBaseUnit
= yUnit
;
358 dlgInfo
->hwndFocus
= GetNextDlgTabItem( hwnd
,
359 GetWindow(wndPtr
->hwndChild
, GW_HWNDLAST
), FALSE
);
361 /* Send initialisation messages and set focus */
363 if (dlgInfo
->hUserFont
)
364 SendMessage( hwnd
, WM_SETFONT
, dlgInfo
->hUserFont
, 0 );
365 if (SendMessage( hwnd
, WM_INITDIALOG
, dlgInfo
->hwndFocus
, param
))
366 SetFocus( dlgInfo
->hwndFocus
);
372 /***********************************************************************
375 static int DIALOG_DoDialogBox( HWND hwnd
, HWND owner
)
378 DIALOGINFO
* dlgInfo
;
383 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return -1;
384 if (!(msgHandle
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(MSG
)))) return -1;
385 lpmsg
= (MSG
*) USER_HEAP_ADDR( msgHandle
);
386 dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
387 ShowWindow( hwnd
, SW_SHOW
);
389 while (MSG_InternalGetMessage( lpmsg
, hwnd
, owner
, MSGF_DIALOGBOX
,
392 if (!IsDialogMessage( hwnd
, lpmsg
))
394 TranslateMessage( lpmsg
);
395 DispatchMessage( lpmsg
);
397 if (dlgInfo
->fEnd
) break;
399 retval
= dlgInfo
->msgResult
;
400 DestroyWindow( hwnd
);
401 USER_HEAP_FREE( msgHandle
);
406 /***********************************************************************
407 * DialogBox (USER.87)
409 int DialogBox( HINSTANCE hInst
, LPCSTR dlgTemplate
,
410 HWND owner
, FARPROC dlgProc
)
412 return DialogBoxParam( hInst
, dlgTemplate
, owner
, dlgProc
, 0 );
416 /***********************************************************************
417 * DialogBoxParam (USER.239)
419 int DialogBoxParam( HINSTANCE hInst
, LPCSTR dlgTemplate
,
420 HWND owner
, FARPROC dlgProc
, LPARAM param
)
425 printf( "DialogBoxParam: %d,'%x',%d,%p,%d\n",
426 hInst
, dlgTemplate
, owner
, dlgProc
, param
);
428 hwnd
= CreateDialogParam( hInst
, dlgTemplate
, owner
, dlgProc
, param
);
429 if (hwnd
) return DIALOG_DoDialogBox( hwnd
, owner
);
434 /***********************************************************************
435 * DialogBoxIndirect (USER.218)
437 int DialogBoxIndirect( HINSTANCE hInst
, HANDLE dlgTemplate
,
438 HWND owner
, FARPROC dlgProc
)
440 return DialogBoxIndirectParam( hInst
, dlgTemplate
, owner
, dlgProc
, 0 );
444 /***********************************************************************
445 * DialogBoxIndirectParam (USER.240)
447 int DialogBoxIndirectParam( HINSTANCE hInst
, HANDLE dlgTemplate
,
448 HWND owner
, FARPROC dlgProc
, LPARAM param
)
453 if (!(ptr
= GlobalLock( dlgTemplate
))) return -1;
454 hwnd
= CreateDialogIndirectParam( hInst
, ptr
, owner
, dlgProc
, param
);
455 GlobalUnlock( dlgTemplate
);
456 if (hwnd
) return DIALOG_DoDialogBox( hwnd
, owner
);
461 /***********************************************************************
462 * EndDialog (USER.88)
464 void EndDialog( HWND hwnd
, short retval
)
466 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
467 DIALOGINFO
* dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
468 dlgInfo
->msgResult
= retval
;
469 dlgInfo
->fEnd
= TRUE
;
471 printf( "EndDialog: %d %d\n", hwnd
, retval
);
476 /***********************************************************************
477 * IsDialogMessage (USER.90)
479 BOOL
IsDialogMessage( HWND hwndDlg
, LPMSG msg
)
483 if (!(wndPtr
= WIN_FindWndPtr( hwndDlg
))) return FALSE
;
484 if ((hwndDlg
!= msg
->hwnd
) && !IsChild( hwndDlg
, msg
->hwnd
)) return FALSE
;
486 if (msg
->message
!= WM_KEYDOWN
)
488 SendMessage( msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
492 int dlgCode
= SendMessage( msg
->hwnd
, WM_GETDLGCODE
, 0, 0 );
493 /* Process key message */
495 SendMessage( msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
501 /****************************************************************
502 * GetDlgCtrlID (USER.277)
504 int GetDlgCtrlID( HWND hwnd
)
506 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
507 if (wndPtr
) return wndPtr
->wIDmenu
;
512 /***********************************************************************
513 * GetDlgItem (USER.91)
515 HWND
GetDlgItem( HWND hwndDlg
, WORD id
)
521 if (!(wndPtr
= WIN_FindWndPtr( hwndDlg
))) return 0;
522 curChild
= wndPtr
->hwndChild
;
525 childPtr
= WIN_FindWndPtr( curChild
);
526 if (childPtr
->wIDmenu
== id
) return curChild
;
527 curChild
= childPtr
->hwndNext
;
533 /*******************************************************************
534 * SendDlgItemMessage (USER.101)
536 LONG
SendDlgItemMessage(HWND hwnd
, WORD id
, UINT msg
, WORD wParam
, LONG lParam
)
538 HWND hwndCtrl
= GetDlgItem( hwnd
, id
);
539 if (hwndCtrl
) return SendMessage( hwndCtrl
, msg
, wParam
, lParam
);
544 /*******************************************************************
545 * SetDlgItemText (USER.92)
547 void SetDlgItemText( HWND hwnd
, WORD id
, LPSTR lpString
)
549 SendDlgItemMessage( hwnd
, id
, WM_SETTEXT
, 0, (DWORD
)lpString
);
553 /***********************************************************************
554 * GetDlgItemText (USER.93)
556 int GetDlgItemText( HWND hwnd
, WORD id
, LPSTR str
, WORD max
)
558 return (int)SendDlgItemMessage( hwnd
, id
, WM_GETTEXT
, max
, (DWORD
)str
);
562 /*******************************************************************
563 * SetDlgItemInt (USER.94)
565 void SetDlgItemInt( HWND hwnd
, WORD id
, WORD value
, BOOL fSigned
)
567 HANDLE hText
= USER_HEAP_ALLOC(0, 10 );
568 char * str
= (char *) USER_HEAP_ADDR( hText
);
570 if (fSigned
) sprintf( str
, "%d", value
);
571 else sprintf( str
, "%u", value
);
572 SendDlgItemMessage( hwnd
, id
, WM_SETTEXT
, 0, (DWORD
)str
);
573 USER_HEAP_FREE( hText
);
577 /***********************************************************************
578 * GetDlgItemInt (USER.95)
580 WORD
GetDlgItemInt( HWND hwnd
, WORD id
, BOOL
* translated
, BOOL fSigned
)
587 if (translated
) *translated
= FALSE
;
588 if (!(len
= SendDlgItemMessage( hwnd
, id
, WM_GETTEXTLENGTH
, 0, 0 )))
590 if (!(hText
= USER_HEAP_ALLOC(0, len
+1 )))
592 str
= (char *) USER_HEAP_ADDR( hText
);
593 if (SendDlgItemMessage( hwnd
, id
, WM_GETTEXT
, len
+1, (DWORD
)str
))
596 result
= strtol( str
, &endptr
, 10 );
597 if (endptr
&& (endptr
!= str
)) /* Conversion was successful */
601 if ((result
< -32767) || (result
> 32767)) result
= 0;
602 else if (translated
) *translated
= TRUE
;
606 if ((result
< 0) || (result
> 65535)) result
= 0;
607 else if (translated
) *translated
= TRUE
;
611 USER_HEAP_FREE( hText
);
616 /***********************************************************************
617 * CheckDlgButton (USER.97)
619 void CheckDlgButton( HWND hwnd
, WORD id
, WORD check
)
621 SendDlgItemMessage( hwnd
, id
, BM_SETCHECK
, check
, 0 );
625 /***********************************************************************
626 * IsDlgButtonChecked (USER.98)
628 WORD
IsDlgButtonChecked( HWND hwnd
, WORD id
)
630 return (WORD
)SendDlgItemMessage( hwnd
, id
, BM_GETCHECK
, 0, 0 );
634 /***********************************************************************
635 * CheckRadioButton (USER.96)
637 void CheckRadioButton( HWND hwndDlg
, WORD firstID
, WORD lastID
, WORD checkID
)
639 HWND button
= GetDlgItem( hwndDlg
, lastID
);
642 WND
* wndPtr
= WIN_FindWndPtr( button
);
644 SendMessage( button
, BM_SETCHECK
, (wndPtr
->wIDmenu
== checkID
), 0 );
645 if (wndPtr
->wIDmenu
== firstID
) break;
646 button
= wndPtr
->hwndNext
;
651 /***********************************************************************
652 * GetDialogBaseUnits (USER.243)
654 DWORD
GetDialogBaseUnits()
656 return MAKELONG( xBaseUnit
, yBaseUnit
);
660 /***********************************************************************
661 * MapDialogRect (USER.103)
663 void MapDialogRect( HWND hwnd
, LPRECT rect
)
665 DIALOGINFO
* dlgInfo
;
666 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
668 dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
669 rect
->left
= (rect
->left
* dlgInfo
->xBaseUnit
) / 4;
670 rect
->right
= (rect
->right
* dlgInfo
->xBaseUnit
) / 4;
671 rect
->top
= (rect
->top
* dlgInfo
->yBaseUnit
) / 8;
672 rect
->bottom
= (rect
->bottom
* dlgInfo
->yBaseUnit
) / 8;
676 /***********************************************************************
677 * GetNextDlgGroupItem (USER.227)
679 HWND
GetNextDlgGroupItem( HWND hwndDlg
, HWND hwndCtrl
, BOOL fPrevious
)
682 WND
* dlgPtr
, * ctrlPtr
, * wndPtr
;
684 if (!(dlgPtr
= WIN_FindWndPtr( hwndDlg
))) return 0;
685 if (!(ctrlPtr
= WIN_FindWndPtr( hwndCtrl
))) return 0;
686 if (ctrlPtr
->hwndParent
!= hwndDlg
) return 0;
689 hwnd
= ctrlPtr
->hwndNext
;
692 if (!hwnd
) hwnd
= dlgPtr
->hwndChild
;
693 if (hwnd
== hwndCtrl
) break;
694 wndPtr
= WIN_FindWndPtr( hwnd
);
695 if (wndPtr
->dwStyle
& WS_TABSTOP
)
698 if (!fPrevious
) break;
700 hwnd
= wndPtr
->hwndNext
;
707 /***********************************************************************
708 * GetNextDlgTabItem (USER.228)
710 HWND
GetNextDlgTabItem( HWND hwndDlg
, HWND hwndCtrl
, BOOL fPrevious
)
713 WND
* dlgPtr
, * ctrlPtr
, * wndPtr
;
715 if (!(dlgPtr
= WIN_FindWndPtr( hwndDlg
))) return 0;
716 if (!(ctrlPtr
= WIN_FindWndPtr( hwndCtrl
))) return 0;
717 if (ctrlPtr
->hwndParent
!= hwndDlg
) return 0;
720 hwnd
= ctrlPtr
->hwndNext
;
723 if (!hwnd
) hwnd
= dlgPtr
->hwndChild
;
724 if (hwnd
== hwndCtrl
) break;
725 wndPtr
= WIN_FindWndPtr( hwnd
);
726 if (wndPtr
->dwStyle
& WS_TABSTOP
)
729 if (!fPrevious
) break;
731 hwnd
= wndPtr
->hwndNext
;