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

Last change on this file since 3060 was 3060, checked in by sandervl, 25 years ago

dialog ctor bugfix

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