Release 960928
[wine/multimedia.git] / windows / dialog.c
blobfe31129ad5405570de45807f35845956a754d5ff
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 "string32.h"
16 #include "user.h"
17 #include "winproc.h"
18 #include "message.h"
19 #include "stddebug.h"
20 #include "debug.h"
23 /* Dialog control information */
24 typedef struct
26 DWORD style;
27 DWORD exStyle;
28 INT16 x;
29 INT16 y;
30 INT16 cx;
31 INT16 cy;
32 UINT16 id;
33 LPCSTR className;
34 LPCSTR windowName;
35 LPVOID data;
36 } DLG_CONTROL_INFO;
38 /* Dialog template */
39 typedef struct
41 DWORD style;
42 DWORD exStyle;
43 UINT16 nbItems;
44 INT16 x;
45 INT16 y;
46 INT16 cx;
47 INT16 cy;
48 LPCSTR menuName;
49 LPCSTR className;
50 LPCSTR caption;
51 WORD pointSize;
52 LPCSTR faceName;
53 } DLG_TEMPLATE;
55 /* Dialog base units */
56 static WORD xBaseUnit = 0, yBaseUnit = 0;
59 /***********************************************************************
60 * DIALOG_Init
62 * Initialisation of the dialog manager.
64 BOOL DIALOG_Init()
66 TEXTMETRIC16 tm;
67 HDC hdc;
69 /* Calculate the dialog base units */
71 if (!(hdc = CreateDC( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
72 GetTextMetrics16( hdc, &tm );
73 DeleteDC( hdc );
74 xBaseUnit = tm.tmAveCharWidth;
75 yBaseUnit = tm.tmHeight;
77 /* Dialog units are based on a proportional system font */
78 /* so we adjust them a bit for a fixed font. */
79 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) xBaseUnit = xBaseUnit * 5 / 4;
81 dprintf_dialog( stddeb, "DIALOG_Init: base units = %d,%d\n",
82 xBaseUnit, yBaseUnit );
83 return TRUE;
87 /***********************************************************************
88 * DIALOG_GetFirstTabItem
90 * Return the first item of the dialog that has the WS_TABSTOP style.
92 HWND DIALOG_GetFirstTabItem( HWND hwndDlg )
94 WND *pWnd = WIN_FindWndPtr( hwndDlg );
95 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
96 if (pWnd->dwStyle & WS_TABSTOP) return pWnd->hwndSelf;
97 return 0;
101 /***********************************************************************
102 * DIALOG_GetControl16
104 * Return the class and text of the control pointed to by ptr,
105 * fill the header structure and return a pointer to the next control.
107 static LPCSTR DIALOG_GetControl16( LPCSTR p, DLG_CONTROL_INFO *info )
109 static char buffer[10];
111 info->x = GET_WORD(p); p += sizeof(WORD);
112 info->y = GET_WORD(p); p += sizeof(WORD);
113 info->cx = GET_WORD(p); p += sizeof(WORD);
114 info->cy = GET_WORD(p); p += sizeof(WORD);
115 info->id = GET_WORD(p); p += sizeof(WORD);
116 info->style = GET_DWORD(p); p += sizeof(DWORD);
117 info->exStyle = 0;
119 if (*p & 0x80)
121 switch((BYTE)*p)
123 case 0x80: strcpy( buffer, "BUTTON" ); break;
124 case 0x81: strcpy( buffer, "EDIT" ); break;
125 case 0x82: strcpy( buffer, "STATIC" ); break;
126 case 0x83: strcpy( buffer, "LISTBOX" ); break;
127 case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
128 case 0x85: strcpy( buffer, "COMBOBOX" ); break;
129 default: buffer[0] = '\0'; break;
131 info->className = buffer;
132 p++;
134 else
136 info->className = p;
137 p += strlen(p) + 1;
139 dprintf_dialog(stddeb, " %s ", info->className );
141 if ((BYTE)*p == 0xff)
143 /* Integer id, not documented (?). Only works for SS_ICON controls */
144 info->windowName = (LPCSTR)(UINT32)GET_WORD(p+1);
145 p += 3;
146 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
148 else
150 info->windowName = p;
151 p += strlen(p) + 1;
152 dprintf_dialog(stddeb,"'%s'", info->windowName );
155 info->data = (LPVOID)(*p ? p + 1 : NULL); /* FIXME: should be a segptr */
156 p += *p + 1;
158 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx\n",
159 info->id, info->x, info->y, info->cx, info->cy,
160 info->style, (DWORD)info->data);
161 return p;
165 /***********************************************************************
166 * DIALOG_GetControl32
168 * Return the class and text of the control pointed to by ptr,
169 * fill the header structure and return a pointer to the next control.
171 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info )
173 static WCHAR buffer[10];
175 info->style = GET_DWORD(p); p += 2;
176 info->exStyle = GET_DWORD(p); p += 2;
177 info->x = GET_WORD(p); p++;
178 info->y = GET_WORD(p); p++;
179 info->cx = GET_WORD(p); p++;
180 info->cy = GET_WORD(p); p++;
181 info->id = GET_WORD(p); p++;
183 if (GET_WORD(p) == 0xffff)
185 switch(GET_WORD(p+1))
187 case 0x80: STRING32_AnsiToUni( buffer, "BUTTON" ); break;
188 case 0x81: STRING32_AnsiToUni( buffer, "EDIT" ); break;
189 case 0x82: STRING32_AnsiToUni( buffer, "STATIC" ); break;
190 case 0x83: STRING32_AnsiToUni( buffer, "LISTBOX" ); break;
191 case 0x84: STRING32_AnsiToUni( buffer, "SCROLLBAR" ); break;
192 case 0x85: STRING32_AnsiToUni( buffer, "COMBOBOX" ); break;
193 default: buffer[0] = '\0'; break;
195 info->className = (LPCSTR)buffer;
196 p += 2;
198 else
200 info->className = (LPCSTR)p;
201 p += lstrlen32W( (LPCWSTR)p ) + 1;
203 dprintf_dialog(stddeb, " %p ", info->className );
205 if (GET_WORD(p) == 0xffff)
207 info->windowName = (LPCSTR)(p + 1);
208 p += 2;
209 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
211 else
213 info->windowName = (LPCSTR)p;
214 p += lstrlen32W( (LPCWSTR)p ) + 1;
215 dprintf_dialog(stddeb,"'%p'", info->windowName );
218 if (GET_WORD(p))
220 info->data = (LPVOID)(p + 1);
221 p += GET_WORD(p) / sizeof(WORD);
223 else info->data = NULL;
224 p++;
226 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n",
227 info->id, info->x, info->y, info->cx, info->cy,
228 info->style, info->exStyle, (DWORD)info->data);
229 /* Next control is on dword boundary */
230 return (const WORD *)((((int)p) + 3) & ~3);
234 /***********************************************************************
235 * DIALOG_CreateControls
237 * Create the control windows for a dialog.
239 static BOOL32 DIALOG_CreateControls( WND *pWnd, LPCSTR template, INT32 items,
240 HINSTANCE32 hInst, BOOL win32 )
242 DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
243 DLG_CONTROL_INFO info;
244 HWND32 hwndCtrl, hwndDefButton = 0;
246 dprintf_dialog(stddeb, " BEGIN\n" );
247 while (items--)
249 if (!win32)
251 HINSTANCE16 instance;
252 template = DIALOG_GetControl16( template, &info );
253 if (HIWORD(info.className) && !strcmp( info.className, "EDIT") &&
254 ((info.style & DS_LOCALEDIT) != DS_LOCALEDIT))
256 if (!dlgInfo->hDialogHeap)
258 dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
259 if (!dlgInfo->hDialogHeap)
261 fprintf( stderr, "CreateDialogIndirectParam: Insufficient memory to create heap for edit control\n" );
262 continue;
264 LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
266 instance = dlgInfo->hDialogHeap;
268 else instance = (HINSTANCE16)hInst;
270 hwndCtrl = CreateWindowEx16( info.exStyle | WS_EX_NOPARENTNOTIFY,
271 info.className, info.windowName,
272 info.style | WS_CHILD,
273 info.x * dlgInfo->xBaseUnit / 4,
274 info.y * dlgInfo->yBaseUnit / 8,
275 info.cx * dlgInfo->xBaseUnit / 4,
276 info.cy * dlgInfo->yBaseUnit / 8,
277 pWnd->hwndSelf, (HMENU)info.id,
278 instance, info.data );
280 else
282 template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info );
283 hwndCtrl = CreateWindowEx32W( info.exStyle | WS_EX_NOPARENTNOTIFY,
284 (LPCWSTR)info.className,
285 (LPCWSTR)info.windowName,
286 info.style | WS_CHILD,
287 info.x * dlgInfo->xBaseUnit / 4,
288 info.y * dlgInfo->yBaseUnit / 8,
289 info.cx * dlgInfo->xBaseUnit / 4,
290 info.cy * dlgInfo->yBaseUnit / 8,
291 pWnd->hwndSelf, (HMENU)info.id,
292 hInst, info.data );
294 if (!hwndCtrl) return FALSE;
296 /* Send initialisation messages to the control */
297 if (dlgInfo->hUserFont) SendMessage32A( hwndCtrl, WM_SETFONT,
298 (WPARAM)dlgInfo->hUserFont, 0 );
299 if (SendMessage32A(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
301 /* If there's already a default push-button, set it back */
302 /* to normal and use this one instead. */
303 if (hwndDefButton)
304 SendMessage32A( hwndDefButton, BM_SETSTYLE32,
305 BS_PUSHBUTTON,FALSE );
306 hwndDefButton = hwndCtrl;
307 dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID );
310 dprintf_dialog(stddeb, " END\n" );
311 return TRUE;
315 /***********************************************************************
316 * DIALOG_ParseTemplate16
318 * Fill a DLG_TEMPLATE structure from the dialog template, and return
319 * a pointer to the first control.
321 static LPCSTR DIALOG_ParseTemplate16( LPCSTR p, DLG_TEMPLATE * result )
323 result->style = GET_DWORD(p); p += sizeof(DWORD);
324 result->exStyle = 0;
325 result->nbItems = *p++;
326 result->x = GET_WORD(p); p += sizeof(WORD);
327 result->y = GET_WORD(p); p += sizeof(WORD);
328 result->cx = GET_WORD(p); p += sizeof(WORD);
329 result->cy = GET_WORD(p); p += sizeof(WORD);
330 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
331 result->x, result->y, result->cx, result->cy );
332 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
334 /* Get the menu name */
336 switch( (BYTE)*p )
338 case 0:
339 result->menuName = 0;
340 p++;
341 break;
342 case 0xff:
343 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
344 p += 3;
345 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
346 break;
347 default:
348 result->menuName = p;
349 dprintf_dialog( stddeb, " MENU '%s'\n", p );
350 p += strlen(p) + 1;
351 break;
354 /* Get the class name */
356 if (*p)
358 result->className = p;
359 dprintf_dialog( stddeb, " CLASS '%s'\n", result->className );
361 else result->className = DIALOG_CLASS_ATOM;
362 p += strlen(p) + 1;
364 /* Get the window caption */
366 result->caption = p;
367 p += strlen(p) + 1;
368 dprintf_dialog( stddeb, " CAPTION '%s'\n", result->caption );
370 /* Get the font name */
372 if (result->style & DS_SETFONT)
374 result->pointSize = GET_WORD(p);
375 p += sizeof(WORD);
376 result->faceName = p;
377 p += strlen(p) + 1;
378 dprintf_dialog( stddeb, " FONT %d,'%s'\n",
379 result->pointSize, result->faceName );
381 return p;
385 /***********************************************************************
386 * DIALOG_ParseTemplate32
388 * Fill a DLG_TEMPLATE structure from the dialog template, and return
389 * a pointer to the first control.
391 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
393 const WORD *p = (const WORD *)template;
395 result->style = GET_DWORD(p); p += 2;
396 result->exStyle = GET_DWORD(p); p += 2;
397 result->nbItems = GET_WORD(p); p++;
398 result->x = GET_WORD(p); p++;
399 result->y = GET_WORD(p); p++;
400 result->cx = GET_WORD(p); p++;
401 result->cy = GET_WORD(p); p++;
402 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
403 result->x, result->y, result->cx, result->cy );
404 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
405 dprintf_dialog( stddeb, " EXSTYLE %08lx\n", result->exStyle );
407 /* Get the menu name */
409 switch(GET_WORD(p))
411 case 0x0000:
412 result->menuName = NULL;
413 p++;
414 break;
415 case 0xffff:
416 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
417 p += 2;
418 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
419 break;
420 default:
421 result->menuName = (LPCSTR)p;
422 dprintf_dialog( stddeb, " MENU '%p'\n", p );
423 p += lstrlen32W( (LPCWSTR)p ) + 1;
424 break;
427 /* Get the class name */
429 switch(GET_WORD(p))
431 case 0x0000:
432 result->className = DIALOG_CLASS_ATOM;
433 p++;
434 break;
435 case 0xffff:
436 result->className = (LPCSTR)(UINT32)GET_WORD( p + 1 );
437 p += 2;
438 dprintf_dialog(stddeb, " CLASS %04x\n", LOWORD(result->className) );
439 break;
440 default:
441 result->className = (LPCSTR)p;
442 dprintf_dialog( stddeb, " CLASS '%p'\n", p );
443 p += lstrlen32W( (LPCWSTR)p ) + 1;
444 break;
447 /* Get the window caption */
449 result->caption = (LPCSTR)p;
450 p += lstrlen32W( (LPCWSTR)p ) + 1;
451 dprintf_dialog( stddeb, " CAPTION '%p'\n", result->caption );
453 /* Get the font name */
455 if (result->style & DS_SETFONT)
457 result->pointSize = GET_WORD(p);
458 p++;
459 result->faceName = (LPCSTR)p;
460 p += lstrlen32W( (LPCWSTR)p ) + 1;
461 dprintf_dialog( stddeb, " FONT %d,'%p'\n",
462 result->pointSize, result->faceName );
464 /* First control is on dword boundary */
465 return (LPCSTR)((((int)p) + 3) & ~3);
469 /***********************************************************************
470 * DIALOG_CreateIndirect
472 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
473 HWND owner, DLGPROC16 dlgProc,
474 LPARAM param, WINDOWPROCTYPE procType )
476 HMENU hMenu = 0;
477 HFONT hFont = 0;
478 HWND hwnd;
479 RECT16 rect;
480 WND * wndPtr;
481 DLG_TEMPLATE template;
482 DIALOGINFO * dlgInfo;
483 WORD xUnit = xBaseUnit;
484 WORD yUnit = yBaseUnit;
486 /* Parse dialog template */
488 if (!dlgTemplate) return 0;
489 if (procType != WIN_PROC_16)
490 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
491 else
492 dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
494 /* Load menu */
496 if (template.menuName)
498 LPSTR str = SEGPTR_STRDUP( template.menuName ); /* FIXME: win32 */
499 hMenu = LoadMenu16( hInst, SEGPTR_GET(str) );
500 SEGPTR_FREE( str );
503 /* Create custom font if needed */
505 if (template.style & DS_SETFONT)
507 /* The font height must be negative as it is a point size */
508 /* (see CreateFont() documentation in the Windows SDK). */
509 hFont = CreateFont16( -template.pointSize, 0, 0, 0, FW_DONTCARE,
510 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
511 DEFAULT_QUALITY, FF_DONTCARE,
512 template.faceName ); /* FIXME: win32 */
513 if (hFont)
515 TEXTMETRIC16 tm;
516 HFONT oldFont;
518 HDC32 hdc = GetDC32(0);
519 oldFont = SelectObject( hdc, hFont );
520 GetTextMetrics16( hdc, &tm );
521 SelectObject( hdc, oldFont );
522 ReleaseDC32( 0, hdc );
523 xUnit = tm.tmAveCharWidth;
524 yUnit = tm.tmHeight;
525 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
526 xBaseUnit = xBaseUnit * 5 / 4; /* See DIALOG_Init() */
530 /* Create dialog main window */
532 rect.left = rect.top = 0;
533 rect.right = template.cx * xUnit / 4;
534 rect.bottom = template.cy * yUnit / 8;
535 if (template.style & DS_MODALFRAME)
536 template.exStyle |= WS_EX_DLGMODALFRAME;
537 AdjustWindowRectEx16( &rect, template.style,
538 hMenu ? TRUE : FALSE , template.exStyle );
539 rect.right -= rect.left;
540 rect.bottom -= rect.top;
542 if ((INT16)template.x == CW_USEDEFAULT16)
544 rect.left = rect.top = (procType == WIN_PROC_16) ? CW_USEDEFAULT16
545 : CW_USEDEFAULT32;
547 else
549 rect.left += template.x * xUnit / 4;
550 rect.top += template.y * yUnit / 8;
551 if ( !(template.style & DS_ABSALIGN) && !(template.style & WS_CHILD) )
552 ClientToScreen16( owner, (POINT16 *)&rect );
555 if (procType != WIN_PROC_16)
556 hwnd = CreateWindowEx32W(template.exStyle, (LPCWSTR)template.className,
557 (LPCWSTR)template.caption,
558 template.style & ~WS_VISIBLE,
559 rect.left, rect.top, rect.right, rect.bottom,
560 owner, hMenu, hInst, NULL );
561 else
562 hwnd = CreateWindowEx16(template.exStyle, template.className,
563 template.caption, template.style & ~WS_VISIBLE,
564 rect.left, rect.top, rect.right, rect.bottom,
565 owner, hMenu, hInst, NULL );
566 if (!hwnd)
568 if (hFont) DeleteObject( hFont );
569 if (hMenu) DestroyMenu( hMenu );
570 return 0;
572 wndPtr = WIN_FindWndPtr( hwnd );
573 wndPtr->flags |= WIN_ISDIALOG;
575 /* Initialise dialog extra data */
577 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
578 WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType );
579 dlgInfo->hUserFont = hFont;
580 dlgInfo->hMenu = hMenu;
581 dlgInfo->xBaseUnit = xUnit;
582 dlgInfo->yBaseUnit = yUnit;
583 dlgInfo->msgResult = 0; /* This is used to store the default button id */
584 dlgInfo->hDialogHeap = 0;
586 /* Create controls */
588 if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
589 hInst, (procType != WIN_PROC_16) ))
591 DestroyWindow( hwnd );
592 return 0;
595 /* Send initialisation messages and set focus */
597 dlgInfo->hwndFocus = DIALOG_GetFirstTabItem( hwnd );
598 if (dlgInfo->hUserFont)
599 SendMessage32A( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
600 if (SendMessage32A(hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param))
601 SetFocus32( dlgInfo->hwndFocus );
602 if (template.style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
603 return hwnd;
607 /***********************************************************************
608 * CreateDialog16 (USER.89)
610 HWND16 CreateDialog16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
611 HWND16 owner, DLGPROC16 dlgProc )
613 return CreateDialogParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
617 /***********************************************************************
618 * CreateDialogParam16 (USER.241)
620 HWND16 CreateDialogParam16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
621 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
623 HWND16 hwnd = 0;
624 HRSRC16 hRsrc;
625 HGLOBAL16 hmem;
626 LPCVOID data;
628 dprintf_dialog(stddeb, "CreateDialogParam16: %04x,%08lx,%04x,%08lx,%ld\n",
629 hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
631 if (!(hRsrc = FindResource16( hInst, dlgTemplate, RT_DIALOG ))) return 0;
632 if (!(hmem = LoadResource16( hInst, hRsrc ))) return 0;
633 if (!(data = LockResource16( hmem ))) hwnd = 0;
634 else hwnd = CreateDialogIndirectParam16( hInst, data, owner,
635 dlgProc, param );
636 FreeResource16( hmem );
637 return hwnd;
641 /***********************************************************************
642 * CreateDialogParam32A (USER32.72)
644 HWND32 CreateDialogParam32A( HINSTANCE32 hInst, LPCSTR name,
645 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
647 if (HIWORD(name))
649 LPWSTR str = STRING32_DupAnsiToUni( name );
650 HWND32 hwnd = CreateDialogParam32W( hInst, str, owner, dlgProc, param);
651 free( str );
652 return hwnd;
654 return CreateDialogParam32W( hInst, (LPCWSTR)name, owner, dlgProc, param );
658 /***********************************************************************
659 * CreateDialogParam32W (USER32.73)
661 HWND32 CreateDialogParam32W( HINSTANCE32 hInst, LPCWSTR name,
662 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
664 HANDLE32 hrsrc = FindResource32W( hInst, name, (LPWSTR)RT_DIALOG );
665 if (!hrsrc) return 0;
666 return CreateDialogIndirectParam32W( hInst,
667 (LPVOID)LoadResource32(hInst, hrsrc),
668 owner, dlgProc, param );
672 /***********************************************************************
673 * CreateDialogIndirect16 (USER.219)
675 HWND16 CreateDialogIndirect16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
676 HWND16 owner, DLGPROC16 dlgProc )
678 return CreateDialogIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0);
682 /***********************************************************************
683 * CreateDialogIndirectParam16 (USER.242)
685 HWND16 CreateDialogIndirectParam16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
686 HWND16 owner, DLGPROC16 dlgProc,
687 LPARAM param )
689 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
690 dlgProc, param, WIN_PROC_16 );
694 /***********************************************************************
695 * CreateDialogIndirectParam32A (USER32.69)
697 HWND32 CreateDialogIndirectParam32A( HINSTANCE32 hInst, LPCVOID dlgTemplate,
698 HWND32 owner, DLGPROC32 dlgProc,
699 LPARAM param )
701 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
702 (DLGPROC16)dlgProc, param, WIN_PROC_32A );
706 /***********************************************************************
707 * CreateDialogIndirectParam32W (USER32.71)
709 HWND32 CreateDialogIndirectParam32W( HINSTANCE32 hInst, LPCVOID dlgTemplate,
710 HWND32 owner, DLGPROC32 dlgProc,
711 LPARAM param )
713 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
714 (DLGPROC16)dlgProc, param, WIN_PROC_32W );
718 /***********************************************************************
719 * DIALOG_DoDialogBox
721 static INT32 DIALOG_DoDialogBox( HWND hwnd, HWND owner )
723 WND * wndPtr;
724 DIALOGINFO * dlgInfo;
725 MSG16 msg;
726 INT32 retval;
728 /* Owner must be a top-level window */
729 owner = WIN_GetTopParent( owner );
730 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
731 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
732 EnableWindow( owner, FALSE );
733 ShowWindow( hwnd, SW_SHOW );
735 while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, PM_REMOVE,
736 !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
738 if (!IsDialogMessage( hwnd, &msg))
740 TranslateMessage( &msg );
741 DispatchMessage( &msg );
743 if (dlgInfo->fEnd) break;
745 retval = dlgInfo->msgResult;
746 EnableWindow( owner, TRUE );
747 DestroyWindow( hwnd );
748 return retval;
752 /***********************************************************************
753 * DialogBox16 (USER.87)
755 INT16 DialogBox16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
756 HWND16 owner, DLGPROC16 dlgProc )
758 return DialogBoxParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
762 /***********************************************************************
763 * DialogBoxParam16 (USER.239)
765 INT16 DialogBoxParam16( HINSTANCE16 hInst, SEGPTR template,
766 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
768 HWND16 hwnd = CreateDialogParam16( hInst, template, owner, dlgProc, param);
769 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
770 return -1;
774 /***********************************************************************
775 * DialogBoxParam32A (USER32.138)
777 INT32 DialogBoxParam32A( HINSTANCE32 hInst, LPCSTR name,
778 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
780 HWND32 hwnd = CreateDialogParam32A( hInst, name, owner, dlgProc, param );
781 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
782 return -1;
786 /***********************************************************************
787 * DialogBoxParam32W (USER32.139)
789 INT32 DialogBoxParam32W( HINSTANCE32 hInst, LPCWSTR name,
790 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
792 HWND32 hwnd = CreateDialogParam32W( hInst, name, owner, dlgProc, param );
793 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
794 return -1;
798 /***********************************************************************
799 * DialogBoxIndirect16 (USER.218)
801 INT16 DialogBoxIndirect16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
802 HWND16 owner, DLGPROC16 dlgProc )
804 return DialogBoxIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
808 /***********************************************************************
809 * DialogBoxIndirectParam16 (USER.240)
811 INT16 DialogBoxIndirectParam16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
812 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
814 HWND16 hwnd;
815 LPCVOID ptr;
817 if (!(ptr = GlobalLock16( dlgTemplate ))) return -1;
818 hwnd = CreateDialogIndirectParam16( hInst, ptr, owner, dlgProc, param );
819 GlobalUnlock16( dlgTemplate );
820 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
821 return -1;
825 /***********************************************************************
826 * DialogBoxIndirectParam32A (USER32.135)
828 INT32 DialogBoxIndirectParam32A( HINSTANCE32 hInstance, LPCVOID template,
829 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
831 HWND32 hwnd = CreateDialogIndirectParam32A( hInstance, template,
832 owner, dlgProc, param );
833 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
834 return -1;
838 /***********************************************************************
839 * DialogBoxIndirectParam32W (USER32.137)
841 INT32 DialogBoxIndirectParam32W( HINSTANCE32 hInstance, LPCVOID template,
842 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
844 HWND32 hwnd = CreateDialogIndirectParam32W( hInstance, template,
845 owner, dlgProc, param );
846 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
847 return -1;
851 /***********************************************************************
852 * EndDialog (USER.88) (USER32.173)
854 BOOL16 EndDialog( HWND32 hwnd, INT32 retval )
856 WND * wndPtr = WIN_FindWndPtr( hwnd );
857 DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
858 dlgInfo->msgResult = retval;
859 dlgInfo->fEnd = TRUE;
860 dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
861 return TRUE;
865 /***********************************************************************
866 * IsDialogMessage (USER.90)
868 BOOL IsDialogMessage( HWND hwndDlg, LPMSG16 msg )
870 WND * wndPtr;
871 int dlgCode;
873 if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
874 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
876 /* Only the key messages get special processing */
877 if ((msg->message != WM_KEYDOWN) &&
878 (msg->message != WM_SYSCHAR) &&
879 (msg->message != WM_CHAR))
880 return FALSE;
882 dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, 0 );
883 if (dlgCode & DLGC_WANTMESSAGE)
885 DispatchMessage( msg );
886 return TRUE;
889 switch(msg->message)
891 case WM_KEYDOWN:
892 if (dlgCode & DLGC_WANTALLKEYS) break;
893 switch(msg->wParam)
895 case VK_TAB:
896 if (!(dlgCode & DLGC_WANTTAB))
898 SendMessage16( hwndDlg, WM_NEXTDLGCTL,
899 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
900 return TRUE;
902 break;
904 case VK_RIGHT:
905 case VK_DOWN:
906 if (!(dlgCode & DLGC_WANTARROWS))
908 SetFocus32( GetNextDlgGroupItem(hwndDlg,GetFocus32(),FALSE) );
909 return TRUE;
911 break;
913 case VK_LEFT:
914 case VK_UP:
915 if (!(dlgCode & DLGC_WANTARROWS))
917 SetFocus32( GetNextDlgGroupItem(hwndDlg,GetFocus32(),TRUE) );
918 return TRUE;
920 break;
922 case VK_ESCAPE:
923 SendMessage32A( hwndDlg, WM_COMMAND, IDCANCEL,
924 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
925 break;
927 case VK_RETURN:
929 DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
930 if (HIWORD(dw) == DC_HASDEFID)
931 SendMessage32A( hwndDlg, WM_COMMAND,
932 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
933 (LPARAM)GetDlgItem( hwndDlg, LOWORD(dw) ));
934 else
935 SendMessage32A( hwndDlg, WM_COMMAND, IDOK,
936 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
938 break;
940 default:
941 TranslateMessage( msg );
943 break; /* case WM_KEYDOWN */
946 case WM_CHAR:
947 if (dlgCode & (DLGC_WANTALLKEYS | DLGC_WANTCHARS)) break;
948 break;
950 case WM_SYSCHAR:
951 if (dlgCode & DLGC_WANTALLKEYS) break;
952 break;
955 /* If we get here, the message has not been treated specially */
956 /* and can be sent to its destination window. */
957 DispatchMessage( msg );
958 return TRUE;
962 /****************************************************************
963 * GetDlgCtrlID (USER.277) (USER32.233)
965 INT16 GetDlgCtrlID( HWND32 hwnd )
967 WND *wndPtr = WIN_FindWndPtr(hwnd);
968 if (wndPtr) return wndPtr->wIDmenu;
969 else return 0;
973 /***********************************************************************
974 * GetDlgItem (USER.91)
976 HWND GetDlgItem( HWND hwndDlg, WORD id )
978 WND *pWnd;
980 if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
981 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
982 if (pWnd->wIDmenu == id) return pWnd->hwndSelf;
983 return 0;
987 /*******************************************************************
988 * SendDlgItemMessage16 (USER.101)
990 LRESULT SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
991 WPARAM16 wParam, LPARAM lParam )
993 HWND16 hwndCtrl = GetDlgItem( hwnd, id );
994 if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
995 else return 0;
999 /*******************************************************************
1000 * SendDlgItemMessage32A (USER32.451)
1002 LRESULT SendDlgItemMessage32A( HWND32 hwnd, INT32 id, UINT32 msg,
1003 WPARAM32 wParam, LPARAM lParam )
1005 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
1006 if (hwndCtrl) return SendMessage32A( hwndCtrl, msg, wParam, lParam );
1007 else return 0;
1011 /*******************************************************************
1012 * SendDlgItemMessage32W (USER32.452)
1014 LRESULT SendDlgItemMessage32W( HWND32 hwnd, INT32 id, UINT32 msg,
1015 WPARAM32 wParam, LPARAM lParam )
1017 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
1018 if (hwndCtrl) return SendMessage32W( hwndCtrl, msg, wParam, lParam );
1019 else return 0;
1023 /*******************************************************************
1024 * SetDlgItemText16 (USER.92)
1026 void SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
1028 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1032 /*******************************************************************
1033 * SetDlgItemText32A (USER32.477)
1035 void SetDlgItemText32A( HWND32 hwnd, INT32 id, LPCSTR lpString )
1037 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1041 /*******************************************************************
1042 * SetDlgItemText32W (USER32.478)
1044 void SetDlgItemText32W( HWND32 hwnd, INT32 id, LPCWSTR lpString )
1046 SendDlgItemMessage32W( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1050 /***********************************************************************
1051 * GetDlgItemText16 (USER.93)
1053 INT16 GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
1055 return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
1056 len, (LPARAM)str );
1060 /***********************************************************************
1061 * GetDlgItemText32A (USER32.236)
1063 INT32 GetDlgItemText32A( HWND32 hwnd, INT32 id, LPSTR str, UINT32 len )
1065 return (INT32)SendDlgItemMessage32A( hwnd, id, WM_GETTEXT,
1066 len, (LPARAM)str );
1070 /***********************************************************************
1071 * GetDlgItemText32W (USER32.237)
1073 INT32 GetDlgItemText32W( HWND32 hwnd, INT32 id, LPWSTR str, UINT32 len )
1075 return (INT32)SendDlgItemMessage32W( hwnd, id, WM_GETTEXT,
1076 len, (LPARAM)str );
1080 /*******************************************************************
1081 * SetDlgItemInt16 (USER.94)
1083 void SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
1085 char *str = (char *)SEGPTR_ALLOC( 20 * sizeof(char) );
1087 if (!str) return;
1088 if (fSigned) sprintf( str, "%d", (INT32)(INT16)value );
1089 else sprintf( str, "%u", value );
1090 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)SEGPTR_GET(str) );
1091 SEGPTR_FREE(str);
1095 /*******************************************************************
1096 * SetDlgItemInt32 (USER32.476)
1098 void SetDlgItemInt32( HWND32 hwnd, INT32 id, UINT32 value, BOOL32 fSigned )
1100 char str[20];
1102 if (fSigned) sprintf( str, "%d", (INT32)value );
1103 else sprintf( str, "%u", value );
1104 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1108 /***********************************************************************
1109 * GetDlgItemInt (USER.95)
1111 WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
1113 char *str;
1114 long result = 0;
1116 if (translated) *translated = FALSE;
1117 if (!(str = (char *)SEGPTR_ALLOC( 30 * sizeof(char) ))) return 0;
1118 if (SendDlgItemMessage16( hwnd, id, WM_GETTEXT, 30, (LPARAM)SEGPTR_GET(str)))
1120 char * endptr;
1121 result = strtol( str, &endptr, 10 );
1122 if (endptr && (endptr != str)) /* Conversion was successful */
1124 if (fSigned)
1126 if ((result < -32767) || (result > 32767)) result = 0;
1127 else if (translated) *translated = TRUE;
1129 else
1131 if ((result < 0) || (result > 65535)) result = 0;
1132 else if (translated) *translated = TRUE;
1136 SEGPTR_FREE(str);
1137 return (WORD)result;
1141 /***********************************************************************
1142 * CheckDlgButton (USER.97) (USER32.44)
1144 BOOL16 CheckDlgButton( HWND32 hwnd, INT32 id, UINT32 check )
1146 SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
1147 return TRUE;
1151 /***********************************************************************
1152 * IsDlgButtonChecked (USER.98)
1154 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
1156 return (WORD)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
1160 /***********************************************************************
1161 * CheckRadioButton (USER.96) (USER32.47)
1163 BOOL16 CheckRadioButton( HWND32 hwndDlg, UINT32 firstID, UINT32 lastID,
1164 UINT32 checkID )
1166 WND *pWnd = WIN_FindWndPtr( hwndDlg );
1167 if (!pWnd) return FALSE;
1169 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1170 if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) break;
1171 if (!pWnd) return FALSE;
1173 if (pWnd->wIDmenu == lastID)
1174 lastID = firstID; /* Buttons are in reverse order */
1175 while (pWnd)
1177 SendMessage32A( pWnd->hwndSelf, BM_SETCHECK32,
1178 (pWnd->wIDmenu == checkID), 0 );
1179 if (pWnd->wIDmenu == lastID) break;
1180 pWnd = pWnd->next;
1182 return TRUE;
1186 /***********************************************************************
1187 * GetDialogBaseUnits (USER.243)
1189 DWORD GetDialogBaseUnits()
1191 return MAKELONG( xBaseUnit, yBaseUnit );
1195 /***********************************************************************
1196 * MapDialogRect16 (USER.103)
1198 void MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
1200 DIALOGINFO * dlgInfo;
1201 WND * wndPtr = WIN_FindWndPtr( hwnd );
1202 if (!wndPtr) return;
1203 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1204 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1205 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1206 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1207 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1211 /***********************************************************************
1212 * MapDialogRect32 (USER32.381)
1214 void MapDialogRect32( HWND32 hwnd, LPRECT32 rect )
1216 DIALOGINFO * dlgInfo;
1217 WND * wndPtr = WIN_FindWndPtr( hwnd );
1218 if (!wndPtr) return;
1219 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1220 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1221 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1222 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1223 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1227 /***********************************************************************
1228 * GetNextDlgGroupItem (USER.227)
1230 HWND GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1232 WND *pWnd, *pWndStart, *pWndCtrl, *pWndDlg;
1234 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1235 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1236 if (pWndCtrl->parent != pWndDlg) return 0;
1238 if (!fPrevious && pWndCtrl->next) /* Check if next control is in group */
1240 if (!(pWndCtrl->next->dwStyle & WS_GROUP))
1241 return pWndCtrl->next->hwndSelf;
1244 /* Now we will have to find the start of the group */
1246 for (pWnd = pWndStart = pWndDlg->child; pWnd; pWnd = pWnd->next)
1248 if (pWnd->dwStyle & WS_GROUP) pWndStart = pWnd; /* Start of a group */
1249 if (pWnd == pWndCtrl) break;
1252 if (!pWnd) fprintf(stderr, "GetNextDlgGroupItem: hwnd not in dialog!\n");
1254 /* only case left for forward search: wraparound */
1255 if (!fPrevious) return pWndStart->hwndSelf;
1257 pWnd = pWndStart->next;
1258 while (pWnd && (pWnd != pWndCtrl))
1260 if (pWnd->dwStyle & WS_GROUP) break;
1261 pWndStart = pWnd;
1262 pWnd = pWnd->next;
1264 return pWndStart->hwndSelf;
1268 /***********************************************************************
1269 * GetNextDlgTabItem (USER.228)
1271 HWND GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1273 WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1275 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1276 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1277 if (pWndCtrl->parent != pWndDlg) return 0;
1279 pWndLast = pWndCtrl;
1280 pWnd = pWndCtrl->next;
1281 while (1)
1283 if (!pWnd) pWnd = pWndDlg->child;
1284 if (pWnd == pWndCtrl) break;
1285 if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE))
1287 pWndLast = pWnd;
1288 if (!fPrevious) break;
1290 pWnd = pWnd->next;
1292 return pWndLast->hwndSelf;