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

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

RDW_FRAME support for GetDCEx; added wine dialog change; added extra logging

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