source: trunk/src/user32/win32dlg.cpp@ 1111

Last change on this file since 1111 was 1063, checked in by sandervl, 26 years ago

Dialog + error handling fixes

File size: 31.7 KB
Line 
1/* $Id: win32dlg.cpp,v 1.5 1999-09-26 14:44:58 sandervl Exp $ */
2/*
3 * Win32 Dialog Code for OS/2
4 *
5 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl) (Wine port & OS/2 adaption)
6 *
7 * Based on Wine code (990815; windows\dialog.c)
8 *
9 * Copyright 1993, 1994, 1996 Alexandre Julliard
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#include <os2win.h>
15#include <windowsx.h>
16#include <stdlib.h>
17#include <string.h>
18#include <misc.h>
19#include <win32dlg.h>
20#include "oslibmsg.h"
21
22#define DEFAULT_DLGFONT "9.WarpSans"
23
24//******************************************************************************
25//******************************************************************************
26Win32Dialog::Win32Dialog(HINSTANCE hInst, LPCSTR dlgTemplate, HWND owner,
27 DLGPROC dlgProc, LPARAM param, BOOL isUnicode)
28 : Win32BaseWindow(OBJTYPE_DIALOG)
29{
30 RECT rect;
31 WORD style;
32 ATOM classAtom;
33
34 this->isUnicode = isUnicode;
35 hUserFont = 0;
36 hMenu = 0;
37 hwndFocus = 0;
38 Win32DlgProc = 0;
39 msgResult = 0;
40 userDlgData = 0;
41 idResult = 0;
42 dialogFlags = 0;
43 memset(&dlgInfo, 0, sizeof(dlgInfo));
44
45 dprintf(("********* CREATE DIALOG ************"));
46 if(fInitialized == FALSE) {
47 if(DIALOG_Init() == FALSE) {
48 dprintf(("DIALOG_Init FAILED!"));
49 DebugInt3();
50 SetLastError(ERROR_GEN_FAILURE);
51 return;
52 }
53 fInitialized = TRUE;
54 }
55 xUnit = xBaseUnit;
56 yUnit = yBaseUnit;
57
58 /* Parse dialog template */
59 dlgTemplate = parseTemplate(dlgTemplate, &dlgInfo);
60
61 /* Load menu */
62 if (dlgInfo.menuName)
63 {
64 hMenu = LoadMenuW( hInst, (LPCWSTR)dlgInfo.menuName );
65 }
66
67 /* Create custom font if needed */
68 if (dlgInfo.style & DS_SETFONT)
69 {
70 /* The font height must be negative as it is a point size */
71 /* (see CreateFont() documentation in the Windows SDK). */
72 hUserFont = CreateFontW(dlgInfo.pointSize*2, 0, 0, 0,
73 dlgInfo.weight, dlgInfo.italic, FALSE,
74 FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY,
75 FF_DONTCARE, (LPCWSTR)dlgInfo.faceName );
76 if (hUserFont)
77 {
78 SIZE charSize;
79 getCharSize(hUserFont,&charSize);
80 xBaseUnit = charSize.cx;
81 yBaseUnit = charSize.cy;
82 }
83 }
84
85 /* Create dialog main window */
86 rect.left = rect.top = 0;
87 rect.right = dlgInfo.cx * xUnit / 4;
88 rect.bottom = dlgInfo.cy * yUnit / 8;
89 if (dlgInfo.style & DS_MODALFRAME)
90 dlgInfo.exStyle |= WS_EX_DLGMODALFRAME;
91
92 AdjustWindowRectEx( &rect, dlgInfo.style, hMenu ? TRUE : FALSE , dlgInfo.exStyle );
93 rect.right -= rect.left;
94 rect.bottom -= rect.top;
95
96 if ((INT16)dlgInfo.x == CW_USEDEFAULT16)
97 {
98 rect.left = rect.top = CW_USEDEFAULT;
99 }
100 else
101 {
102 if (dlgInfo.style & DS_CENTER)
103 {
104 rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
105 rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
106 }
107 else
108 {
109 rect.left += dlgInfo.x * xUnit / 4;
110 rect.top += dlgInfo.y * yUnit / 8;
111 }
112 if ( !(dlgInfo.style & WS_CHILD) )
113 {
114 INT dX, dY;
115
116 if( !(dlgInfo.style & DS_ABSALIGN) )
117 ClientToScreen(owner, (POINT *)&rect );
118
119 /* try to fit it into the desktop */
120
121 if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
122 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
123 if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
124 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
125 if( rect.left < 0 ) rect.left = 0;
126 if( rect.top < 0 ) rect.top = 0;
127 }
128 }
129
130 /* Create the dialog window */
131
132 /* Find the class atom */
133 if (!HIWORD(dlgInfo.className))
134 {
135 classAtom = (ATOM)LOWORD(dlgInfo.className);
136 }
137 else
138 if(!(classAtom = GlobalFindAtomW((LPWSTR)dlgInfo.className)))
139 {
140 SetLastError(ERROR_INVALID_PARAMETER);
141 return;
142 }
143 CREATESTRUCTA cs;
144 cs.lpCreateParams = NULL;
145 cs.hInstance = hInst;
146 cs.hMenu = hMenu;
147 cs.hwndParent = owner;
148 cs.x = rect.left;
149 cs.y = rect.top;
150 cs.cx = rect.right;
151 cs.cy = rect.bottom;
152 cs.style = dlgInfo.style & ~WS_VISIBLE;
153 if(!isUnicode) {
154 if(dlgInfo.caption) {
155 cs.lpszName = UnicodeToAsciiString((LPWSTR)dlgInfo.caption);
156 }
157 else cs.lpszName = 0;
158 if(HIWORD(cs.lpszClass)) {
159 cs.lpszClass = UnicodeToAsciiString((LPWSTR)dlgInfo.className);
160 }
161 else cs.lpszClass = dlgInfo.className;
162 }
163 else {
164 cs.lpszName = dlgInfo.caption;
165 cs.lpszClass = dlgInfo.className;
166 }
167 cs.dwExStyle = dlgInfo.exStyle;
168
169 fIsDialog = TRUE;
170 CreateWindowExA(&cs, classAtom);
171
172 if(!isUnicode) {
173 if(cs.lpszName) FreeAsciiString((LPSTR)cs.lpszName);
174 if(HIWORD(cs.lpszClass)) {
175 FreeAsciiString((LPSTR)cs.lpszClass);
176 }
177 }
178
179 if (!getWindowHandle())
180 {
181 if (hUserFont) DeleteObject( hUserFont );
182 if (hMenu) DestroyMenu( hMenu );
183 return;
184 }
185
186//TODO:
187// wndPtr->helpContext = helpId;
188 Win32DlgProc = dlgProc;
189
190 if (hUserFont)
191 SendMessageA(WM_SETFONT, (WPARAM)hUserFont, 0 );
192
193 /* Create controls */
194 if (createControls(dlgTemplate, hInst))
195 {
196 /* Send initialisation messages and set focus */
197 hwndFocus = GetNextDlgTabItem( getWindowHandle(), 0, FALSE );
198
199 if (SendMessageA(WM_INITDIALOG, (WPARAM)hwndFocus, param ))
200 SetFocus(hwndFocus);
201
202 if (dlgInfo.style & WS_VISIBLE && !(getStyle() & WS_VISIBLE))
203 {
204 ShowWindow( SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
205 ::UpdateWindow( getWindowHandle() );
206 }
207 dprintf(("********* DIALOG CREATED ************"));
208 return;
209 }
210 DestroyWindow();
211}
212//******************************************************************************
213//******************************************************************************
214Win32Dialog::~Win32Dialog()
215{
216 if (hUserFont) DeleteObject( hUserFont );
217 if (hMenu) DestroyMenu( hMenu );
218
219}
220/***********************************************************************
221 * DIALOG_DoDialogBox
222 */
223INT Win32Dialog::doDialogBox()
224{
225 Win32BaseWindow *topOwner;
226 MSG msg;
227 INT retval;
228
229 /* Owner must be a top-level window */
230 if(getOwner() == NULL) {
231 dprintf(("Dialog box has no owner!!!"));
232 return -1;
233 }
234 topOwner = getOwner()->getTopParent();
235 if(topOwner == NULL) {
236 dprintf(("Dialog box has no top owner!!!"));
237 return -1;
238 }
239
240 if (!dialogFlags & DF_END) /* was EndDialog called in WM_INITDIALOG ? */
241 {
242 topOwner->EnableWindow( FALSE );
243 ShowWindow( SW_SHOW );
244
245 while (TRUE) {
246// while (OSLibWinPeekMsg(&msg, getWindowHandle(), owner, MSGF_DIALOGBOX,
247// MSG_REMOVE, !(getStyle() & DS_NOIDLEMSG), NULL ))
248// if(OSLibWinPeekMsg(&msg, topOwner->getOS2FrameWindowHandle(), 0, 0, MSG_REMOVE))
249 if(OSLibWinPeekMsg(&msg, 0, 0, 0, MSG_REMOVE))
250 {
251 if(msg.message == WM_QUIT) {
252 dprintf(("Win32Dialog::doDialogBox: received WM_QUIT"));
253 break;
254 }
255 if (!IsDialogMessageA( getWindowHandle(), &msg))
256 {
257 TranslateMessage( &msg );
258 DispatchMessageA( &msg );
259 }
260 if (dialogFlags & DF_END) break;
261 }
262 else {
263 if(!(getStyle() & DS_NOIDLEMSG)) {
264 topOwner->SendMessageA(WM_ENTERIDLE, MSGF_DIALOGBOX, getWindowHandle());
265 }
266 }
267 }
268 topOwner->EnableWindow( TRUE );
269 }
270 retval = idResult;
271 DestroyWindow();
272 return retval;
273}
274/***********************************************************************
275 * DIALOG_Init
276 *
277 * Initialisation of the dialog manager.
278 */
279BOOL Win32Dialog::DIALOG_Init(void)
280{
281 HDC hdc;
282 SIZE size;
283
284 /* Calculate the dialog base units */
285 if (!(hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
286 if (!getCharSizeFromDC( hdc, 0, &size )) return FALSE;
287 DeleteDC( hdc );
288 xBaseUnit = size.cx;
289 yBaseUnit = size.cy;
290
291 return TRUE;
292}
293/***********************************************************************
294 * DIALOG_GetCharSizeFromDC
295 *
296 *
297 * Calculates the *true* average size of English characters in the
298 * specified font as oppposed to the one returned by GetTextMetrics.
299 */
300BOOL Win32Dialog::getCharSizeFromDC( HDC hDC, HFONT hUserFont, SIZE * pSize )
301{
302 BOOL Success = FALSE;
303 HFONT hUserFontPrev = 0;
304 pSize->cx = xBaseUnit;
305 pSize->cy = yBaseUnit;
306
307 if ( hDC )
308 {
309 /* select the font */
310 TEXTMETRICA tm;
311 memset(&tm,0,sizeof(tm));
312 if (hUserFont) hUserFontPrev = SelectFont(hDC,hUserFont);
313 if (GetTextMetricsA(hDC,&tm))
314 {
315 pSize->cx = tm.tmAveCharWidth;
316 pSize->cy = tm.tmHeight;
317
318 /* if variable width font */
319 if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
320 {
321 SIZE total;
322 static const char szAvgChars[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
323
324 /* Calculate a true average as opposed to the one returned
325 * by tmAveCharWidth. This works better when dealing with
326 * proportional spaced fonts and (more important) that's
327 * how Microsoft's dialog creation code calculates the size
328 * of the font
329 */
330 if (GetTextExtentPointA(hDC,szAvgChars,sizeof(szAvgChars),&total))
331 {
332 /* round up */
333 pSize->cx = ((2*total.cx/sizeof(szAvgChars)) + 1)/2;
334 Success = TRUE;
335 }
336 }
337 else
338 {
339 Success = TRUE;
340 }
341 }
342
343 /* select the original font */
344 if (hUserFontPrev) SelectFont(hDC,hUserFontPrev);
345 }
346 return (Success);
347}
348/***********************************************************************
349 * DIALOG_GetCharSize
350 *
351 *
352 * Calculates the *true* average size of English characters in the
353 * specified font as oppposed to the one returned by GetTextMetrics.
354 * A convenient variant of DIALOG_GetCharSizeFromDC.
355 */
356BOOL Win32Dialog::getCharSize( HFONT hUserFont, SIZE * pSize )
357{
358 HDC hDC = GetDC(0);
359 BOOL Success = getCharSizeFromDC( hDC, hUserFont, pSize );
360 ReleaseDC(0, hDC);
361 return Success;
362}
363/***********************************************************************
364 * DIALOG_ParseTemplate32
365 *
366 * Fill a DLG_TEMPLATE structure from the dialog template, and return
367 * a pointer to the first control.
368 */
369LPCSTR Win32Dialog::parseTemplate( LPCSTR dlgtemplate, DLG_TEMPLATE * result )
370{
371 const WORD *p = (const WORD *)dlgtemplate;
372
373 result->style = GET_DWORD(p); p += 2;
374 if (result->style == 0xffff0001) /* DIALOGEX resource */
375 {
376 result->dialogEx = TRUE;
377 result->helpId = GET_DWORD(p); p += 2;
378 result->exStyle = GET_DWORD(p); p += 2;
379 result->style = GET_DWORD(p); p += 2;
380 }
381 else
382 {
383 result->dialogEx = FALSE;
384 result->helpId = 0;
385 result->exStyle = GET_DWORD(p); p += 2;
386 }
387 result->nbItems = GET_WORD(p); p++;
388 result->x = GET_WORD(p); p++;
389 result->y = GET_WORD(p); p++;
390 result->cx = GET_WORD(p); p++;
391 result->cy = GET_WORD(p); p++;
392
393 /* Get the menu name */
394
395 switch(GET_WORD(p))
396 {
397 case 0x0000:
398 result->menuName = NULL;
399 p++;
400 break;
401 case 0xffff:
402 result->menuName = (LPCSTR)(UINT)GET_WORD( p + 1 );
403 p += 2;
404 break;
405 default:
406 result->menuName = (LPCSTR)p;
407 p += lstrlenW( (LPCWSTR)p ) + 1;
408 break;
409 }
410
411 /* Get the class name */
412 switch(GET_WORD(p))
413 {
414 case 0x0000:
415 result->className = (LPCSTR)DIALOG_CLASS_NAMEW;
416 p++;
417 break;
418 case 0xffff:
419 result->className = (LPCSTR)(UINT)GET_WORD( p + 1 );
420 p += 2;
421 break;
422 default:
423 result->className = (LPCSTR)p;
424 p += lstrlenW( (LPCWSTR)p ) + 1;
425 break;
426 }
427
428 /* Get the window caption */
429
430 result->caption = (LPCSTR)p;
431 p += lstrlenW( (LPCWSTR)p ) + 1;
432
433 /* Get the font name */
434
435 if (result->style & DS_SETFONT)
436 {
437 result->pointSize = GET_WORD(p);
438 p++;
439 if (result->dialogEx)
440 {
441 result->weight = GET_WORD(p); p++;
442 result->italic = LOBYTE(GET_WORD(p)); p++;
443 }
444 else
445 {
446 result->weight = FW_DONTCARE;
447 result->italic = FALSE;
448 }
449 result->faceName = (LPCSTR)p;
450 p += lstrlenW( (LPCWSTR)p ) + 1;
451 }
452
453 /* First control is on dword boundary */
454 return (LPCSTR)((((int)p) + 3) & ~3);
455}
456/***********************************************************************
457 * DIALOG_GetControl32
458 *
459 * Return the class and text of the control pointed to by ptr,
460 * fill the header structure and return a pointer to the next control.
461 */
462WORD *Win32Dialog::getControl(const WORD *p, DLG_CONTROL_INFO *info, BOOL dialogEx)
463{
464 if (dialogEx)
465 {
466 info->helpId = GET_DWORD(p); p += 2;
467 info->exStyle = GET_DWORD(p); p += 2;
468 info->style = GET_DWORD(p); p += 2;
469 }
470 else
471 {
472 info->helpId = 0;
473 info->style = GET_DWORD(p); p += 2;
474 info->exStyle = GET_DWORD(p); p += 2;
475 }
476 info->x = GET_WORD(p); p++;
477 info->y = GET_WORD(p); p++;
478 info->cx = GET_WORD(p); p++;
479 info->cy = GET_WORD(p); p++;
480
481 if (dialogEx)
482 {
483 /* id is a DWORD for DIALOGEX */
484 info->id = GET_DWORD(p);
485 p += 2;
486 }
487 else
488 {
489 info->id = GET_WORD(p);
490 p++;
491 }
492
493 if (GET_WORD(p) == 0xffff)
494 {
495 static const WCHAR class_names[6][10] =
496 {
497 { 'B','u','t','t','o','n', }, /* 0x80 */
498 { 'E','d','i','t', }, /* 0x81 */
499 { 'S','t','a','t','i','c', }, /* 0x82 */
500 { 'L','i','s','t','B','o','x', }, /* 0x83 */
501 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
502 { 'C','o','m','b','o','B','o','x', } /* 0x85 */
503 };
504 WORD id = GET_WORD(p+1);
505 if ((id >= 0x80) && (id <= 0x85))
506 info->className = (LPCSTR)class_names[id - 0x80];
507 else
508 {
509 info->className = NULL;
510 dprintf(("Unknown built-in class id %04x\n", id ));
511 }
512 p += 2;
513 }
514 else
515 {
516 info->className = (LPCSTR)p;
517 p += lstrlenW( (LPCWSTR)p ) + 1;
518 }
519
520 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
521 {
522 info->windowName = (LPCSTR)(UINT)GET_WORD(p + 1);
523 p += 2;
524 }
525 else
526 {
527 info->windowName = (LPCSTR)p;
528 p += lstrlenW( (LPCWSTR)p ) + 1;
529 }
530
531 if (GET_WORD(p))
532 {
533 info->data = (LPVOID)(p + 1);
534 p += GET_WORD(p) / sizeof(WORD);
535 }
536 else info->data = NULL;
537 p++;
538
539 /* Next control is on dword boundary */
540 return (WORD *)((((int)p) + 3) & ~3);
541}
542
543
544/***********************************************************************
545 * DIALOG_CreateControls
546 *
547 * Create the control windows for a dialog.
548 */
549BOOL Win32Dialog::createControls(LPCSTR dlgtemplate, HINSTANCE hInst)
550{
551 DLG_CONTROL_INFO info;
552 HWND hwndCtrl, hwndDefButton = 0;
553 INT items = dlgInfo.nbItems;
554
555 while (items--)
556 {
557 dlgtemplate = (LPCSTR)getControl( (WORD *)dlgtemplate, &info, dlgInfo.dialogEx );
558
559 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
560 (LPCWSTR)info.className,
561 (LPCWSTR)info.windowName,
562 info.style | WS_CHILD,
563 info.x * xUnit / 4,
564 info.y * yUnit / 8,
565 info.cx * xUnit / 4,
566 info.cy * yUnit / 8,
567 getWindowHandle(), (HMENU)info.id,
568 hInst, info.data );
569
570 if (!hwndCtrl) return FALSE;
571
572 /* Send initialisation messages to the control */
573 if (hUserFont) ::SendMessageA( hwndCtrl, WM_SETFONT, (WPARAM)hUserFont, 0 );
574
575 if (::SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
576 {
577 /* If there's already a default push-button, set it back */
578 /* to normal and use this one instead. */
579 if (hwndDefButton)
580 ::SendMessageA( hwndDefButton, BM_SETSTYLE,
581 BS_PUSHBUTTON,FALSE );
582 hwndDefButton = hwndCtrl;
583 idResult = ::GetWindowWord( hwndCtrl, GWW_ID );
584 }
585 }
586 return TRUE;
587}
588/***********************************************************************
589 * DEFDLG_Proc
590 *
591 * Implementation of DefDlgProc(). Only handle messages that need special
592 * handling for dialogs.
593 */
594LRESULT Win32Dialog::DefDlg_Proc(UINT msg, WPARAM wParam, LPARAM lParam)
595{
596 switch(msg)
597 {
598 case WM_ERASEBKGND:
599 {
600 RECT rect;
601 int rc;
602 /* Since WM_ERASEBKGND may receive either a window dc or a */
603 /* client dc, the area to be erased has to be retrieved from */
604 /* the device context. */
605 rc = GetClipBox( (HDC)wParam, &rect );
606 if ((rc == SIMPLEREGION) || (rc == COMPLEXREGION))
607 FillRect( (HDC)wParam, &rect, windowClass->getBackgroundBrush());
608 return 1;
609 }
610 case WM_NCDESTROY:
611 /* Free dialog heap (if created) */
612#if 0
613 if (dlgInfo->hDialogHeap)
614 {
615 GlobalUnlock16(dlgInfo->hDialogHeap);
616 GlobalFree16(dlgInfo->hDialogHeap);
617 dlgInfo->hDialogHeap = 0;
618 }
619#endif
620 /* Delete font */
621 if (hUserFont)
622 {
623 DeleteObject( hUserFont );
624 hUserFont = 0;
625 }
626
627 /* Delete menu */
628 if (hMenu)
629 {
630 DestroyMenu( hMenu );
631 hMenu = 0;
632 }
633
634 /* Delete window procedure */
635 Win32DlgProc = 0;
636 dialogFlags |= DF_END; /* just in case */
637
638 /* Window clean-up */
639 return DefWindowProcA(msg, wParam, lParam );
640
641 case WM_SHOWWINDOW:
642 if (!wParam) saveFocus();
643 return DefWindowProcA(msg, wParam, lParam );
644
645 case WM_ACTIVATE:
646 if (wParam) {
647 restoreFocus();
648 }
649 else saveFocus();
650 return 0;
651
652 case WM_SETFOCUS:
653 restoreFocus();
654 return 0;
655
656 case DM_SETDEFID:
657 if (dialogFlags & DF_END)
658 return 1;
659
660 setDefButton(wParam ? GetDlgItem( getWindowHandle(), wParam ) : 0 );
661 return 1;
662
663 case DM_GETDEFID:
664 {
665 HWND hwndDefId;
666 if (dialogFlags & DF_END) return 0;
667 if (idResult)
668 return MAKELONG( idResult, DC_HASDEFID );
669 if ((hwndDefId = findDefButton()))
670 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
671
672 return 0;
673 }
674
675 case WM_NEXTDLGCTL:
676 {
677 HWND hwndDest = (HWND)wParam;
678 if (!lParam)
679 hwndDest = GetNextDlgTabItem(getWindowHandle(), GetFocus(), wParam);
680 if (hwndDest) setFocus( hwndDest );
681 setDefButton( hwndDest );
682 return 0;
683 }
684
685 case WM_ENTERMENULOOP:
686 case WM_LBUTTONDOWN:
687 case WM_NCLBUTTONDOWN:
688 {
689 HWND hwndCurFocus = GetFocus();
690 if (hwndCurFocus)
691 {
692#if 0
693 WND *wnd = WIN_FindWndPtr( hwndFocus );
694
695 if( wnd )
696 {
697 /* always make combo box hide its listbox control */
698 if( WIDGETS_IsControl( wnd, BIC32_COMBO ) )
699 SendMessageA( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 );
700 else
701 if( WIDGETS_IsControl( wnd, BIC32_EDIT ) &&
702 WIDGETS_IsControl( wnd->parent, BIC32_COMBO ))
703 SendMessageA(CB_SHOWDROPDOWN, FALSE, 0 );
704 }
705#endif
706 }
707 return DefWindowProcA( msg, wParam, lParam );
708 }
709
710 case WM_GETFONT:
711 return hUserFont;
712
713 case WM_CLOSE:
714 PostMessageA(WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( getWindowHandle(), IDCANCEL ) );
715 return 0;
716
717 case WM_NOTIFYFORMAT:
718 return DefWindowProcA(msg, wParam, lParam );
719 }
720 return 0;
721}
722//******************************************************************************
723//******************************************************************************
724LRESULT Win32Dialog::DefDlgProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
725{
726 BOOL result = FALSE;
727
728 msgResult = 0;
729
730 if (Win32DlgProc) { /* Call dialog procedure */
731 result = Win32DlgProc(getWindowHandle(), Msg, wParam, lParam);
732 }
733
734 if (!result && IsWindow())
735 {
736 /* callback didn't process this message */
737 switch(Msg)
738 {
739 case WM_ERASEBKGND:
740 case WM_SHOWWINDOW:
741 case WM_ACTIVATE:
742 case WM_SETFOCUS:
743 case DM_SETDEFID:
744 case DM_GETDEFID:
745 case WM_NEXTDLGCTL:
746 case WM_GETFONT:
747 case WM_CLOSE:
748 case WM_NCDESTROY:
749 case WM_ENTERMENULOOP:
750 case WM_LBUTTONDOWN:
751 case WM_NCLBUTTONDOWN:
752 return DefDlg_Proc(Msg, (WPARAM)wParam, lParam);
753
754 case WM_INITDIALOG:
755 case WM_VKEYTOITEM:
756 case WM_COMPAREITEM:
757 case WM_CHARTOITEM:
758 break;
759
760 default:
761 return DefWindowProcA(Msg, wParam, lParam );
762 }
763 }
764 return DefDlg_Epilog(Msg, result);
765}
766//******************************************************************************
767//******************************************************************************
768LRESULT Win32Dialog::DefDlgProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
769{
770 BOOL result = FALSE;
771
772 msgResult = 0;
773
774 if (Win32DlgProc) { /* Call dialog procedure */
775 result = Win32DlgProc(getWindowHandle(), Msg, wParam, lParam);
776 }
777
778 if (!result && IsWindow())
779 {
780 /* callback didn't process this message */
781 switch(Msg)
782 {
783 case WM_ERASEBKGND:
784 case WM_SHOWWINDOW:
785 case WM_ACTIVATE:
786 case WM_SETFOCUS:
787 case DM_SETDEFID:
788 case DM_GETDEFID:
789 case WM_NEXTDLGCTL:
790 case WM_GETFONT:
791 case WM_CLOSE:
792 case WM_NCDESTROY:
793 case WM_ENTERMENULOOP:
794 case WM_LBUTTONDOWN:
795 case WM_NCLBUTTONDOWN:
796 return DefDlg_Proc(Msg, (WPARAM)wParam, lParam);
797
798 case WM_INITDIALOG:
799 case WM_VKEYTOITEM:
800 case WM_COMPAREITEM:
801 case WM_CHARTOITEM:
802 break;
803
804 default:
805 return DefWindowProcW(Msg, wParam, lParam );
806 }
807 }
808 return DefDlg_Epilog(Msg, result);
809}
810/***********************************************************************
811 * DEFDLG_Epilog
812 */
813LRESULT Win32Dialog::DefDlg_Epilog(UINT msg, BOOL fResult)
814{
815 /* see SDK 3.1 */
816 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
817 msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
818 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
819 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
820 return fResult;
821
822 return msgResult;
823}
824/***********************************************************************
825 * DEFDLG_SetFocus
826 *
827 * Set the focus to a control of the dialog, selecting the text if
828 * the control is an edit dialog.
829 */
830void Win32Dialog::setFocus(HWND hwndCtrl )
831{
832 HWND hwndPrev = GetFocus();
833
834 if (IsChild( hwndPrev ))
835 {
836 if (::SendMessageA( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
837 ::SendMessageA( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
838 }
839 if (::SendMessageA(hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
840 ::SendMessageA(hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
841 SetFocus( hwndCtrl );
842}
843
844
845/***********************************************************************
846 * DEFDLG_SaveFocus
847 */
848BOOL Win32Dialog::saveFocus()
849{
850 HWND hwndCurrentFocus = GetFocus();
851
852 if (!hwndCurrentFocus || !IsChild( hwndCurrentFocus )) return FALSE;
853
854 hwndFocus = hwndCurrentFocus;
855 /* Remove default button */
856 return TRUE;
857}
858
859
860/***********************************************************************
861 * DEFDLG_RestoreFocus
862 */
863BOOL Win32Dialog::restoreFocus()
864{
865 if (!hwndFocus || IsIconic()) return FALSE;
866
867 if (!::IsWindow( hwndFocus )) return FALSE;
868
869 /* Don't set the focus back to controls if EndDialog is already called.*/
870 if (!(dialogFlags & DF_END))
871 setFocus(hwndFocus);
872
873 /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
874 sometimes losing focus when receiving WM_SETFOCUS messages. */
875 return TRUE;
876}
877
878
879/***********************************************************************
880 * DEFDLG_FindDefButton
881 *
882 * Find the current default push-button.
883 */
884HWND Win32Dialog::findDefButton()
885{
886 HWND hwndChild = GetWindow( GW_CHILD );
887 while (hwndChild)
888 {
889 if (::SendMessageA( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
890 break;
891 hwndChild = ::GetWindow( hwndChild, GW_HWNDNEXT );
892 }
893 return hwndChild;
894}
895
896
897/***********************************************************************
898 * DEFDLG_SetDefButton
899 *
900 * Set the new default button to be hwndNew.
901 */
902BOOL Win32Dialog::setDefButton(HWND hwndNew )
903{
904 if (hwndNew &&
905 !(::SendMessageA(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
906 return FALSE; /* Destination is not a push button */
907
908 if (idResult) /* There's already a default pushbutton */
909 {
910 HWND hwndOld = GetDlgItem( getWindowHandle(), idResult );
911 if (::SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
912 ::SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
913 }
914 if (hwndNew)
915 {
916 ::SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
917 idResult = GetDlgCtrlID( hwndNew );
918 }
919 else idResult = 0;
920 return TRUE;
921}
922//******************************************************************************
923// GetNextDlgTabItem32 (USER32.276)
924//******************************************************************************
925HWND Win32Dialog::getNextDlgTabItem(HWND hwndCtrl, BOOL fPrevious)
926{
927 Win32BaseWindow *child, *nextchild, *lastchild;
928 HWND retvalue;
929
930 if (hwndCtrl)
931 {
932 child = GetWindowFromHandle(hwndCtrl);
933 if (!child)
934 {
935 retvalue = 0;
936 goto END;
937 }
938 /* Make sure hwndCtrl is a top-level child */
939 while ((child->getStyle() & WS_CHILD) && (child->getParent() != this))
940 {
941 child = child->getParent();
942 if(child == NULL) break;
943 }
944
945 if (!child || child->getParent() != this)
946 {
947 retvalue = 0;
948 goto END;
949 }
950 }
951 else
952 {
953 /* No ctrl specified -> start from the beginning */
954 child = (Win32BaseWindow *)getFirstChild();
955 if (!child)
956 {
957 retvalue = 0;
958 goto END;
959 }
960
961 if (!fPrevious)
962 {
963 while (child->getNextChild())
964 {
965 child = (Win32BaseWindow *)child->getNextChild();
966 }
967 }
968 }
969
970 lastchild = child;
971 nextchild = (Win32BaseWindow *)child->getNextChild();
972 while (TRUE)
973 {
974 if (!nextchild) nextchild = (Win32BaseWindow *)getFirstChild();
975
976 if (child == nextchild) break;
977
978 if ((nextchild->getStyle() & WS_TABSTOP) && (nextchild->getStyle() & WS_VISIBLE) &&
979 !(nextchild->getStyle() & WS_DISABLED))
980 {
981 lastchild = nextchild;
982 if (!fPrevious) break;
983 }
984 nextchild = (Win32BaseWindow *)nextchild->getNextChild();
985 }
986 retvalue = lastchild->getWindowHandle();
987
988END:
989 return retvalue;
990}
991//******************************************************************************
992//******************************************************************************
993Win32BaseWindow *Win32Dialog::getDlgItem(int id)
994{
995 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
996 {
997 if (child->getWindowId() == id)
998 {
999 return child;
1000 }
1001 }
1002 return 0;
1003}
1004//******************************************************************************
1005//******************************************************************************
1006BOOL Win32Dialog::endDialog(int retval)
1007{
1008 dialogFlags |= DF_END;
1009 idResult = retval;
1010 return TRUE;
1011}
1012//******************************************************************************
1013//******************************************************************************
1014ULONG Win32Dialog::MsgOS2Create(HWND hwndOS2, ULONG initParam)
1015{
1016 OS2Hwnd = hwndOS2;
1017 return win32wndproc(Win32Hwnd, WM_CREATE, 0, initParam);
1018}
1019//******************************************************************************
1020//******************************************************************************
1021LONG Win32Dialog::SetWindowLongA(int index, ULONG value)
1022{
1023 LONG oldval;
1024
1025 switch(index)
1026 {
1027 case DWL_DLGPROC:
1028 oldval = (LONG)Win32DlgProc;
1029 Win32DlgProc = (DLGPROC)index;
1030 return oldval;
1031 case DWL_MSGRESULT:
1032 oldval = msgResult;
1033 msgResult = value;
1034 return oldval;
1035 case DWL_USER:
1036 oldval = userDlgData;
1037 userDlgData = value;
1038 return oldval;
1039 default:
1040 return Win32BaseWindow::SetWindowLongA(index, value);
1041 }
1042}
1043//******************************************************************************
1044//******************************************************************************
1045ULONG Win32Dialog::GetWindowLongA(int index)
1046{
1047 switch(index)
1048 {
1049 case DWL_DLGPROC:
1050 return (ULONG)Win32DlgProc;
1051 case DWL_MSGRESULT:
1052 return msgResult;
1053 case DWL_USER:
1054 return userDlgData;
1055 default:
1056 return Win32BaseWindow::GetWindowLongA(index);
1057 }
1058}
1059//******************************************************************************
1060//******************************************************************************
1061BOOL DIALOG_Register()
1062{
1063 WNDCLASSA wndClass;
1064
1065 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1066 wndClass.style = CS_GLOBALCLASS | CS_SAVEBITS;
1067 wndClass.lpfnWndProc = (WNDPROC)DefDlgProcA;
1068 wndClass.cbClsExtra = 0;
1069 wndClass.cbWndExtra = 0;
1070 wndClass.hCursor = (HCURSOR)IDC_ARROWA;
1071 wndClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
1072 wndClass.lpszClassName = DIALOG_CLASS_NAMEA;
1073
1074 return RegisterClassA(&wndClass);
1075}
1076//******************************************************************************
1077//******************************************************************************
1078BOOL DIALOG_Unregister()
1079{
1080 if (GlobalFindAtomA(DIALOG_CLASS_NAMEA))
1081 return UnregisterClassA(DIALOG_CLASS_NAMEA,(HINSTANCE)NULL);
1082 else return FALSE;
1083}
1084//******************************************************************************
1085//******************************************************************************
1086BOOL Win32Dialog::fInitialized = FALSE;
1087int Win32Dialog::xBaseUnit = 0;
1088int Win32Dialog::yBaseUnit = 0;
Note: See TracBrowser for help on using the repository browser.