Release 940518
[wine/multimedia.git] / windows / dialog.c
blob772408452e746f6d939a5aa8a56c9fe731f972c3
1 /*
2 * Dialog functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #define DEBUG_DIALOG /* */
9 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include "windows.h"
15 #include "dialog.h"
16 #include "win.h"
17 #include "user.h"
20 /* Dialog base units */
21 static WORD xBaseUnit = 0, yBaseUnit = 0;
24 /***********************************************************************
25 * DIALOG_Init
27 * Initialisation of the dialog manager.
29 BOOL DIALOG_Init()
31 TEXTMETRIC tm;
32 HDC hdc;
34 /* Calculate the dialog base units */
36 if (!(hdc = GetDC(GetDesktopWindow()))) return FALSE;
37 GetTextMetrics( hdc, &tm );
38 ReleaseDC( 0, hdc );
39 xBaseUnit = tm.tmAveCharWidth;
40 yBaseUnit = tm.tmHeight;
41 #ifdef DEBUG_DIALOG
42 printf( "DIALOG_Init: base units = %d,%d\n", xBaseUnit, yBaseUnit );
43 #endif
44 return TRUE;
48 /***********************************************************************
49 * DIALOG_GetControl
51 * Return the class and text of the control pointed to by ptr,
52 * and return a pointer to the next control.
54 static DLGCONTROLHEADER * DIALOG_GetControl( DLGCONTROLHEADER * ptr,
55 char ** class, char ** text )
57 unsigned char * p = (unsigned char *)ptr;
58 p += 14; /* size of control header */
59 if (*p & 0x80)
61 switch(*p++)
63 case 0x80: *class = "BUTTON"; break;
64 case 0x81: *class = "EDIT"; break;
65 case 0x82: *class = "STATIC"; break;
66 case 0x83: *class = "LISTBOX"; break;
67 case 0x84: *class = "SCROLLBAR"; break;
68 case 0x85: *class = "COMBOBOX"; break;
69 default: *class = ""; break;
72 else
74 *class = p;
75 p += strlen(p) + 1;
77 *text = p;
78 p += strlen(p) + 2;
79 return (DLGCONTROLHEADER *)p;
83 /***********************************************************************
84 * DIALOG_ParseTemplate
86 * Fill a DLGTEMPLATE structure from the dialog template, and return
87 * a pointer to the first control.
89 static DLGCONTROLHEADER * DIALOG_ParseTemplate( LPCSTR template,
90 DLGTEMPLATE * result )
92 unsigned char * p = (unsigned char *)template;
94 result->header = (DLGTEMPLATEHEADER *)p;
95 p += 13;
97 result->menuName = p;
98 if (*p == 0xff) p += 3;
99 else p += strlen(p) + 1;
101 if (*p) result->className = p;
102 else result->className = DIALOG_CLASS_NAME;
103 p += strlen(p) + 1;
105 result->caption = p;
106 p += strlen(p) + 1;
108 if (result->header->style & DS_SETFONT)
110 result->pointSize = *(WORD *)p; p += sizeof(WORD);
111 result->faceName = p; p += strlen(p) + 1;
114 return (DLGCONTROLHEADER *)p;
118 /***********************************************************************
119 * DIALOG_DisplayTemplate
121 #ifdef DEBUG_DIALOG
122 static void DIALOG_DisplayTemplate( DLGTEMPLATE * result )
124 printf( "DIALOG %d, %d, %d, %d\n", result->header->x, result->header->y,
125 result->header->cx, result->header->cy );
126 printf( " STYLE %08x\n", result->header->style );
127 printf( " CAPTION '%s'\n", result->caption );
128 printf( " CLASS '%s'\n", result->className );
129 if (result->menuName[0] == 0xff)
130 printf( " MENU %d\n", result->menuName[1] + 256*result->menuName[2] );
131 else printf( " MENU '%s'\n", result->menuName );
132 if (result->header->style & DS_SETFONT)
133 printf( " FONT %d,'%s'\n", result->pointSize, result->faceName );
135 #endif /* DEBUG_DIALOG */
138 /***********************************************************************
139 * CreateDialog (USER.89)
141 HWND CreateDialog( HINSTANCE hInst, LPCSTR dlgTemplate,
142 HWND owner, FARPROC dlgProc )
144 return CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, 0 );
148 /***********************************************************************
149 * CreateDialogParam (USER.241)
151 HWND CreateDialogParam( HINSTANCE hInst, LPCSTR dlgTemplate,
152 HWND owner, FARPROC dlgProc, LPARAM param )
154 HWND hwnd = 0;
155 HANDLE hres, hmem;
156 LPCSTR data;
158 #ifdef DEBUG_DIALOG
159 printf( "CreateDialogParam: %d,'%s',%d,%p,%d\n",
160 hInst, dlgTemplate, owner, dlgProc, param );
161 #endif
163 /* FIXME: MAKEINTRESOURCE should be replaced by RT_DIALOG */
164 if (!(hres = FindResource( hInst, dlgTemplate, MAKEINTRESOURCE(0x8005) )))
165 return 0;
166 if (!(hmem = LoadResource( hInst, hres ))) return 0;
167 if (!(data = LockResource( hmem ))) hwnd = 0;
168 else hwnd = CreateDialogIndirectParam(hInst, data, owner, dlgProc, param);
169 FreeResource( hmem );
170 return hwnd;
174 /***********************************************************************
175 * CreateDialogIndirect (USER.219)
177 HWND CreateDialogIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
178 HWND owner, FARPROC dlgProc )
180 return CreateDialogIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
184 /***********************************************************************
185 * CreateDialogIndirectParam (USER.242)
187 HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate,
188 HWND owner, FARPROC dlgProc, LPARAM param )
190 HMENU hMenu;
191 HFONT hFont = 0;
192 HWND hwnd;
193 RECT rect;
194 WND * wndPtr;
195 int i;
196 DLGTEMPLATE template;
197 DLGCONTROLHEADER * header;
198 DIALOGINFO * dlgInfo;
199 DWORD exStyle = 0;
200 WORD xUnit = xBaseUnit;
201 WORD yUnit = yBaseUnit;
203 /* Parse dialog template */
205 if (!dlgTemplate) return 0;
206 header = DIALOG_ParseTemplate( dlgTemplate, &template );
207 #ifdef DEBUG_DIALOG
208 DIALOG_DisplayTemplate( &template );
209 #endif
211 /* Load menu */
213 switch (template.menuName[0])
215 case 0x00:
216 hMenu = 0;
217 break;
218 case 0xff:
219 hMenu = LoadMenu( hInst, MAKEINTRESOURCE( template.menuName[1] +
220 256*template.menuName[2] ));
221 break;
222 default:
223 hMenu = LoadMenu( hInst, template.menuName );
224 break;
227 /* Create custom font if needed */
229 if (template.header->style & DS_SETFONT)
231 hFont = CreateFont( template.pointSize, 0, 0, 0, FW_DONTCARE,
232 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
233 DEFAULT_QUALITY, FF_DONTCARE, template.faceName );
234 if (hFont)
236 TEXTMETRIC tm;
237 HFONT oldFont;
238 HDC hdc;
240 hdc = GetDC(0);
241 oldFont = SelectObject( hdc, hFont );
242 GetTextMetrics( hdc, &tm );
243 SelectObject( hdc, oldFont );
244 ReleaseDC( 0, hdc );
245 xUnit = tm.tmAveCharWidth;
246 yUnit = tm.tmHeight;
250 /* Create dialog main window */
252 rect.left = rect.top = 0;
253 rect.right = template.header->cx * xUnit / 4;
254 rect.bottom = template.header->cy * yUnit / 8;
255 if (template.header->style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
256 AdjustWindowRectEx( &rect, template.header->style, hMenu, exStyle );
258 hwnd = CreateWindowEx( exStyle, template.className, template.caption,
259 template.header->style,
260 rect.left + template.header->x * xUnit / 4,
261 rect.top + template.header->y * yUnit / 8,
262 rect.right - rect.left, rect.bottom - rect.top,
263 owner, hMenu, hInst,
264 NULL );
265 if (!hwnd)
267 if (hFont) DeleteObject( hFont );
268 if (hMenu) DestroyMenu( hMenu );
269 return 0;
272 ShowWindow(hwnd, SW_SHOWNORMAL);
273 UpdateWindow(hwnd);
275 /* Create control windows */
277 #ifdef DEBUG_DIALOG
278 printf( " BEGIN\n" );
279 #endif
281 for (i = 0; i < template.header->nbItems; i++)
283 DLGCONTROLHEADER * next_header;
284 LPSTR class, text;
285 next_header = DIALOG_GetControl( header, &class, &text );
287 #ifdef DEBUG_DIALOG
288 printf( " %s '%s' %d, %d, %d, %d, %d, %08x\n",
289 class, text, header->id, header->x, header->y, header->cx,
290 header->cy, header->style );
291 #endif
292 if ((strcmp(class, "STATIC") == 0) & ((header->style & SS_ICON) == SS_ICON)) {
293 header->cx = 32;
294 header->cy = 32;
296 header->style |= WS_CHILD;
297 CreateWindowEx( WS_EX_NOPARENTNOTIFY,
298 class, text, header->style,
299 header->x * xUnit / 4, header->y * yUnit / 8,
300 header->cx * xUnit / 4, header->cy * yUnit / 8,
301 hwnd, header->id, hInst, NULL );
302 header = next_header;
305 #ifdef DEBUG_DIALOG
306 printf( " END\n" );
307 #endif
309 /* Initialise dialog extra data */
311 wndPtr = WIN_FindWndPtr( hwnd );
312 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
313 dlgInfo->dlgProc = dlgProc;
314 dlgInfo->hUserFont = hFont;
315 dlgInfo->hMenu = hMenu;
316 dlgInfo->xBaseUnit = xUnit;
317 dlgInfo->yBaseUnit = yUnit;
318 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd,
319 GetWindow(wndPtr->hwndChild, GW_HWNDLAST), FALSE );
321 /* Send initialisation messages and set focus */
323 if (dlgInfo->hUserFont)
324 SendMessage( hwnd, WM_SETFONT, dlgInfo->hUserFont, 0 );
325 if (SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param ))
326 SetFocus( dlgInfo->hwndFocus );
328 return hwnd;
332 /***********************************************************************
333 * DIALOG_DoDialogBox
335 static int DIALOG_DoDialogBox( HWND hwnd )
337 WND * wndPtr;
338 DIALOGINFO * dlgInfo;
339 HANDLE msgHandle;
340 MSG* lpmsg;
341 int retval;
343 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
344 if (!(msgHandle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(MSG)))) return -1;
345 lpmsg = (MSG *) USER_HEAP_ADDR( msgHandle );
346 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
347 ShowWindow( hwnd, SW_SHOW );
349 while (MSG_InternalGetMessage( lpmsg, hwnd, MSGF_DIALOGBOX, TRUE ))
351 if (!IsDialogMessage( hwnd, lpmsg))
353 TranslateMessage( lpmsg );
354 DispatchMessage( lpmsg );
356 if (dlgInfo->fEnd) break;
358 retval = dlgInfo->msgResult;
359 DestroyWindow( hwnd );
360 USER_HEAP_FREE( msgHandle );
361 return retval;
365 /***********************************************************************
366 * DialogBox (USER.87)
368 int DialogBox( HINSTANCE hInst, LPCSTR dlgTemplate,
369 HWND owner, FARPROC dlgProc )
371 return DialogBoxParam( hInst, dlgTemplate, owner, dlgProc, 0 );
375 /***********************************************************************
376 * DialogBoxParam (USER.239)
378 int DialogBoxParam( HINSTANCE hInst, LPCSTR dlgTemplate,
379 HWND owner, FARPROC dlgProc, LPARAM param )
381 HWND hwnd;
383 #ifdef DEBUG_DIALOG
384 printf( "DialogBoxParam: %d,'%s',%d,%p,%d\n",
385 hInst, dlgTemplate, owner, dlgProc, param );
386 #endif
387 hwnd = CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, param );
388 if (hwnd) return DIALOG_DoDialogBox( hwnd );
389 return -1;
393 /***********************************************************************
394 * DialogBoxIndirect (USER.218)
396 int DialogBoxIndirect( HINSTANCE hInst, HANDLE dlgTemplate,
397 HWND owner, FARPROC dlgProc )
399 return DialogBoxIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
403 /***********************************************************************
404 * DialogBoxIndirectParam (USER.240)
406 int DialogBoxIndirectParam( HINSTANCE hInst, HANDLE dlgTemplate,
407 HWND owner, FARPROC dlgProc, LPARAM param )
409 HWND hwnd;
410 LPCSTR ptr;
412 if (!(ptr = GlobalLock( dlgTemplate ))) return -1;
413 hwnd = CreateDialogIndirectParam( hInst, ptr, owner, dlgProc, param );
414 GlobalUnlock( dlgTemplate );
415 if (hwnd) return DIALOG_DoDialogBox( hwnd );
416 return -1;
420 /***********************************************************************
421 * EndDialog (USER.88)
423 void EndDialog( HWND hwnd, short retval )
425 WND * wndPtr = WIN_FindWndPtr( hwnd );
426 DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
427 dlgInfo->msgResult = retval;
428 dlgInfo->fEnd = TRUE;
429 #ifdef DEBUG_DIALOG
430 printf( "EndDialog: %d %d\n", hwnd, retval );
431 #endif
435 /***********************************************************************
436 * IsDialogMessage (USER.90)
438 BOOL IsDialogMessage( HWND hwndDlg, LPMSG msg )
440 WND * wndPtr;
442 if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
443 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
445 if (msg->message != WM_KEYDOWN)
447 SendMessage( msg->hwnd, msg->message, msg->wParam, msg->lParam );
449 else
451 int dlgCode = SendMessage( msg->hwnd, WM_GETDLGCODE, 0, 0 );
452 /* Process key message */
453 /* .... */
455 return TRUE;
459 /****************************************************************
460 * GetDlgCtrlID (USER.277)
462 int GetDlgCtrlID( HWND hwnd )
464 WND *wndPtr = WIN_FindWndPtr(hwnd);
465 if (wndPtr) return wndPtr->wIDmenu;
466 else return 0;
470 /***********************************************************************
471 * GetDlgItem (USER.91)
473 HWND GetDlgItem( HWND hwndDlg, WORD id )
475 HWND curChild;
476 WND * childPtr;
477 WND * wndPtr;
479 if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
480 curChild = wndPtr->hwndChild;
481 while(curChild)
483 childPtr = WIN_FindWndPtr( curChild );
484 if (childPtr->wIDmenu == id) return curChild;
485 curChild = childPtr->hwndNext;
487 return 0;
491 /*******************************************************************
492 * SendDlgItemMessage (USER.101)
494 LONG SendDlgItemMessage(HWND hwnd, WORD id, UINT msg, WORD wParam, LONG lParam)
496 HWND hwndCtrl = GetDlgItem( hwnd, id );
497 if (hwndCtrl) return SendMessage( hwndCtrl, msg, wParam, lParam );
498 else return 0;
502 /*******************************************************************
503 * SetDlgItemText (USER.92)
505 void SetDlgItemText( HWND hwnd, WORD id, LPSTR lpString )
507 SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)lpString );
511 /***********************************************************************
512 * GetDlgItemText (USER.93)
514 int GetDlgItemText( HWND hwnd, WORD id, LPSTR str, WORD max )
516 return (int)SendDlgItemMessage( hwnd, id, WM_GETTEXT, max, (DWORD)str );
520 /*******************************************************************
521 * SetDlgItemInt (USER.94)
523 void SetDlgItemInt( HWND hwnd, WORD id, WORD value, BOOL fSigned )
525 HANDLE hText = USER_HEAP_ALLOC(0, 10 );
526 char * str = (char *) USER_HEAP_ADDR( hText );
528 if (fSigned) sprintf( str, "%d", value );
529 else sprintf( str, "%u", value );
530 SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)str );
531 USER_HEAP_FREE( hText );
535 /***********************************************************************
536 * GetDlgItemInt (USER.95)
538 WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
540 int len;
541 HANDLE hText;
542 long result;
543 char * str;
545 if (translated) *translated = FALSE;
546 if (!(len = SendDlgItemMessage( hwnd, id, WM_GETTEXTLENGTH, 0, 0 )))
547 return 0;
548 if (!(hText = USER_HEAP_ALLOC(0, len+1 )))
549 return 0;
550 str = (char *) USER_HEAP_ADDR( hText );
551 if (SendDlgItemMessage( hwnd, id, WM_GETTEXT, len+1, (DWORD)str ))
553 char * endptr;
554 result = strtol( str, &endptr, 10 );
555 if (endptr && (endptr != str)) /* Conversion was successful */
557 if (fSigned)
559 if ((result < -32767) || (result > 32767)) result = 0;
560 else if (translated) *translated = TRUE;
562 else
564 if ((result < 0) || (result > 65535)) result = 0;
565 else if (translated) *translated = TRUE;
569 USER_HEAP_FREE( hText );
570 return (WORD)result;
574 /***********************************************************************
575 * CheckDlgButton (USER.97)
577 void CheckDlgButton( HWND hwnd, WORD id, WORD check )
579 SendDlgItemMessage( hwnd, id, BM_SETCHECK, check, 0 );
583 /***********************************************************************
584 * IsDlgButtonChecked (USER.98)
586 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
588 return (WORD)SendDlgItemMessage( hwnd, id, BM_GETCHECK, 0, 0 );
592 /***********************************************************************
593 * CheckRadioButton (USER.96)
595 void CheckRadioButton( HWND hwndDlg, WORD firstID, WORD lastID, WORD checkID )
597 HWND button = GetDlgItem( hwndDlg, firstID );
598 while (button != 0)
600 WND * wndPtr = WIN_FindWndPtr( button );
601 if (!wndPtr) break;
602 SendMessage( button, BM_SETCHECK, (wndPtr->wIDmenu == checkID), 0 );
603 if (wndPtr->wIDmenu == lastID) break;
604 button = wndPtr->hwndNext;
609 /***********************************************************************
610 * GetDialogBaseUnits (USER.243)
612 DWORD GetDialogBaseUnits()
614 return MAKELONG( xBaseUnit, yBaseUnit );
618 /***********************************************************************
619 * MapDialogRect (USER.103)
621 void MapDialogRect( HWND hwnd, LPRECT rect )
623 DIALOGINFO * dlgInfo;
624 WND * wndPtr = WIN_FindWndPtr( hwnd );
625 if (!wndPtr) return;
626 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
627 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
628 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
629 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
630 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
634 /***********************************************************************
635 * GetNextDlgGroupItem (USER.227)
637 HWND GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
639 HWND hwnd, hwndLast;
640 WND * dlgPtr, * ctrlPtr, * wndPtr;
642 if (!(dlgPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
643 if (!(ctrlPtr = WIN_FindWndPtr( hwndCtrl ))) return 0;
644 if (ctrlPtr->hwndParent != hwndDlg) return 0;
646 hwndLast = hwndCtrl;
647 hwnd = ctrlPtr->hwndNext;
648 while (1)
650 if (!hwnd) hwnd = dlgPtr->hwndChild;
651 if (hwnd == hwndCtrl) break;
652 wndPtr = WIN_FindWndPtr( hwnd );
653 if (wndPtr->dwStyle & WS_TABSTOP)
655 hwndLast = hwnd;
656 if (!fPrevious) break;
658 hwnd = wndPtr->hwndNext;
660 return hwndLast;
661 return 0;
665 /***********************************************************************
666 * GetNextDlgTabItem (USER.228)
668 HWND GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
670 HWND hwnd, hwndLast;
671 WND * dlgPtr, * ctrlPtr, * wndPtr;
673 if (!(dlgPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
674 if (!(ctrlPtr = WIN_FindWndPtr( hwndCtrl ))) return 0;
675 if (ctrlPtr->hwndParent != hwndDlg) return 0;
677 hwndLast = hwndCtrl;
678 hwnd = ctrlPtr->hwndNext;
679 while (1)
681 if (!hwnd) hwnd = dlgPtr->hwndChild;
682 if (hwnd == hwndCtrl) break;
683 wndPtr = WIN_FindWndPtr( hwnd );
684 if (wndPtr->dwStyle & WS_TABSTOP)
686 hwndLast = hwnd;
687 if (!fPrevious) break;
689 hwnd = wndPtr->hwndNext;
691 return hwndLast;