Release 960717
[wine/multimedia.git] / windows / dialog.c
blobbdd46a30c060b3272b6cf897be360662a1957106
1 /*
2 * Dialog functions
4 * Copyright 1993, 1994, 1996 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "dialog.h"
12 #include "heap.h"
13 #include "win.h"
14 #include "ldt.h"
15 #include "stackframe.h"
16 #include "string32.h"
17 #include "user.h"
18 #include "winproc.h"
19 #include "message.h"
20 #include "stddebug.h"
21 #include "debug.h"
24 /* Dialog control information */
25 typedef struct
27 DWORD style;
28 DWORD exStyle;
29 INT16 x;
30 INT16 y;
31 INT16 cx;
32 INT16 cy;
33 UINT16 id;
34 LPCSTR className;
35 LPCSTR windowName;
36 LPVOID data;
37 } DLG_CONTROL_INFO;
39 /* Dialog template */
40 typedef struct
42 DWORD style;
43 DWORD exStyle;
44 UINT16 nbItems;
45 INT16 x;
46 INT16 y;
47 INT16 cx;
48 INT16 cy;
49 LPCSTR menuName;
50 LPCSTR className;
51 LPCSTR caption;
52 WORD pointSize;
53 LPCSTR faceName;
54 } DLG_TEMPLATE;
56 /* Dialog base units */
57 static WORD xBaseUnit = 0, yBaseUnit = 0;
60 /***********************************************************************
61 * DIALOG_Init
63 * Initialisation of the dialog manager.
65 BOOL DIALOG_Init()
67 TEXTMETRIC16 tm;
68 HDC hdc;
70 /* Calculate the dialog base units */
72 if (!(hdc = CreateDC( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
73 GetTextMetrics16( hdc, &tm );
74 DeleteDC( hdc );
75 xBaseUnit = tm.tmAveCharWidth;
76 yBaseUnit = tm.tmHeight;
78 /* Dialog units are based on a proportional system font */
79 /* so we adjust them a bit for a fixed font. */
80 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) xBaseUnit = xBaseUnit * 5 / 4;
82 dprintf_dialog( stddeb, "DIALOG_Init: base units = %d,%d\n",
83 xBaseUnit, yBaseUnit );
84 return TRUE;
88 /***********************************************************************
89 * DIALOG_GetFirstTabItem
91 * Return the first item of the dialog that has the WS_TABSTOP style.
93 HWND DIALOG_GetFirstTabItem( HWND hwndDlg )
95 WND *pWnd = WIN_FindWndPtr( hwndDlg );
96 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
97 if (pWnd->dwStyle & WS_TABSTOP) return pWnd->hwndSelf;
98 return 0;
102 /***********************************************************************
103 * DIALOG_GetControl16
105 * Return the class and text of the control pointed to by ptr,
106 * fill the header structure and return a pointer to the next control.
108 static LPCSTR DIALOG_GetControl16( LPCSTR p, DLG_CONTROL_INFO *info )
110 static char buffer[10];
112 info->x = GET_WORD(p); p += sizeof(WORD);
113 info->y = GET_WORD(p); p += sizeof(WORD);
114 info->cx = GET_WORD(p); p += sizeof(WORD);
115 info->cy = GET_WORD(p); p += sizeof(WORD);
116 info->id = GET_WORD(p); p += sizeof(WORD);
117 info->style = GET_DWORD(p); p += sizeof(DWORD);
118 info->exStyle = 0;
120 if (*p & 0x80)
122 switch((BYTE)*p)
124 case 0x80: strcpy( buffer, "BUTTON" ); break;
125 case 0x81: strcpy( buffer, "EDIT" ); break;
126 case 0x82: strcpy( buffer, "STATIC" ); break;
127 case 0x83: strcpy( buffer, "LISTBOX" ); break;
128 case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
129 case 0x85: strcpy( buffer, "COMBOBOX" ); break;
130 default: buffer[0] = '\0'; break;
132 info->className = buffer;
133 p++;
135 else
137 info->className = p;
138 p += strlen(p) + 1;
140 dprintf_dialog(stddeb, " %s ", info->className );
142 if ((BYTE)*p == 0xff)
144 /* Integer id, not documented (?). Only works for SS_ICON controls */
145 info->windowName = (LPCSTR)(UINT32)GET_WORD(p+1);
146 p += 3;
147 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
149 else
151 info->windowName = p;
152 p += strlen(p) + 1;
153 dprintf_dialog(stddeb,"'%s'", info->windowName );
156 info->data = (LPVOID)(*p ? p + 1 : NULL); /* FIXME: should be a segptr */
157 p += *p + 1;
159 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx\n",
160 info->id, info->x, info->y, info->cx, info->cy,
161 info->style, (DWORD)info->data);
162 return p;
166 /***********************************************************************
167 * DIALOG_GetControl32
169 * Return the class and text of the control pointed to by ptr,
170 * fill the header structure and return a pointer to the next control.
172 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info )
174 static WCHAR buffer[10];
176 info->style = GET_DWORD(p); p += 2;
177 info->exStyle = GET_DWORD(p); p += 2;
178 info->x = GET_WORD(p); p++;
179 info->y = GET_WORD(p); p++;
180 info->cx = GET_WORD(p); p++;
181 info->cy = GET_WORD(p); p++;
182 info->id = GET_WORD(p); p++;
184 if (GET_WORD(p) == 0xffff)
186 switch(GET_WORD(p+1))
188 case 0x80: STRING32_AnsiToUni( buffer, "BUTTON" ); break;
189 case 0x81: STRING32_AnsiToUni( buffer, "EDIT" ); break;
190 case 0x82: STRING32_AnsiToUni( buffer, "STATIC" ); break;
191 case 0x83: STRING32_AnsiToUni( buffer, "LISTBOX" ); break;
192 case 0x84: STRING32_AnsiToUni( buffer, "SCROLLBAR" ); break;
193 case 0x85: STRING32_AnsiToUni( buffer, "COMBOBOX" ); break;
194 default: buffer[0] = '\0'; break;
196 info->className = (LPCSTR)buffer;
197 p += 2;
199 else
201 info->className = (LPCSTR)p;
202 p += lstrlen32W( (LPCWSTR)p ) + 1;
204 dprintf_dialog(stddeb, " %p ", info->className );
206 if (GET_WORD(p) == 0xffff)
208 info->windowName = (LPCSTR)(p + 1);
209 p += 2;
210 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
212 else
214 info->windowName = (LPCSTR)p;
215 p += lstrlen32W( (LPCWSTR)p ) + 1;
216 dprintf_dialog(stddeb,"'%p'", info->windowName );
219 if (GET_WORD(p))
221 info->data = (LPVOID)(p + 1);
222 p += GET_WORD(p) / sizeof(WORD);
224 else info->data = NULL;
225 p++;
227 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n",
228 info->id, info->x, info->y, info->cx, info->cy,
229 info->style, info->exStyle, (DWORD)info->data);
230 /* Next control is on dword boundary */
231 return (const WORD *)((((int)p) + 3) & ~3);
235 /***********************************************************************
236 * DIALOG_CreateControls
238 * Create the control windows for a dialog.
240 static BOOL32 DIALOG_CreateControls( WND *pWnd, LPCSTR template, INT32 items,
241 HINSTANCE32 hInst, BOOL win32 )
243 DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
244 DLG_CONTROL_INFO info;
245 HWND32 hwndCtrl, hwndDefButton = 0;
247 dprintf_dialog(stddeb, " BEGIN\n" );
248 while (items--)
250 if (!win32)
252 HINSTANCE16 instance;
253 template = DIALOG_GetControl16( template, &info );
254 if (HIWORD(info.className) && !strcmp( info.className, "EDIT") &&
255 ((info.style & DS_LOCALEDIT) != DS_LOCALEDIT))
257 if (!dlgInfo->hDialogHeap)
259 dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
260 if (!dlgInfo->hDialogHeap)
262 fprintf( stderr, "CreateDialogIndirectParam: Insufficient memory to create heap for edit control\n" );
263 continue;
265 LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
267 instance = dlgInfo->hDialogHeap;
269 else instance = (HINSTANCE16)hInst;
271 hwndCtrl = CreateWindowEx16( info.exStyle | WS_EX_NOPARENTNOTIFY,
272 info.className, info.windowName,
273 info.style | WS_CHILD,
274 info.x * dlgInfo->xBaseUnit / 4,
275 info.y * dlgInfo->yBaseUnit / 8,
276 info.cx * dlgInfo->xBaseUnit / 4,
277 info.cy * dlgInfo->yBaseUnit / 8,
278 pWnd->hwndSelf, (HMENU)info.id,
279 instance, info.data );
281 else
283 template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info );
284 hwndCtrl = CreateWindowEx32W( info.exStyle | WS_EX_NOPARENTNOTIFY,
285 (LPCWSTR)info.className,
286 (LPCWSTR)info.windowName,
287 info.style | WS_CHILD,
288 info.x * dlgInfo->xBaseUnit / 4,
289 info.y * dlgInfo->yBaseUnit / 8,
290 info.cx * dlgInfo->xBaseUnit / 4,
291 info.cy * dlgInfo->yBaseUnit / 8,
292 pWnd->hwndSelf, (HMENU)info.id,
293 hInst, info.data );
295 if (!hwndCtrl) return FALSE;
297 /* Send initialisation messages to the control */
298 if (dlgInfo->hUserFont) SendMessage32A( hwndCtrl, WM_SETFONT,
299 (WPARAM)dlgInfo->hUserFont, 0 );
300 if (SendMessage32A(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
302 /* If there's already a default push-button, set it back */
303 /* to normal and use this one instead. */
304 if (hwndDefButton)
305 SendMessage32A( hwndDefButton, BM_SETSTYLE32,
306 BS_PUSHBUTTON,FALSE );
307 hwndDefButton = hwndCtrl;
308 dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID );
311 dprintf_dialog(stddeb, " END\n" );
312 return TRUE;
316 /***********************************************************************
317 * DIALOG_ParseTemplate16
319 * Fill a DLG_TEMPLATE structure from the dialog template, and return
320 * a pointer to the first control.
322 static LPCSTR DIALOG_ParseTemplate16( LPCSTR p, DLG_TEMPLATE * result )
324 result->style = GET_DWORD(p); p += sizeof(DWORD);
325 result->exStyle = 0;
326 result->nbItems = *p++;
327 result->x = GET_WORD(p); p += sizeof(WORD);
328 result->y = GET_WORD(p); p += sizeof(WORD);
329 result->cx = GET_WORD(p); p += sizeof(WORD);
330 result->cy = GET_WORD(p); p += sizeof(WORD);
331 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
332 result->x, result->y, result->cx, result->cy );
333 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
335 /* Get the menu name */
337 switch( (BYTE)*p )
339 case 0:
340 result->menuName = 0;
341 p++;
342 break;
343 case 0xff:
344 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
345 p += 3;
346 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
347 break;
348 default:
349 result->menuName = p;
350 dprintf_dialog( stddeb, " MENU '%s'\n", p );
351 p += strlen(p) + 1;
352 break;
355 /* Get the class name */
357 if (*p)
359 result->className = p;
360 dprintf_dialog( stddeb, " CLASS '%s'\n", result->className );
362 else result->className = DIALOG_CLASS_ATOM;
363 p += strlen(p) + 1;
365 /* Get the window caption */
367 result->caption = p;
368 p += strlen(p) + 1;
369 dprintf_dialog( stddeb, " CAPTION '%s'\n", result->caption );
371 /* Get the font name */
373 if (result->style & DS_SETFONT)
375 result->pointSize = GET_WORD(p);
376 p += sizeof(WORD);
377 result->faceName = p;
378 p += strlen(p) + 1;
379 dprintf_dialog( stddeb, " FONT %d,'%s'\n",
380 result->pointSize, result->faceName );
382 return p;
386 /***********************************************************************
387 * DIALOG_ParseTemplate32
389 * Fill a DLG_TEMPLATE structure from the dialog template, and return
390 * a pointer to the first control.
392 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
394 const WORD *p = (const WORD *)template;
396 result->style = GET_DWORD(p); p += 2;
397 result->exStyle = GET_DWORD(p); p += 2;
398 result->nbItems = GET_WORD(p); p++;
399 result->x = GET_WORD(p); p++;
400 result->y = GET_WORD(p); p++;
401 result->cx = GET_WORD(p); p++;
402 result->cy = GET_WORD(p); p++;
403 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
404 result->x, result->y, result->cx, result->cy );
405 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
406 dprintf_dialog( stddeb, " EXSTYLE %08lx\n", result->exStyle );
408 /* Get the menu name */
410 switch(GET_WORD(p))
412 case 0x0000:
413 result->menuName = NULL;
414 p++;
415 break;
416 case 0xffff:
417 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
418 p += 2;
419 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
420 break;
421 default:
422 result->menuName = (LPCSTR)p;
423 dprintf_dialog( stddeb, " MENU '%p'\n", p );
424 p += lstrlen32W( (LPCWSTR)p ) + 1;
425 break;
428 /* Get the class name */
430 switch(GET_WORD(p))
432 case 0x0000:
433 result->className = DIALOG_CLASS_ATOM;
434 p++;
435 break;
436 case 0xffff:
437 result->className = (LPCSTR)(UINT32)GET_WORD( p + 1 );
438 p += 2;
439 dprintf_dialog(stddeb, " CLASS %04x\n", LOWORD(result->className) );
440 break;
441 default:
442 result->className = (LPCSTR)p;
443 dprintf_dialog( stddeb, " CLASS '%p'\n", p );
444 p += lstrlen32W( (LPCWSTR)p ) + 1;
445 break;
448 /* Get the window caption */
450 result->caption = (LPCSTR)p;
451 p += lstrlen32W( (LPCWSTR)p ) + 1;
452 dprintf_dialog( stddeb, " CAPTION '%p'\n", result->caption );
454 /* Get the font name */
456 if (result->style & DS_SETFONT)
458 result->pointSize = GET_WORD(p);
459 p++;
460 result->faceName = (LPCSTR)p;
461 p += lstrlen32W( (LPCWSTR)p ) + 1;
462 dprintf_dialog( stddeb, " FONT %d,'%p'\n",
463 result->pointSize, result->faceName );
465 /* First control is on dword boundary */
466 return (LPCSTR)((((int)p) + 3) & ~3);
470 /***********************************************************************
471 * DIALOG_CreateIndirect
473 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
474 HWND owner, DLGPROC16 dlgProc,
475 LPARAM param, WINDOWPROCTYPE procType )
477 HMENU hMenu = 0;
478 HFONT hFont = 0;
479 HWND hwnd;
480 RECT16 rect;
481 WND * wndPtr;
482 DLG_TEMPLATE template;
483 DIALOGINFO * dlgInfo;
484 WORD xUnit = xBaseUnit;
485 WORD yUnit = yBaseUnit;
487 /* Parse dialog template */
489 if (!dlgTemplate) return 0;
490 if (procType != WIN_PROC_16)
491 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
492 else
493 dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
495 /* Load menu */
497 if (template.menuName)
499 LPSTR str = SEGPTR_STRDUP( template.menuName ); /* FIXME: win32 */
500 hMenu = LoadMenu16( hInst, SEGPTR_GET(str) );
501 SEGPTR_FREE( str );
504 /* Create custom font if needed */
506 if (template.style & DS_SETFONT)
508 /* The font height must be negative as it is a point size */
509 /* (see CreateFont() documentation in the Windows SDK). */
510 hFont = CreateFont16( -template.pointSize, 0, 0, 0, FW_DONTCARE,
511 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
512 DEFAULT_QUALITY, FF_DONTCARE,
513 template.faceName ); /* FIXME: win32 */
514 if (hFont)
516 TEXTMETRIC16 tm;
517 HFONT oldFont;
518 HDC hdc;
520 hdc = GetDC(0);
521 oldFont = SelectObject( hdc, hFont );
522 GetTextMetrics16( hdc, &tm );
523 SelectObject( hdc, oldFont );
524 ReleaseDC( 0, hdc );
525 xUnit = tm.tmAveCharWidth;
526 yUnit = tm.tmHeight;
527 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
528 xBaseUnit = xBaseUnit * 5 / 4; /* See DIALOG_Init() */
532 /* Create dialog main window */
534 rect.left = rect.top = 0;
535 rect.right = template.cx * xUnit / 4;
536 rect.bottom = template.cy * yUnit / 8;
537 if (template.style & DS_MODALFRAME)
538 template.exStyle |= WS_EX_DLGMODALFRAME;
539 AdjustWindowRectEx16( &rect, template.style,
540 hMenu ? TRUE : FALSE , template.exStyle );
541 rect.right -= rect.left;
542 rect.bottom -= rect.top;
544 if ((INT16)template.x == CW_USEDEFAULT16)
546 rect.left = rect.top = (procType == WIN_PROC_16) ? CW_USEDEFAULT16
547 : CW_USEDEFAULT32;
549 else
551 rect.left += template.x * xUnit / 4;
552 rect.top += template.y * yUnit / 8;
553 if (!(template.style & DS_ABSALIGN))
554 ClientToScreen16( owner, (POINT16 *)&rect );
557 if (procType != WIN_PROC_16)
558 hwnd = CreateWindowEx32W(template.exStyle, (LPCWSTR)template.className,
559 (LPCWSTR)template.caption,
560 template.style & ~WS_VISIBLE,
561 rect.left, rect.top, rect.right, rect.bottom,
562 owner, hMenu, hInst, NULL );
563 else
564 hwnd = CreateWindowEx16(template.exStyle, template.className,
565 template.caption, template.style & ~WS_VISIBLE,
566 rect.left, rect.top, rect.right, rect.bottom,
567 owner, hMenu, hInst, NULL );
568 if (!hwnd)
570 if (hFont) DeleteObject( hFont );
571 if (hMenu) DestroyMenu( hMenu );
572 return 0;
574 wndPtr = WIN_FindWndPtr( hwnd );
575 wndPtr->flags |= WIN_ISDIALOG;
577 /* Initialise dialog extra data */
579 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
580 dlgInfo->hUserFont = hFont;
581 dlgInfo->hMenu = hMenu;
582 dlgInfo->xBaseUnit = xUnit;
583 dlgInfo->yBaseUnit = yUnit;
584 dlgInfo->msgResult = 0; /* This is used to store the default button id */
585 dlgInfo->hDialogHeap = 0;
587 /* Create controls */
589 if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
590 hInst, (procType != WIN_PROC_16) ))
592 DestroyWindow( hwnd );
593 return 0;
596 /* Send initialisation messages and set focus */
598 WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType );
599 dlgInfo->hwndFocus = DIALOG_GetFirstTabItem( hwnd );
600 if (dlgInfo->hUserFont)
601 SendMessage32A( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
602 if (SendMessage32A(hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param))
603 SetFocus( dlgInfo->hwndFocus );
604 if (template.style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
605 return hwnd;
609 /***********************************************************************
610 * CreateDialog16 (USER.89)
612 HWND16 CreateDialog16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
613 HWND16 owner, DLGPROC16 dlgProc )
615 return CreateDialogParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
619 /***********************************************************************
620 * CreateDialogParam16 (USER.241)
622 HWND16 CreateDialogParam16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
623 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
625 HWND16 hwnd = 0;
626 HRSRC hRsrc;
627 HGLOBAL16 hmem;
628 LPCVOID data;
630 dprintf_dialog(stddeb, "CreateDialogParam16: %04x,%08lx,%04x,%08lx,%ld\n",
631 hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
633 if (!(hRsrc = FindResource16( hInst, dlgTemplate, RT_DIALOG ))) return 0;
634 if (!(hmem = LoadResource16( hInst, hRsrc ))) return 0;
635 if (!(data = LockResource16( hmem ))) hwnd = 0;
636 else hwnd = CreateDialogIndirectParam16( hInst, data, owner,
637 dlgProc, param );
638 FreeResource16( hmem );
639 return hwnd;
643 /***********************************************************************
644 * CreateDialogParam32A (USER32.72)
646 HWND32 CreateDialogParam32A( HINSTANCE32 hInst, LPCSTR name,
647 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
649 if (HIWORD(name))
651 LPWSTR str = STRING32_DupAnsiToUni( name );
652 HWND32 hwnd = CreateDialogParam32W( hInst, str, owner, dlgProc, param);
653 free( str );
654 return hwnd;
656 return CreateDialogParam32W( hInst, (LPCWSTR)name, owner, dlgProc, param );
660 /***********************************************************************
661 * CreateDialogParam32W (USER32.73)
663 HWND32 CreateDialogParam32W( HINSTANCE32 hInst, LPCWSTR name,
664 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
666 HANDLE32 hrsrc = FindResource32W( hInst, name, (LPWSTR)RT_DIALOG );
667 if (!hrsrc) return 0;
668 return CreateDialogIndirectParam32W( hInst,
669 (LPVOID)LoadResource32(hInst, hrsrc),
670 owner, dlgProc, param );
674 /***********************************************************************
675 * CreateDialogIndirect16 (USER.219)
677 HWND16 CreateDialogIndirect16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
678 HWND16 owner, DLGPROC16 dlgProc )
680 return CreateDialogIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0);
684 /***********************************************************************
685 * CreateDialogIndirectParam16 (USER.242)
687 HWND16 CreateDialogIndirectParam16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
688 HWND16 owner, DLGPROC16 dlgProc,
689 LPARAM param )
691 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
692 dlgProc, param, WIN_PROC_16 );
696 /***********************************************************************
697 * CreateDialogIndirectParam32A (USER32.69)
699 HWND32 CreateDialogIndirectParam32A( HINSTANCE32 hInst, LPCVOID dlgTemplate,
700 HWND32 owner, DLGPROC32 dlgProc,
701 LPARAM param )
703 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
704 (DLGPROC16)dlgProc, param, WIN_PROC_32A );
708 /***********************************************************************
709 * CreateDialogIndirectParam32W (USER32.71)
711 HWND32 CreateDialogIndirectParam32W( HINSTANCE32 hInst, LPCVOID dlgTemplate,
712 HWND32 owner, DLGPROC32 dlgProc,
713 LPARAM param )
715 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
716 (DLGPROC16)dlgProc, param, WIN_PROC_32W );
720 /***********************************************************************
721 * DIALOG_DoDialogBox
723 static INT32 DIALOG_DoDialogBox( HWND hwnd, HWND owner )
725 WND * wndPtr;
726 DIALOGINFO * dlgInfo;
727 HANDLE msgHandle;
728 MSG16* lpmsg;
729 INT32 retval;
731 /* Owner must be a top-level window */
732 owner = WIN_GetTopParent( owner );
733 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
734 if (!(msgHandle = USER_HEAP_ALLOC( sizeof(MSG16) ))) return -1;
735 lpmsg = (MSG16 *) USER_HEAP_LIN_ADDR( msgHandle );
736 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
737 EnableWindow( owner, FALSE );
738 ShowWindow( hwnd, SW_SHOW );
740 while (MSG_InternalGetMessage( (SEGPTR)USER_HEAP_SEG_ADDR(msgHandle), hwnd, owner,
741 MSGF_DIALOGBOX, PM_REMOVE,
742 !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
744 if (!IsDialogMessage( hwnd, lpmsg))
746 TranslateMessage( lpmsg );
747 DispatchMessage( lpmsg );
749 if (dlgInfo->fEnd) break;
751 retval = dlgInfo->msgResult;
752 DestroyWindow( hwnd );
753 USER_HEAP_FREE( msgHandle );
754 EnableWindow( owner, TRUE );
755 return retval;
759 /***********************************************************************
760 * DialogBox16 (USER.87)
762 INT16 DialogBox16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
763 HWND16 owner, DLGPROC16 dlgProc )
765 return DialogBoxParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
769 /***********************************************************************
770 * DialogBoxParam16 (USER.239)
772 INT16 DialogBoxParam16( HINSTANCE16 hInst, SEGPTR template,
773 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
775 HWND16 hwnd = CreateDialogParam16( hInst, template, owner, dlgProc, param);
776 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
777 return -1;
781 /***********************************************************************
782 * DialogBoxParam32A (USER32.138)
784 INT32 DialogBoxParam32A( HINSTANCE32 hInst, LPCSTR name,
785 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
787 HWND32 hwnd = CreateDialogParam32A( hInst, name, owner, dlgProc, param );
788 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
789 return -1;
793 /***********************************************************************
794 * DialogBoxParam32W (USER32.139)
796 INT32 DialogBoxParam32W( HINSTANCE32 hInst, LPCWSTR name,
797 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
799 HWND32 hwnd = CreateDialogParam32W( hInst, name, owner, dlgProc, param );
800 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
801 return -1;
805 /***********************************************************************
806 * DialogBoxIndirect16 (USER.218)
808 INT16 DialogBoxIndirect16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
809 HWND16 owner, DLGPROC16 dlgProc )
811 return DialogBoxIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
815 /***********************************************************************
816 * DialogBoxIndirectParam16 (USER.240)
818 INT16 DialogBoxIndirectParam16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
819 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
821 HWND16 hwnd;
822 LPCVOID ptr;
824 if (!(ptr = GlobalLock16( dlgTemplate ))) return -1;
825 hwnd = CreateDialogIndirectParam16( hInst, ptr, owner, dlgProc, param );
826 GlobalUnlock16( dlgTemplate );
827 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
828 return -1;
832 /***********************************************************************
833 * DialogBoxIndirectParam32A (USER32.135)
835 INT32 DialogBoxIndirectParam32A( HINSTANCE32 hInstance, LPCVOID template,
836 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
838 HWND32 hwnd = CreateDialogIndirectParam32A( hInstance, template,
839 owner, dlgProc, param );
840 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
841 return -1;
845 /***********************************************************************
846 * DialogBoxIndirectParam32W (USER32.137)
848 INT32 DialogBoxIndirectParam32W( HINSTANCE32 hInstance, LPCVOID template,
849 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
851 HWND32 hwnd = CreateDialogIndirectParam32W( hInstance, template,
852 owner, dlgProc, param );
853 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
854 return -1;
858 /***********************************************************************
859 * EndDialog (USER.88) (USER32.173)
861 BOOL16 EndDialog( HWND32 hwnd, INT32 retval )
863 WND * wndPtr = WIN_FindWndPtr( hwnd );
864 DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
865 dlgInfo->msgResult = retval;
866 dlgInfo->fEnd = TRUE;
867 dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
868 return TRUE;
872 /***********************************************************************
873 * IsDialogMessage (USER.90)
875 BOOL IsDialogMessage( HWND hwndDlg, LPMSG16 msg )
877 WND * wndPtr;
878 int dlgCode;
880 if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
881 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
883 /* Only the key messages get special processing */
884 if ((msg->message != WM_KEYDOWN) &&
885 (msg->message != WM_SYSCHAR) &&
886 (msg->message != WM_CHAR))
887 return FALSE;
889 dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, 0 );
890 if (dlgCode & DLGC_WANTMESSAGE)
892 DispatchMessage( msg );
893 return TRUE;
896 switch(msg->message)
898 case WM_KEYDOWN:
899 if (dlgCode & DLGC_WANTALLKEYS) break;
900 switch(msg->wParam)
902 case VK_TAB:
903 if (!(dlgCode & DLGC_WANTTAB))
905 SendMessage16( hwndDlg, WM_NEXTDLGCTL,
906 (GetKeyState(VK_SHIFT) & 0x80), 0 );
907 return TRUE;
909 break;
911 case VK_RIGHT:
912 case VK_DOWN:
913 if (!(dlgCode & DLGC_WANTARROWS))
915 SetFocus(GetNextDlgGroupItem(hwndDlg,GetFocus(),FALSE));
916 return TRUE;
918 break;
920 case VK_LEFT:
921 case VK_UP:
922 if (!(dlgCode & DLGC_WANTARROWS))
924 SetFocus(GetNextDlgGroupItem(hwndDlg,GetFocus(),TRUE));
925 return TRUE;
927 break;
929 case VK_ESCAPE:
930 SendMessage32A( hwndDlg, WM_COMMAND, IDCANCEL,
931 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
932 break;
934 case VK_RETURN:
936 DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
937 if (HIWORD(dw) == DC_HASDEFID)
938 SendMessage32A( hwndDlg, WM_COMMAND,
939 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
940 (LPARAM)GetDlgItem( hwndDlg, LOWORD(dw) ));
941 else
942 SendMessage32A( hwndDlg, WM_COMMAND, IDOK,
943 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
945 break;
947 default:
948 TranslateMessage( msg );
950 break; /* case WM_KEYDOWN */
953 case WM_CHAR:
954 if (dlgCode & (DLGC_WANTALLKEYS | DLGC_WANTCHARS)) break;
955 break;
957 case WM_SYSCHAR:
958 if (dlgCode & DLGC_WANTALLKEYS) break;
959 break;
962 /* If we get here, the message has not been treated specially */
963 /* and can be sent to its destination window. */
964 DispatchMessage( msg );
965 return TRUE;
969 /****************************************************************
970 * GetDlgCtrlID (USER.277) (USER32.233)
972 INT16 GetDlgCtrlID( HWND32 hwnd )
974 WND *wndPtr = WIN_FindWndPtr(hwnd);
975 if (wndPtr) return wndPtr->wIDmenu;
976 else return 0;
980 /***********************************************************************
981 * GetDlgItem (USER.91)
983 HWND GetDlgItem( HWND hwndDlg, WORD id )
985 WND *pWnd;
987 if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
988 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
989 if (pWnd->wIDmenu == id) return pWnd->hwndSelf;
990 return 0;
994 /*******************************************************************
995 * SendDlgItemMessage16 (USER.101)
997 LRESULT SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
998 WPARAM16 wParam, LPARAM lParam )
1000 HWND16 hwndCtrl = GetDlgItem( hwnd, id );
1001 if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
1002 else return 0;
1006 /*******************************************************************
1007 * SendDlgItemMessage32A (USER32.451)
1009 LRESULT SendDlgItemMessage32A( HWND32 hwnd, INT32 id, UINT32 msg,
1010 WPARAM32 wParam, LPARAM lParam )
1012 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
1013 if (hwndCtrl) return SendMessage32A( hwndCtrl, msg, wParam, lParam );
1014 else return 0;
1018 /*******************************************************************
1019 * SendDlgItemMessage32W (USER32.452)
1021 LRESULT SendDlgItemMessage32W( HWND32 hwnd, INT32 id, UINT32 msg,
1022 WPARAM32 wParam, LPARAM lParam )
1024 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
1025 if (hwndCtrl) return SendMessage32W( hwndCtrl, msg, wParam, lParam );
1026 else return 0;
1030 /*******************************************************************
1031 * SetDlgItemText16 (USER.92)
1033 void SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
1035 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1039 /*******************************************************************
1040 * SetDlgItemText32A (USER32.477)
1042 void SetDlgItemText32A( HWND32 hwnd, INT32 id, LPCSTR lpString )
1044 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1048 /*******************************************************************
1049 * SetDlgItemText32W (USER32.478)
1051 void SetDlgItemText32W( HWND32 hwnd, INT32 id, LPCWSTR lpString )
1053 SendDlgItemMessage32W( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1057 /***********************************************************************
1058 * GetDlgItemText16 (USER.93)
1060 INT16 GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
1062 return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
1063 len, (LPARAM)str );
1067 /***********************************************************************
1068 * GetDlgItemText32A (USER32.236)
1070 INT32 GetDlgItemText32A( HWND32 hwnd, INT32 id, LPSTR str, UINT32 len )
1072 return (INT32)SendDlgItemMessage32A( hwnd, id, WM_GETTEXT,
1073 len, (LPARAM)str );
1077 /***********************************************************************
1078 * GetDlgItemText32W (USER32.237)
1080 INT32 GetDlgItemText32W( HWND32 hwnd, INT32 id, LPWSTR str, UINT32 len )
1082 return (INT32)SendDlgItemMessage32W( hwnd, id, WM_GETTEXT,
1083 len, (LPARAM)str );
1087 /*******************************************************************
1088 * SetDlgItemInt16 (USER.94)
1090 void SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
1092 char *str = (char *)SEGPTR_ALLOC( 20 * sizeof(char) );
1094 if (!str) return;
1095 if (fSigned) sprintf( str, "%d", (INT32)(INT16)value );
1096 else sprintf( str, "%u", value );
1097 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)SEGPTR_GET(str) );
1098 SEGPTR_FREE(str);
1102 /*******************************************************************
1103 * SetDlgItemInt32 (USER32.476)
1105 void SetDlgItemInt32( HWND32 hwnd, INT32 id, UINT32 value, BOOL32 fSigned )
1107 char str[20];
1109 if (fSigned) sprintf( str, "%d", (INT32)value );
1110 else sprintf( str, "%u", value );
1111 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1115 /***********************************************************************
1116 * GetDlgItemInt (USER.95)
1118 WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
1120 char *str;
1121 long result = 0;
1123 if (translated) *translated = FALSE;
1124 if (!(str = (char *)SEGPTR_ALLOC( 30 * sizeof(char) ))) return 0;
1125 if (SendDlgItemMessage16( hwnd, id, WM_GETTEXT, 30, (LPARAM)SEGPTR_GET(str)))
1127 char * endptr;
1128 result = strtol( str, &endptr, 10 );
1129 if (endptr && (endptr != str)) /* Conversion was successful */
1131 if (fSigned)
1133 if ((result < -32767) || (result > 32767)) result = 0;
1134 else if (translated) *translated = TRUE;
1136 else
1138 if ((result < 0) || (result > 65535)) result = 0;
1139 else if (translated) *translated = TRUE;
1143 SEGPTR_FREE(str);
1144 return (WORD)result;
1148 /***********************************************************************
1149 * CheckDlgButton (USER.97) (USER32.44)
1151 BOOL16 CheckDlgButton( HWND32 hwnd, INT32 id, UINT32 check )
1153 SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
1154 return TRUE;
1158 /***********************************************************************
1159 * IsDlgButtonChecked (USER.98)
1161 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
1163 return (WORD)SendDlgItemMessage16( hwnd, id, BM_GETCHECK16, 0, 0 );
1167 /***********************************************************************
1168 * CheckRadioButton (USER.96) (USER32.47)
1170 BOOL16 CheckRadioButton( HWND32 hwndDlg, UINT32 firstID, UINT32 lastID,
1171 UINT32 checkID )
1173 WND *pWnd = WIN_FindWndPtr( hwndDlg );
1174 if (!pWnd) return FALSE;
1176 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1177 if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) break;
1178 if (!pWnd) return FALSE;
1180 if (pWnd->wIDmenu == lastID)
1181 lastID = firstID; /* Buttons are in reverse order */
1182 while (pWnd)
1184 SendMessage32A( pWnd->hwndSelf, BM_SETCHECK32,
1185 (pWnd->wIDmenu == checkID), 0 );
1186 if (pWnd->wIDmenu == lastID) break;
1187 pWnd = pWnd->next;
1189 return TRUE;
1193 /***********************************************************************
1194 * GetDialogBaseUnits (USER.243)
1196 DWORD GetDialogBaseUnits()
1198 return MAKELONG( xBaseUnit, yBaseUnit );
1202 /***********************************************************************
1203 * MapDialogRect16 (USER.103)
1205 void MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
1207 DIALOGINFO * dlgInfo;
1208 WND * wndPtr = WIN_FindWndPtr( hwnd );
1209 if (!wndPtr) return;
1210 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1211 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1212 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1213 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1214 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1218 /***********************************************************************
1219 * MapDialogRect32 (USER32.381)
1221 void MapDialogRect32( HWND32 hwnd, LPRECT32 rect )
1223 DIALOGINFO * dlgInfo;
1224 WND * wndPtr = WIN_FindWndPtr( hwnd );
1225 if (!wndPtr) return;
1226 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1227 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1228 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1229 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1230 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1234 /***********************************************************************
1235 * GetNextDlgGroupItem (USER.227)
1237 HWND GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1239 WND *pWnd, *pWndStart, *pWndCtrl, *pWndDlg;
1241 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1242 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1243 if (pWndCtrl->parent != pWndDlg) return 0;
1245 if (!fPrevious && pWndCtrl->next) /* Check if next control is in group */
1247 if (!(pWndCtrl->next->dwStyle & WS_GROUP))
1248 return pWndCtrl->next->hwndSelf;
1251 /* Now we will have to find the start of the group */
1253 for (pWnd = pWndStart = pWndDlg->child; pWnd; pWnd = pWnd->next)
1255 if (pWnd->dwStyle & WS_GROUP) pWndStart = pWnd; /* Start of a group */
1256 if (pWnd == pWndCtrl) break;
1259 if (!pWnd) fprintf(stderr, "GetNextDlgGroupItem: hwnd not in dialog!\n");
1261 /* only case left for forward search: wraparound */
1262 if (!fPrevious) return pWndStart->hwndSelf;
1264 pWnd = pWndStart->next;
1265 while (pWnd && (pWnd != pWndCtrl))
1267 if (pWnd->dwStyle & WS_GROUP) break;
1268 pWndStart = pWnd;
1269 pWnd = pWnd->next;
1271 return pWndStart->hwndSelf;
1275 /***********************************************************************
1276 * GetNextDlgTabItem (USER.228)
1278 HWND GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1280 WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1282 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1283 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1284 if (pWndCtrl->parent != pWndDlg) return 0;
1286 pWndLast = pWndCtrl;
1287 pWnd = pWndCtrl->next;
1288 while (1)
1290 if (!pWnd) pWnd = pWndDlg->child;
1291 if (pWnd == pWndCtrl) break;
1292 if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE))
1294 pWndLast = pWnd;
1295 if (!fPrevious) break;
1297 pWnd = pWnd->next;
1299 return pWndLast->hwndSelf;