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

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

Unicode <-> Ascii translation changes + fixes for window procedures

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