Release 961102
[wine/hacks.git] / windows / dialog.c
blob17a349a990dec95be057aadc9344b02321212623
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 BOOL32 DIALOG_Init()
66 TEXTMETRIC16 tm;
67 HDC16 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_GetControl16
90 * Return the class and text of the control pointed to by ptr,
91 * fill the header structure and return a pointer to the next control.
93 static LPCSTR DIALOG_GetControl16( LPCSTR p, DLG_CONTROL_INFO *info )
95 static char buffer[10];
97 info->x = GET_WORD(p); p += sizeof(WORD);
98 info->y = GET_WORD(p); p += sizeof(WORD);
99 info->cx = GET_WORD(p); p += sizeof(WORD);
100 info->cy = GET_WORD(p); p += sizeof(WORD);
101 info->id = GET_WORD(p); p += sizeof(WORD);
102 info->style = GET_DWORD(p); p += sizeof(DWORD);
103 info->exStyle = 0;
105 if (*p & 0x80)
107 switch((BYTE)*p)
109 case 0x80: strcpy( buffer, "BUTTON" ); break;
110 case 0x81: strcpy( buffer, "EDIT" ); break;
111 case 0x82: strcpy( buffer, "STATIC" ); break;
112 case 0x83: strcpy( buffer, "LISTBOX" ); break;
113 case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
114 case 0x85: strcpy( buffer, "COMBOBOX" ); break;
115 default: buffer[0] = '\0'; break;
117 info->className = buffer;
118 p++;
120 else
122 info->className = p;
123 p += strlen(p) + 1;
125 dprintf_dialog(stddeb, " %s ", info->className );
127 if ((BYTE)*p == 0xff)
129 /* Integer id, not documented (?). Only works for SS_ICON controls */
130 info->windowName = (LPCSTR)(UINT32)GET_WORD(p+1);
131 p += 3;
132 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
134 else
136 info->windowName = p;
137 p += strlen(p) + 1;
138 dprintf_dialog(stddeb,"'%s'", info->windowName );
141 info->data = (LPVOID)(*p ? p + 1 : NULL); /* FIXME: should be a segptr */
142 p += *p + 1;
144 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx\n",
145 info->id, info->x, info->y, info->cx, info->cy,
146 info->style, (DWORD)info->data);
147 return p;
151 /***********************************************************************
152 * DIALOG_GetControl32
154 * Return the class and text of the control pointed to by ptr,
155 * fill the header structure and return a pointer to the next control.
157 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info )
159 static WCHAR buffer[10];
161 info->style = GET_DWORD(p); p += 2;
162 info->exStyle = GET_DWORD(p); p += 2;
163 info->x = GET_WORD(p); p++;
164 info->y = GET_WORD(p); p++;
165 info->cx = GET_WORD(p); p++;
166 info->cy = GET_WORD(p); p++;
167 info->id = GET_WORD(p); p++;
169 if (GET_WORD(p) == 0xffff)
171 switch(GET_WORD(p+1))
173 case 0x80: STRING32_AnsiToUni( buffer, "BUTTON" ); break;
174 case 0x81: STRING32_AnsiToUni( buffer, "EDIT" ); break;
175 case 0x82: STRING32_AnsiToUni( buffer, "STATIC" ); break;
176 case 0x83: STRING32_AnsiToUni( buffer, "LISTBOX" ); break;
177 case 0x84: STRING32_AnsiToUni( buffer, "SCROLLBAR" ); break;
178 case 0x85: STRING32_AnsiToUni( buffer, "COMBOBOX" ); break;
179 default: buffer[0] = '\0'; break;
181 info->className = (LPCSTR)buffer;
182 p += 2;
184 else
186 info->className = (LPCSTR)p;
187 p += lstrlen32W( (LPCWSTR)p ) + 1;
189 dprintf_dialog(stddeb, " %p ", info->className );
191 if (GET_WORD(p) == 0xffff)
193 info->windowName = (LPCSTR)(p + 1);
194 p += 2;
195 dprintf_dialog( stddeb,"%04x", LOWORD(info->windowName) );
197 else
199 info->windowName = (LPCSTR)p;
200 p += lstrlen32W( (LPCWSTR)p ) + 1;
201 dprintf_dialog(stddeb,"'%p'", info->windowName );
204 if (GET_WORD(p))
206 info->data = (LPVOID)(p + 1);
207 p += GET_WORD(p) / sizeof(WORD);
209 else info->data = NULL;
210 p++;
212 dprintf_dialog( stddeb," %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n",
213 info->id, info->x, info->y, info->cx, info->cy,
214 info->style, info->exStyle, (DWORD)info->data);
215 /* Next control is on dword boundary */
216 return (const WORD *)((((int)p) + 3) & ~3);
220 /***********************************************************************
221 * DIALOG_CreateControls
223 * Create the control windows for a dialog.
225 static BOOL32 DIALOG_CreateControls( WND *pWnd, LPCSTR template, INT32 items,
226 HINSTANCE32 hInst, BOOL win32 )
228 DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
229 DLG_CONTROL_INFO info;
230 HWND32 hwndCtrl, hwndDefButton = 0;
232 dprintf_dialog(stddeb, " BEGIN\n" );
233 while (items--)
235 if (!win32)
237 HINSTANCE16 instance;
238 template = DIALOG_GetControl16( template, &info );
239 if (HIWORD(info.className) && !strcmp( info.className, "EDIT") &&
240 ((pWnd->dwStyle & DS_LOCALEDIT) != DS_LOCALEDIT))
242 if (!dlgInfo->hDialogHeap)
244 dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
245 if (!dlgInfo->hDialogHeap)
247 fprintf( stderr, "CreateDialogIndirectParam: Insufficient memory to create heap for edit control\n" );
248 continue;
250 LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
252 instance = dlgInfo->hDialogHeap;
254 else instance = (HINSTANCE16)hInst;
256 hwndCtrl = CreateWindowEx16( info.exStyle | WS_EX_NOPARENTNOTIFY,
257 info.className, info.windowName,
258 info.style | WS_CHILD,
259 info.x * dlgInfo->xBaseUnit / 4,
260 info.y * dlgInfo->yBaseUnit / 8,
261 info.cx * dlgInfo->xBaseUnit / 4,
262 info.cy * dlgInfo->yBaseUnit / 8,
263 pWnd->hwndSelf, (HMENU16)info.id,
264 instance, info.data );
266 else
268 template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info );
269 hwndCtrl = CreateWindowEx32W( info.exStyle | WS_EX_NOPARENTNOTIFY,
270 (LPCWSTR)info.className,
271 (LPCWSTR)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, (HMENU32)info.id,
278 hInst, info.data );
280 if (!hwndCtrl) return FALSE;
282 /* Send initialisation messages to the control */
283 if (dlgInfo->hUserFont) SendMessage32A( hwndCtrl, WM_SETFONT,
284 (WPARAM32)dlgInfo->hUserFont, 0 );
285 if (SendMessage32A(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
287 /* If there's already a default push-button, set it back */
288 /* to normal and use this one instead. */
289 if (hwndDefButton)
290 SendMessage32A( hwndDefButton, BM_SETSTYLE32,
291 BS_PUSHBUTTON,FALSE );
292 hwndDefButton = hwndCtrl;
293 dlgInfo->msgResult = GetWindowWord( hwndCtrl, GWW_ID );
296 dprintf_dialog(stddeb, " END\n" );
297 return TRUE;
301 /***********************************************************************
302 * DIALOG_ParseTemplate16
304 * Fill a DLG_TEMPLATE structure from the dialog template, and return
305 * a pointer to the first control.
307 static LPCSTR DIALOG_ParseTemplate16( LPCSTR p, DLG_TEMPLATE * result )
309 result->style = GET_DWORD(p); p += sizeof(DWORD);
310 result->exStyle = 0;
311 result->nbItems = *p++;
312 result->x = GET_WORD(p); p += sizeof(WORD);
313 result->y = GET_WORD(p); p += sizeof(WORD);
314 result->cx = GET_WORD(p); p += sizeof(WORD);
315 result->cy = GET_WORD(p); p += sizeof(WORD);
316 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
317 result->x, result->y, result->cx, result->cy );
318 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
320 /* Get the menu name */
322 switch( (BYTE)*p )
324 case 0:
325 result->menuName = 0;
326 p++;
327 break;
328 case 0xff:
329 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
330 p += 3;
331 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
332 break;
333 default:
334 result->menuName = p;
335 dprintf_dialog( stddeb, " MENU '%s'\n", p );
336 p += strlen(p) + 1;
337 break;
340 /* Get the class name */
342 if (*p)
344 result->className = p;
345 dprintf_dialog( stddeb, " CLASS '%s'\n", result->className );
347 else result->className = DIALOG_CLASS_ATOM;
348 p += strlen(p) + 1;
350 /* Get the window caption */
352 result->caption = p;
353 p += strlen(p) + 1;
354 dprintf_dialog( stddeb, " CAPTION '%s'\n", result->caption );
356 /* Get the font name */
358 if (result->style & DS_SETFONT)
360 result->pointSize = GET_WORD(p);
361 p += sizeof(WORD);
362 result->faceName = p;
363 p += strlen(p) + 1;
364 dprintf_dialog( stddeb, " FONT %d,'%s'\n",
365 result->pointSize, result->faceName );
367 return p;
371 /***********************************************************************
372 * DIALOG_ParseTemplate32
374 * Fill a DLG_TEMPLATE structure from the dialog template, and return
375 * a pointer to the first control.
377 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
379 const WORD *p = (const WORD *)template;
381 result->style = GET_DWORD(p); p += 2;
382 result->exStyle = GET_DWORD(p); p += 2;
383 result->nbItems = GET_WORD(p); p++;
384 result->x = GET_WORD(p); p++;
385 result->y = GET_WORD(p); p++;
386 result->cx = GET_WORD(p); p++;
387 result->cy = GET_WORD(p); p++;
388 dprintf_dialog( stddeb, "DIALOG %d, %d, %d, %d\n",
389 result->x, result->y, result->cx, result->cy );
390 dprintf_dialog( stddeb, " STYLE %08lx\n", result->style );
391 dprintf_dialog( stddeb, " EXSTYLE %08lx\n", result->exStyle );
393 /* Get the menu name */
395 switch(GET_WORD(p))
397 case 0x0000:
398 result->menuName = NULL;
399 p++;
400 break;
401 case 0xffff:
402 result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
403 p += 2;
404 dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
405 break;
406 default:
407 result->menuName = (LPCSTR)p;
408 dprintf_dialog( stddeb, " MENU '%p'\n", p );
409 p += lstrlen32W( (LPCWSTR)p ) + 1;
410 break;
413 /* Get the class name */
415 switch(GET_WORD(p))
417 case 0x0000:
418 result->className = DIALOG_CLASS_ATOM;
419 p++;
420 break;
421 case 0xffff:
422 result->className = (LPCSTR)(UINT32)GET_WORD( p + 1 );
423 p += 2;
424 dprintf_dialog(stddeb, " CLASS %04x\n", LOWORD(result->className) );
425 break;
426 default:
427 result->className = (LPCSTR)p;
428 dprintf_dialog( stddeb, " CLASS '%p'\n", p );
429 p += lstrlen32W( (LPCWSTR)p ) + 1;
430 break;
433 /* Get the window caption */
435 result->caption = (LPCSTR)p;
436 p += lstrlen32W( (LPCWSTR)p ) + 1;
437 dprintf_dialog( stddeb, " CAPTION '%p'\n", result->caption );
439 /* Get the font name */
441 if (result->style & DS_SETFONT)
443 result->pointSize = GET_WORD(p);
444 p++;
445 result->faceName = (LPCSTR)p;
446 p += lstrlen32W( (LPCWSTR)p ) + 1;
447 dprintf_dialog( stddeb, " FONT %d,'%p'\n",
448 result->pointSize, result->faceName );
450 /* First control is on dword boundary */
451 return (LPCSTR)((((int)p) + 3) & ~3);
455 /***********************************************************************
456 * DIALOG_CreateIndirect
458 static HWND DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate,
459 HWND owner, DLGPROC16 dlgProc,
460 LPARAM param, WINDOWPROCTYPE procType )
462 HMENU16 hMenu = 0;
463 HFONT16 hFont = 0;
464 HWND hwnd;
465 RECT16 rect;
466 WND * wndPtr;
467 DLG_TEMPLATE template;
468 DIALOGINFO * dlgInfo;
469 WORD xUnit = xBaseUnit;
470 WORD yUnit = yBaseUnit;
472 /* Parse dialog template */
474 if (!dlgTemplate) return 0;
475 if (procType != WIN_PROC_16)
476 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
477 else
478 dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
480 /* Load menu */
482 if (template.menuName)
484 LPSTR str = SEGPTR_STRDUP( template.menuName ); /* FIXME: win32 */
485 hMenu = LoadMenu16( hInst, SEGPTR_GET(str) );
486 SEGPTR_FREE( str );
489 /* Create custom font if needed */
491 if (template.style & DS_SETFONT)
493 /* The font height must be negative as it is a point size */
494 /* (see CreateFont() documentation in the Windows SDK). */
495 hFont = CreateFont16( -template.pointSize, 0, 0, 0, FW_DONTCARE,
496 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
497 DEFAULT_QUALITY, FF_DONTCARE,
498 template.faceName ); /* FIXME: win32 */
499 if (hFont)
501 TEXTMETRIC16 tm;
502 HFONT16 oldFont;
504 HDC32 hdc = GetDC32(0);
505 oldFont = SelectObject32( hdc, hFont );
506 GetTextMetrics16( hdc, &tm );
507 SelectObject32( hdc, oldFont );
508 ReleaseDC32( 0, hdc );
509 xUnit = tm.tmAveCharWidth;
510 yUnit = tm.tmHeight;
511 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
512 xBaseUnit = xBaseUnit * 5 / 4; /* See DIALOG_Init() */
516 /* Create dialog main window */
518 rect.left = rect.top = 0;
519 rect.right = template.cx * xUnit / 4;
520 rect.bottom = template.cy * yUnit / 8;
521 if (template.style & DS_MODALFRAME)
522 template.exStyle |= WS_EX_DLGMODALFRAME;
523 AdjustWindowRectEx16( &rect, template.style,
524 hMenu ? TRUE : FALSE , template.exStyle );
525 rect.right -= rect.left;
526 rect.bottom -= rect.top;
528 if ((INT16)template.x == CW_USEDEFAULT16)
530 rect.left = rect.top = (procType == WIN_PROC_16) ? CW_USEDEFAULT16
531 : CW_USEDEFAULT32;
533 else
535 rect.left += template.x * xUnit / 4;
536 rect.top += template.y * yUnit / 8;
537 if ( !(template.style & DS_ABSALIGN) && !(template.style & WS_CHILD) )
538 ClientToScreen16( owner, (POINT16 *)&rect );
541 if (procType != WIN_PROC_16)
542 hwnd = CreateWindowEx32W(template.exStyle, (LPCWSTR)template.className,
543 (LPCWSTR)template.caption,
544 template.style & ~WS_VISIBLE,
545 rect.left, rect.top, rect.right, rect.bottom,
546 owner, hMenu, hInst, NULL );
547 else
548 hwnd = CreateWindowEx16(template.exStyle, template.className,
549 template.caption, template.style & ~WS_VISIBLE,
550 rect.left, rect.top, rect.right, rect.bottom,
551 owner, hMenu, hInst, NULL );
552 if (!hwnd)
554 if (hFont) DeleteObject32( hFont );
555 if (hMenu) DestroyMenu( hMenu );
556 return 0;
558 wndPtr = WIN_FindWndPtr( hwnd );
559 wndPtr->flags |= WIN_ISDIALOG;
561 /* Initialise dialog extra data */
563 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
564 WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType );
565 dlgInfo->hUserFont = hFont;
566 dlgInfo->hMenu = hMenu;
567 dlgInfo->xBaseUnit = xUnit;
568 dlgInfo->yBaseUnit = yUnit;
569 dlgInfo->msgResult = 0; /* This is used to store the default button id */
570 dlgInfo->hDialogHeap = 0;
572 /* Create controls */
574 if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
575 hInst, (procType != WIN_PROC_16) ))
577 DestroyWindow( hwnd );
578 return 0;
581 /* Send initialisation messages and set focus */
583 dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE );
584 if (dlgInfo->hUserFont)
585 SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 );
586 if (SendMessage32A( hwnd, WM_INITDIALOG,
587 (WPARAM32)dlgInfo->hwndFocus, param ))
588 SetFocus32( dlgInfo->hwndFocus );
589 if (template.style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
590 return hwnd;
594 /***********************************************************************
595 * CreateDialog16 (USER.89)
597 HWND16 CreateDialog16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
598 HWND16 owner, DLGPROC16 dlgProc )
600 return CreateDialogParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
604 /***********************************************************************
605 * CreateDialogParam16 (USER.241)
607 HWND16 CreateDialogParam16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
608 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
610 HWND16 hwnd = 0;
611 HRSRC16 hRsrc;
612 HGLOBAL16 hmem;
613 LPCVOID data;
615 dprintf_dialog(stddeb, "CreateDialogParam16: %04x,%08lx,%04x,%08lx,%ld\n",
616 hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
618 if (!(hRsrc = FindResource16( hInst, dlgTemplate, RT_DIALOG ))) return 0;
619 if (!(hmem = LoadResource16( hInst, hRsrc ))) return 0;
620 if (!(data = LockResource16( hmem ))) hwnd = 0;
621 else hwnd = CreateDialogIndirectParam16( hInst, data, owner,
622 dlgProc, param );
623 FreeResource16( hmem );
624 return hwnd;
628 /***********************************************************************
629 * CreateDialogParam32A (USER32.72)
631 HWND32 CreateDialogParam32A( HINSTANCE32 hInst, LPCSTR name,
632 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
634 if (HIWORD(name))
636 LPWSTR str = STRING32_DupAnsiToUni( name );
637 HWND32 hwnd = CreateDialogParam32W( hInst, str, owner, dlgProc, param);
638 free( str );
639 return hwnd;
641 return CreateDialogParam32W( hInst, (LPCWSTR)name, owner, dlgProc, param );
645 /***********************************************************************
646 * CreateDialogParam32W (USER32.73)
648 HWND32 CreateDialogParam32W( HINSTANCE32 hInst, LPCWSTR name,
649 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
651 HANDLE32 hrsrc = FindResource32W( hInst, name, (LPWSTR)RT_DIALOG );
652 if (!hrsrc) return 0;
653 return CreateDialogIndirectParam32W( hInst,
654 (LPVOID)LoadResource32(hInst, hrsrc),
655 owner, dlgProc, param );
659 /***********************************************************************
660 * CreateDialogIndirect16 (USER.219)
662 HWND16 CreateDialogIndirect16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
663 HWND16 owner, DLGPROC16 dlgProc )
665 return CreateDialogIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0);
669 /***********************************************************************
670 * CreateDialogIndirectParam16 (USER.242)
672 HWND16 CreateDialogIndirectParam16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
673 HWND16 owner, DLGPROC16 dlgProc,
674 LPARAM param )
676 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
677 dlgProc, param, WIN_PROC_16 );
681 /***********************************************************************
682 * CreateDialogIndirectParam32A (USER32.69)
684 HWND32 CreateDialogIndirectParam32A( HINSTANCE32 hInst, LPCVOID dlgTemplate,
685 HWND32 owner, DLGPROC32 dlgProc,
686 LPARAM param )
688 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
689 (DLGPROC16)dlgProc, param, WIN_PROC_32A );
693 /***********************************************************************
694 * CreateDialogIndirectParam32W (USER32.71)
696 HWND32 CreateDialogIndirectParam32W( HINSTANCE32 hInst, LPCVOID dlgTemplate,
697 HWND32 owner, DLGPROC32 dlgProc,
698 LPARAM param )
700 return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
701 (DLGPROC16)dlgProc, param, WIN_PROC_32W );
705 /***********************************************************************
706 * DIALOG_DoDialogBox
708 static INT32 DIALOG_DoDialogBox( HWND hwnd, HWND owner )
710 WND * wndPtr;
711 DIALOGINFO * dlgInfo;
712 MSG16 msg;
713 INT32 retval;
715 /* Owner must be a top-level window */
716 owner = WIN_GetTopParent( owner );
717 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
718 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
719 EnableWindow( owner, FALSE );
720 ShowWindow( hwnd, SW_SHOW );
722 while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, PM_REMOVE,
723 !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
725 if (!IsDialogMessage( hwnd, &msg))
727 TranslateMessage( &msg );
728 DispatchMessage( &msg );
730 if (dlgInfo->fEnd) break;
732 retval = dlgInfo->msgResult;
733 EnableWindow( owner, TRUE );
734 DestroyWindow( hwnd );
735 return retval;
739 /***********************************************************************
740 * DialogBox16 (USER.87)
742 INT16 DialogBox16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
743 HWND16 owner, DLGPROC16 dlgProc )
745 return DialogBoxParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
749 /***********************************************************************
750 * DialogBoxParam16 (USER.239)
752 INT16 DialogBoxParam16( HINSTANCE16 hInst, SEGPTR template,
753 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
755 HWND16 hwnd = CreateDialogParam16( hInst, template, owner, dlgProc, param);
756 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
757 return -1;
761 /***********************************************************************
762 * DialogBoxParam32A (USER32.138)
764 INT32 DialogBoxParam32A( HINSTANCE32 hInst, LPCSTR name,
765 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
767 HWND32 hwnd = CreateDialogParam32A( hInst, name, owner, dlgProc, param );
768 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
769 return -1;
773 /***********************************************************************
774 * DialogBoxParam32W (USER32.139)
776 INT32 DialogBoxParam32W( HINSTANCE32 hInst, LPCWSTR name,
777 HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
779 HWND32 hwnd = CreateDialogParam32W( hInst, name, owner, dlgProc, param );
780 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
781 return -1;
785 /***********************************************************************
786 * DialogBoxIndirect16 (USER.218)
788 INT16 DialogBoxIndirect16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
789 HWND16 owner, DLGPROC16 dlgProc )
791 return DialogBoxIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
795 /***********************************************************************
796 * DialogBoxIndirectParam16 (USER.240)
798 INT16 DialogBoxIndirectParam16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
799 HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
801 HWND16 hwnd;
802 LPCVOID ptr;
804 if (!(ptr = GlobalLock16( dlgTemplate ))) return -1;
805 hwnd = CreateDialogIndirectParam16( hInst, ptr, owner, dlgProc, param );
806 GlobalUnlock16( dlgTemplate );
807 if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
808 return -1;
812 /***********************************************************************
813 * DialogBoxIndirectParam32A (USER32.135)
815 INT32 DialogBoxIndirectParam32A( HINSTANCE32 hInstance, LPCVOID template,
816 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
818 HWND32 hwnd = CreateDialogIndirectParam32A( hInstance, template,
819 owner, dlgProc, param );
820 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
821 return -1;
825 /***********************************************************************
826 * DialogBoxIndirectParam32W (USER32.137)
828 INT32 DialogBoxIndirectParam32W( HINSTANCE32 hInstance, LPCVOID template,
829 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
831 HWND32 hwnd = CreateDialogIndirectParam32W( hInstance, template,
832 owner, dlgProc, param );
833 if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
834 return -1;
838 /***********************************************************************
839 * EndDialog (USER.88) (USER32.173)
841 BOOL16 EndDialog( HWND32 hwnd, INT32 retval )
843 WND * wndPtr = WIN_FindWndPtr( hwnd );
844 DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
845 dlgInfo->msgResult = retval;
846 dlgInfo->fEnd = TRUE;
847 dprintf_dialog(stddeb, "EndDialog: %04x %d\n", hwnd, retval );
848 return TRUE;
852 /***********************************************************************
853 * IsDialogMessage (USER.90)
855 BOOL IsDialogMessage( HWND hwndDlg, LPMSG16 msg )
857 WND * wndPtr;
858 int dlgCode;
860 if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
861 if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
863 /* Only the key messages get special processing */
864 if ((msg->message != WM_KEYDOWN) &&
865 (msg->message != WM_SYSCHAR) &&
866 (msg->message != WM_CHAR))
867 return FALSE;
869 dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, 0 );
870 if (dlgCode & DLGC_WANTMESSAGE)
872 DispatchMessage( msg );
873 return TRUE;
876 switch(msg->message)
878 case WM_KEYDOWN:
879 if (dlgCode & DLGC_WANTALLKEYS) break;
880 switch(msg->wParam)
882 case VK_TAB:
883 if (!(dlgCode & DLGC_WANTTAB))
885 SendMessage16( hwndDlg, WM_NEXTDLGCTL,
886 (GetKeyState(VK_SHIFT) & 0x8000), 0 );
887 return TRUE;
889 break;
891 case VK_RIGHT:
892 case VK_DOWN:
893 if (!(dlgCode & DLGC_WANTARROWS))
895 SetFocus32( GetNextDlgGroupItem32( hwndDlg, GetFocus32(),
896 FALSE ) );
897 return TRUE;
899 break;
901 case VK_LEFT:
902 case VK_UP:
903 if (!(dlgCode & DLGC_WANTARROWS))
905 SetFocus32( GetNextDlgGroupItem32( hwndDlg, GetFocus32(),
906 TRUE ) );
907 return TRUE;
909 break;
911 case VK_ESCAPE:
912 SendMessage32A( hwndDlg, WM_COMMAND, IDCANCEL,
913 (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
914 break;
916 case VK_RETURN:
918 DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
919 if (HIWORD(dw) == DC_HASDEFID)
920 SendMessage32A( hwndDlg, WM_COMMAND,
921 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
922 (LPARAM)GetDlgItem( hwndDlg, LOWORD(dw) ));
923 else
924 SendMessage32A( hwndDlg, WM_COMMAND, IDOK,
925 (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
927 break;
929 default:
930 TranslateMessage( msg );
932 break; /* case WM_KEYDOWN */
935 case WM_CHAR:
936 if (dlgCode & (DLGC_WANTALLKEYS | DLGC_WANTCHARS)) break;
937 break;
939 case WM_SYSCHAR:
940 if (dlgCode & DLGC_WANTALLKEYS) break;
941 break;
944 /* If we get here, the message has not been treated specially */
945 /* and can be sent to its destination window. */
946 DispatchMessage( msg );
947 return TRUE;
951 /****************************************************************
952 * GetDlgCtrlID (USER.277) (USER32.233)
954 INT16 GetDlgCtrlID( HWND32 hwnd )
956 WND *wndPtr = WIN_FindWndPtr(hwnd);
957 if (wndPtr) return wndPtr->wIDmenu;
958 else return 0;
962 /***********************************************************************
963 * GetDlgItem (USER.91)
965 HWND GetDlgItem( HWND hwndDlg, WORD id )
967 WND *pWnd;
969 if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
970 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
971 if (pWnd->wIDmenu == id) return pWnd->hwndSelf;
972 return 0;
976 /*******************************************************************
977 * SendDlgItemMessage16 (USER.101)
979 LRESULT SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
980 WPARAM16 wParam, LPARAM lParam )
982 HWND16 hwndCtrl = GetDlgItem( hwnd, id );
983 if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
984 else return 0;
988 /*******************************************************************
989 * SendDlgItemMessage32A (USER32.451)
991 LRESULT SendDlgItemMessage32A( HWND32 hwnd, INT32 id, UINT32 msg,
992 WPARAM32 wParam, LPARAM lParam )
994 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
995 if (hwndCtrl) return SendMessage32A( hwndCtrl, msg, wParam, lParam );
996 else return 0;
1000 /*******************************************************************
1001 * SendDlgItemMessage32W (USER32.452)
1003 LRESULT SendDlgItemMessage32W( HWND32 hwnd, INT32 id, UINT32 msg,
1004 WPARAM32 wParam, LPARAM lParam )
1006 HWND hwndCtrl = GetDlgItem( (HWND16)hwnd, (INT16)id );
1007 if (hwndCtrl) return SendMessage32W( hwndCtrl, msg, wParam, lParam );
1008 else return 0;
1012 /*******************************************************************
1013 * SetDlgItemText16 (USER.92)
1015 void SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
1017 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1021 /*******************************************************************
1022 * SetDlgItemText32A (USER32.477)
1024 void SetDlgItemText32A( HWND32 hwnd, INT32 id, LPCSTR lpString )
1026 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1030 /*******************************************************************
1031 * SetDlgItemText32W (USER32.478)
1033 void SetDlgItemText32W( HWND32 hwnd, INT32 id, LPCWSTR lpString )
1035 SendDlgItemMessage32W( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
1039 /***********************************************************************
1040 * GetDlgItemText16 (USER.93)
1042 INT16 GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
1044 return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
1045 len, (LPARAM)str );
1049 /***********************************************************************
1050 * GetDlgItemText32A (USER32.236)
1052 INT32 GetDlgItemText32A( HWND32 hwnd, INT32 id, LPSTR str, UINT32 len )
1054 return (INT32)SendDlgItemMessage32A( hwnd, id, WM_GETTEXT,
1055 len, (LPARAM)str );
1059 /***********************************************************************
1060 * GetDlgItemText32W (USER32.237)
1062 INT32 GetDlgItemText32W( HWND32 hwnd, INT32 id, LPWSTR str, UINT32 len )
1064 return (INT32)SendDlgItemMessage32W( hwnd, id, WM_GETTEXT,
1065 len, (LPARAM)str );
1069 /*******************************************************************
1070 * SetDlgItemInt16 (USER.94)
1072 void SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
1074 char *str = (char *)SEGPTR_ALLOC( 20 * sizeof(char) );
1076 if (!str) return;
1077 if (fSigned) sprintf( str, "%d", (INT32)(INT16)value );
1078 else sprintf( str, "%u", value );
1079 SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)SEGPTR_GET(str) );
1080 SEGPTR_FREE(str);
1084 /*******************************************************************
1085 * SetDlgItemInt32 (USER32.476)
1087 void SetDlgItemInt32( HWND32 hwnd, INT32 id, UINT32 value, BOOL32 fSigned )
1089 char str[20];
1091 if (fSigned) sprintf( str, "%d", (INT32)value );
1092 else sprintf( str, "%u", value );
1093 SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
1097 /***********************************************************************
1098 * GetDlgItemInt (USER.95)
1100 WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
1102 char *str;
1103 long result = 0;
1105 if (translated) *translated = FALSE;
1106 if (!(str = (char *)SEGPTR_ALLOC( 30 * sizeof(char) ))) return 0;
1107 if (SendDlgItemMessage16( hwnd, id, WM_GETTEXT, 30, (LPARAM)SEGPTR_GET(str)))
1109 char * endptr;
1110 result = strtol( str, &endptr, 10 );
1111 if (endptr && (endptr != str)) /* Conversion was successful */
1113 if (fSigned)
1115 if ((result < -32767) || (result > 32767)) result = 0;
1116 else if (translated) *translated = TRUE;
1118 else
1120 if ((result < 0) || (result > 65535)) result = 0;
1121 else if (translated) *translated = TRUE;
1125 SEGPTR_FREE(str);
1126 return (WORD)result;
1130 /***********************************************************************
1131 * CheckDlgButton (USER.97) (USER32.44)
1133 BOOL16 CheckDlgButton( HWND32 hwnd, INT32 id, UINT32 check )
1135 SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
1136 return TRUE;
1140 /***********************************************************************
1141 * IsDlgButtonChecked (USER.98)
1143 WORD IsDlgButtonChecked( HWND hwnd, WORD id )
1145 return (WORD)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
1149 /***********************************************************************
1150 * CheckRadioButton (USER.96) (USER32.47)
1152 BOOL16 CheckRadioButton( HWND32 hwndDlg, UINT32 firstID, UINT32 lastID,
1153 UINT32 checkID )
1155 WND *pWnd = WIN_FindWndPtr( hwndDlg );
1156 if (!pWnd) return FALSE;
1158 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1159 if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) break;
1160 if (!pWnd) return FALSE;
1162 if (pWnd->wIDmenu == lastID)
1163 lastID = firstID; /* Buttons are in reverse order */
1164 while (pWnd)
1166 SendMessage32A( pWnd->hwndSelf, BM_SETCHECK32,
1167 (pWnd->wIDmenu == checkID), 0 );
1168 if (pWnd->wIDmenu == lastID) break;
1169 pWnd = pWnd->next;
1171 return TRUE;
1175 /***********************************************************************
1176 * GetDialogBaseUnits (USER.243)
1178 DWORD GetDialogBaseUnits()
1180 return MAKELONG( xBaseUnit, yBaseUnit );
1184 /***********************************************************************
1185 * MapDialogRect16 (USER.103)
1187 void MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
1189 DIALOGINFO * dlgInfo;
1190 WND * wndPtr = WIN_FindWndPtr( hwnd );
1191 if (!wndPtr) return;
1192 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1193 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1194 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1195 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1196 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1200 /***********************************************************************
1201 * MapDialogRect32 (USER32.381)
1203 void MapDialogRect32( HWND32 hwnd, LPRECT32 rect )
1205 DIALOGINFO * dlgInfo;
1206 WND * wndPtr = WIN_FindWndPtr( hwnd );
1207 if (!wndPtr) return;
1208 dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
1209 rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
1210 rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
1211 rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
1212 rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
1216 /***********************************************************************
1217 * GetNextDlgGroupItem16 (USER.227)
1219 HWND16 GetNextDlgGroupItem16(HWND16 hwndDlg, HWND16 hwndCtrl, BOOL16 fPrevious)
1221 return (HWND16)GetNextDlgGroupItem32( hwndDlg, hwndCtrl, fPrevious );
1225 /***********************************************************************
1226 * GetNextDlgGroupItem32 (USER32.274)
1228 HWND32 GetNextDlgGroupItem32(HWND32 hwndDlg, HWND32 hwndCtrl, BOOL32 fPrevious)
1230 WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1232 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1233 if (hwndCtrl)
1235 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1236 /* Make sure hwndCtrl is a top-level child */
1237 while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1238 pWndCtrl = pWndCtrl->parent;
1239 if (pWndCtrl->parent != pWndDlg) return 0;
1241 else
1243 /* No ctrl specified -> start from the beginning */
1244 if (!(pWndCtrl = pWndDlg->child)) return 0;
1245 if (fPrevious) while (pWndCtrl->next) pWndCtrl = pWndCtrl->next;
1248 pWndLast = pWndCtrl;
1249 pWnd = pWndCtrl->next;
1250 while (1)
1252 if (!pWnd || (pWnd->dwStyle & WS_GROUP))
1254 /* Wrap-around to the beginning of the group */
1255 WND *pWndStart = pWndDlg->child;
1256 for (pWnd = pWndStart; pWnd; pWnd = pWnd->next)
1258 if (pWnd->dwStyle & WS_GROUP) pWndStart = pWnd;
1259 if (pWnd == pWndCtrl) break;
1261 pWnd = pWndStart;
1263 if (pWnd == pWndCtrl) break;
1264 if ((pWnd->dwStyle & WS_VISIBLE) && !(pWnd->dwStyle & WS_DISABLED))
1266 pWndLast = pWnd;
1267 if (!fPrevious) break;
1269 pWnd = pWnd->next;
1271 return pWndLast->hwndSelf;
1275 /***********************************************************************
1276 * GetNextDlgTabItem16 (USER.228)
1278 HWND16 GetNextDlgTabItem16( HWND16 hwndDlg, HWND16 hwndCtrl, BOOL16 fPrevious )
1280 return (HWND16)GetNextDlgTabItem32( hwndDlg, hwndCtrl, fPrevious );
1284 /***********************************************************************
1285 * GetNextDlgTabItem32 (USER32.275)
1287 HWND32 GetNextDlgTabItem32( HWND32 hwndDlg, HWND32 hwndCtrl, BOOL32 fPrevious )
1289 WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
1291 if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
1292 if (hwndCtrl)
1294 if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl ))) return 0;
1295 /* Make sure hwndCtrl is a top-level child */
1296 while ((pWndCtrl->dwStyle & WS_CHILD) && (pWndCtrl->parent != pWndDlg))
1297 pWndCtrl = pWndCtrl->parent;
1298 if (pWndCtrl->parent != pWndDlg) return 0;
1300 else
1302 /* No ctrl specified -> start from the beginning */
1303 if (!(pWndCtrl = pWndDlg->child)) return 0;
1304 if (fPrevious) while (pWndCtrl->next) pWndCtrl = pWndCtrl->next;
1307 pWndLast = pWndCtrl;
1308 pWnd = pWndCtrl->next;
1309 while (1)
1311 if (!pWnd) pWnd = pWndDlg->child;
1312 if (pWnd == pWndCtrl) break;
1313 if ((pWnd->dwStyle & WS_TABSTOP) && (pWnd->dwStyle & WS_VISIBLE) &&
1314 !(pWnd->dwStyle & WS_DISABLED))
1316 pWndLast = pWnd;
1317 if (!fPrevious) break;
1319 pWnd = pWnd->next;
1321 return pWndLast->hwndSelf;