source: trunk/src/user32/win32wbase.cpp@ 21529

Last change on this file since 21529 was 21529, checked in by dmik, 15 years ago

Fixed completely broken national (non-Latin1) character input in Odin. There were two problems:
1) When translating OS2 WM_CHAR to Win32 WM_CHAR in UNICODE mode, ANSI->UNICODE conversion of the character was not done.
2) When hosting windows on threads created with CreateThread(), characters in WM_CHAR were wrongly converted from OS/2 codepage to ANSI codepage while they already were in ANSI due to the message queue begin switched to it at thread startup.
3) The main thread's message queue is now also switched to ANSI at startup so the conversion from step 2) should normally not take place now.

File size: 152.4 KB
Line 
1/* $Id: win32wbase.cpp,v 1.390 2004-05-24 09:02:00 sandervl Exp $ */
2/*
3 * Win32 Window Base Class for OS/2
4 *
5 * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 * Copyright 1999-2000 Christoph Bratschi (cbratschi@datacomm.ch)
8 *
9 * Parts based on Wine Windows code (windows\win.c)
10 * Corel version: corel20000212
11 *
12 * Copyright 1993, 1994, 1996 Alexandre Julliard
13 * 1995 Alex Korobka
14 *
15 * TODO: Not thread/process safe
16 *
17 * NOTE: To access a window object, you must call GetWindowFromOS2Handle or
18 * GetWindowFromHandle. Both these methods increase the reference count
19 * of the object. When you're done with the object, you MUST call
20 * the release method!
21 * This mechanism prevents premature destruction of objects when there
22 * are still clients using it.
23 *
24 * NOTE: Client rectangle always relative to frame window
25 * Window rectangle in parent coordinates (relative to parent's client window)
26 * (screen coord. if no parent)
27 *
28 * NOTE: Status of window:
29 * Before a window has processed WM_NCCREATE:
30 * - GetTopWindow can't return that window handle
31 * - GetWindow(parent, GW_CHILD) can't return that window handle
32 * - IsChild works
33 * TODO: Does this affect more functions?? (other GetWindow ops)
34 * (verified in NT4, SP6)
35 *
36 * Project Odin Software License can be found in LICENSE.TXT
37 *
38 */
39#include <os2win.h>
40#include <win.h>
41#include <stdlib.h>
42#include <string.h>
43#include <stdarg.h>
44#include <assert.h>
45#include <misc.h>
46#include <heapstring.h>
47#include <winuser32.h>
48#include <custombuild.h>
49#include "win32wbase.h"
50#include "win32wfake.h"
51#include "wndmsg.h"
52#include "oslibwin.h"
53#include "oslibmsg.h"
54#include "oslibutil.h"
55#include "oslibgdi.h"
56#include "oslibres.h"
57#include "oslibdos.h"
58#include "syscolor.h"
59#include "win32wndhandle.h"
60#include "dc.h"
61#include "win32wdesktop.h"
62#include "pmwindow.h"
63#include "controls.h"
64#include <wprocess.h>
65#include <win\hook.h>
66#include <menu.h>
67#define INCL_TIMERWIN32
68#include "timer.h"
69#include "user32api.h"
70#include "callwrap.h"
71
72#define DBG_LOCALLOG DBG_win32wbase
73#include "dbglocal.h"
74
75/* bits in the dwKeyData */
76#define KEYDATA_ALT 0x2000
77#define KEYDATA_PREVSTATE 0x4000
78
79void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle);
80
81static fDestroyAll = FALSE;
82//For quick lookup of current process id
83static ULONG currentProcessId = -1;
84static int iF10Key = 0;
85static int iMenuSysKey = 0;
86
87//******************************************************************************
88//******************************************************************************
89Win32BaseWindow::Win32BaseWindow()
90 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
91{
92 Init();
93}
94//******************************************************************************
95//******************************************************************************
96Win32BaseWindow::Win32BaseWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
97 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
98{
99 Init();
100 this->isUnicode = isUnicode;
101 // call member function
102 CreateWindowExA(lpCreateStructA, classAtom);
103}
104//******************************************************************************
105//******************************************************************************
106void Win32BaseWindow::Init()
107{
108 isUnicode = FALSE;
109 fFirstShow = TRUE;
110 fIsDialog = FALSE;
111 fIsModalDialogOwner = FALSE;
112 OS2HwndModalDialog = 0;
113 fParentChange = FALSE;
114 fDestroyWindowCalled = FALSE;
115 fChildDestructionInProgress = FALSE;
116 fTaskList = FALSE;
117 fParentDC = FALSE;
118 fComingToTop = FALSE;
119 fMinMaxChange = FALSE;
120 fPMUpdateRegionChanged = FALSE;
121 fEraseBkgndFlag = TRUE;
122 fIsDragDropActive= FALSE;
123 fDirtyUpdateRegion = FALSE;
124 fWindowLocked = FALSE;
125
126 state = STATE_INIT;
127 windowNameA = NULL;
128 windowNameW = NULL;
129 windowNameLengthA = 0;
130 windowNameLengthW = 0;
131
132 userWindowBytes = NULL;;
133 nrUserWindowBytes= 0;
134
135 OS2Hwnd = 0;
136 OS2HwndFrame = 0;
137 hSysMenu = 0;
138 Win32Hwnd = 0;
139
140 // allocate a Win32 HWND, return it in Win32Hwnd and associate object
141 // pointer with it
142 if(HwAllocateWindowHandle(&Win32Hwnd, (ULONG)this) == FALSE)
143 {
144 dprintf(("Win32BaseWindow::Init HwAllocateWindowHandle failed!!"));
145 DebugInt3();
146 }
147 Win32HwndOrg = Win32Hwnd;
148
149 posx = posy = 0;
150 width = height = 0;
151
152 dwExStyle = 0;
153 dwStyle = 0;
154 dwOldStyle = 0;
155 win32wndproc = 0;
156 hInstance = 0;
157 dwIDMenu = 0; //0xFFFFFFFF; //default -1
158 userData = 0;
159 contextHelpId = 0;
160 hotkey = 0;
161
162 hwndLinkAfter = HWND_BOTTOM;
163 flags = 0;
164 lastHitTestVal = HTCLIENT;
165 owner = NULL;
166 windowClass = 0;
167
168 hIcon = 0;
169 hIconSm = 0;
170
171 horzScrollInfo = NULL;
172 vertScrollInfo = NULL;
173
174 propertyList = NULL;
175
176 cbExtra = 0;
177 pExtra = NULL;
178
179 ownDC = 0;
180 hWindowRegion = 0;
181 hClipRegion = 0;
182 hVisRegion = 0;
183 hUpdateRegion = 0;
184
185 hTaskList = 0;
186
187 if(currentProcessId == -1)
188 {
189 currentProcessId = GetCurrentProcessId();
190 }
191 dwThreadId = GetCurrentThreadId();
192 dwProcessId = currentProcessId;
193
194 memset(&windowpos, 0, sizeof(windowpos));
195 //min and max position are initially -1 (verified in NT4, SP6)
196 windowpos.ptMinPosition.x = -1;
197 windowpos.ptMinPosition.y = -1;
198 windowpos.ptMaxPosition.x = -1;
199 windowpos.ptMaxPosition.y = -1;
200
201 lpVisRgnNotifyProc = NULL;
202 dwVisRgnNotifyParam = NULL;
203
204 pfnOldPMWndProc = NULL;
205
206 memset(hdcWindow, 0, sizeof(hdcWindow));
207 nrOpenDCs = 0;
208}
209//******************************************************************************
210//todo get rid of resources (menu, icon etc)
211//******************************************************************************
212Win32BaseWindow::~Win32BaseWindow()
213{
214 if(getRefCount() < 0) {
215 DebugInt3();
216 }
217
218 if(hTaskList) {
219 OSLibWinRemoveFromTasklist(hTaskList);
220 }
221
222 OSLibWinSetVisibleRegionNotify(OS2Hwnd, FALSE);
223 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, 0);
224 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, 0);
225
226 if(fDestroyAll) {
227 dprintf(("Destroying window %x %s", getWindowHandle(), windowNameA));
228 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
229 }
230 else
231 if(getParent() && getParent()->getFirstChild() == this && getNextChild() == NULL)
232 {
233 //if we're the last child that's being destroyed and our
234 //parent window was also destroyed, then we
235 if(getParent()->IsWindowDestroyed())
236 {
237 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
238 RELEASE_WNDOBJ(wndparent);
239 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
240 }
241 }
242 else
243 {
244 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
245 if(wndparent && !fDestroyAll) {
246 RELEASE_WNDOBJ(wndparent);
247 }
248 }
249 if(owner && !fDestroyAll) {
250 RELEASE_WNDOBJ(owner);
251 }
252
253 // Decrement class window counter
254 // NOTE: Must be done before ReleaseDC call for ownDC!
255 if(windowClass) {
256 RELEASE_CLASSOBJ(windowClass);
257 }
258
259 if(ownDC)
260 ReleaseDC(Win32HwndOrg, ownDC);
261
262 if(Win32Hwnd)
263 HwFreeWindowHandle(Win32Hwnd);
264
265 if(userWindowBytes)
266 free(userWindowBytes);
267
268 if(windowNameA) {
269 free(windowNameA);
270 windowNameA = NULL;
271 }
272 if(windowNameW) {
273 free(windowNameW);
274 windowNameW = NULL;
275 }
276 if(vertScrollInfo) {
277 free(vertScrollInfo);
278 vertScrollInfo = NULL;
279 }
280 if(horzScrollInfo) {
281 free(horzScrollInfo);
282 horzScrollInfo = NULL;
283 }
284 if(propertyList) {
285 removeWindowProps();
286 }
287 if(hUpdateRegion) {
288 DeleteObject(hUpdateRegion);
289 hUpdateRegion = NULL;
290 }
291}
292//******************************************************************************
293//******************************************************************************
294void Win32BaseWindow::DestroyAll()
295{
296 fDestroyAll = TRUE;
297 GenericObject::DestroyAll(windows);
298}
299//******************************************************************************
300//******************************************************************************
301BOOL Win32BaseWindow::isChild()
302{
303 return ((dwStyle & WS_CHILD) != 0);
304}
305//******************************************************************************
306//******************************************************************************
307BOOL Win32BaseWindow::IsWindowUnicode()
308{
309 dprintf2(("IsWindowUnicode %x %d", getWindowHandle(), WINPROC_GetProcType(getWindowProc()) == WIN_PROC_32W));
310 return (WINPROC_GetProcType(getWindowProc()) == WIN_PROC_32W);
311}
312//******************************************************************************
313//******************************************************************************
314BOOL Win32BaseWindow::CreateWindowExA(CREATESTRUCTA *cs, ATOM classAtom)
315{
316 char buffer[256];
317
318#ifdef DEBUG
319 PrintWindowStyle(cs->style, cs->dwExStyle);
320#endif
321
322 //If window has no owner/parent window, then it will be added to the tasklist
323 //(depending on visibility state)
324 if (!cs->hwndParent) fTaskList = TRUE;
325
326 sw = SW_SHOW;
327 SetLastError(0);
328
329 /* Find the parent window */
330 if (cs->hwndParent)
331 {
332 Win32BaseWindow *window = GetWindowFromHandle(cs->hwndParent);
333 if(!window) {
334 dprintf(("Bad parent %04x\n", cs->hwndParent ));
335 SetLastError(ERROR_INVALID_PARAMETER);
336 return FALSE;
337 }
338 /* Make sure parent is valid */
339/*RLW if (!window->IsWindow() ) */
340 if (!::IsWindow(cs->hwndParent) )
341 {
342 RELEASE_WNDOBJ(window);
343 dprintf(("Bad parent %04x\n", cs->hwndParent ));
344 SetLastError(ERROR_INVALID_PARAMETER);
345 return FALSE;
346 }
347 if (window->getExStyle() & WS_EX_TOPMOST)
348 cs->dwExStyle |= WS_EX_TOPMOST;
349
350 RELEASE_WNDOBJ(window);
351 /* Windows does this for overlapped windows
352 * (I don't know about other styles.) */
353 if (cs->hwndParent == GetDesktopWindow() && (!(cs->style & WS_CHILD) || (cs->style & WS_POPUP)))
354 {
355 cs->hwndParent = 0;
356 }
357 }
358 else
359 if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
360 dprintf(("No parent for child window" ));
361 SetLastError(ERROR_INVALID_PARAMETER);
362 return FALSE; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
363 }
364
365 /* Find the window class */
366 windowClass = Win32WndClass::FindClass(cs->hInstance, (LPSTR)classAtom);
367 if (!windowClass)
368 {
369 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
370 dprintf(("Bad class '%s'", buffer ));
371 SetLastError(ERROR_INVALID_PARAMETER);
372 return 0;
373 }
374
375#ifdef DEBUG
376 if(HIWORD(cs->lpszClass))
377 {
378 if(isUnicode) dprintf(("Window class %ls", cs->lpszClass));
379 else dprintf(("Window class %s", cs->lpszClass));
380 }
381 else dprintf(("Window class %x", cs->lpszClass));
382#endif
383
384 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
385 * with an atom as the class name, put some programs expect to have a *REAL* string in
386 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
387 */
388 if (!HIWORD(cs->lpszClass) ) {
389 if (isUnicode) {
390 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
391 }
392 else {
393 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
394 }
395 cs->lpszClass = buffer;
396 }
397 /* Fix the coordinates */
398 fXDefault = FALSE;
399 fCXDefault = FALSE;
400 FixCoordinates(cs, &sw);
401
402 /* Correct the window style - stage 1
403 *
404 * These are patches that appear to affect both the style loaded into the
405 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
406 *
407 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
408 * why does the user get to set it?
409 */
410
411 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
412 * tested for WS_POPUP
413 */
414 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
415 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
416 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
417 cs->dwExStyle |= WS_EX_WINDOWEDGE;
418 else
419 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
420
421 //Allocate window words
422 nrUserWindowBytes = windowClass->getExtraWndBytes();
423 if(nrUserWindowBytes) {
424 userWindowBytes = (char *)_smalloc(nrUserWindowBytes);
425 memset(userWindowBytes, 0, nrUserWindowBytes);
426 }
427
428 // check if it's the standard child window case
429 if ((cs->style & WS_CHILD) && cs->hwndParent)
430 {
431 SetParent(cs->hwndParent);
432 owner = NULL;
433 //SvL: Shell positioning shouldn't be done for child windows! (breaks Notes)
434 fXDefault = fCXDefault = FALSE;
435 }
436 else
437 {
438 // either no child window or a popup window
439
440 SetParent(0);
441 if (!cs->hwndParent || (cs->hwndParent == windowDesktop->getWindowHandle())) {
442 owner = NULL;
443 }
444 else
445 {
446 // we're a popup window
447
448 Win32BaseWindow *wndparent = GetWindowFromHandle(cs->hwndParent);
449 if(wndparent) {
450 owner = GetWindowFromHandle(wndparent->GetTopParent());
451 RELEASE_WNDOBJ(wndparent);
452 }
453 else owner = NULL;
454
455 if(owner == NULL)
456 {
457 dprintf(("HwGetWindowHandleData couldn't find owner window %x!!!", cs->hwndParent));
458 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
459 return FALSE;
460 }
461 }
462 }
463
464 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, windowClass->getWindowProc((isUnicode) ? WNDPROC_UNICODE : WNDPROC_ASCII), WINPROC_GetProcType(windowClass->getWindowProc((isUnicode) ? WNDPROC_UNICODE : WNDPROC_ASCII)), WIN_PROC_WINDOW);
465 hInstance = cs->hInstance;
466 dwStyle = cs->style & ~WS_VISIBLE;
467 dwOldStyle = dwStyle;
468 dwExStyle = cs->dwExStyle;
469
470 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
471
472 /* Correct the window style phase 2 */
473 if (!(cs->style & WS_CHILD))
474 {
475 dwStyle |= WS_CLIPSIBLINGS;
476 if (!(cs->style & WS_POPUP))
477 {
478 dwStyle |= WS_CAPTION;
479 flags |= WIN_NEED_SIZE;
480 }
481 }
482
483 //WinZip 8.0 crashes when a dialog created after opening a zipfile receives
484 //the WM_SIZE message (before WM_INITDIALOG)
485 //Opera doesn't like this either.
486 if(IsDialog()) {
487 flags |= WIN_NEED_SIZE;
488 }
489
490 //copy pointer of CREATESTRUCT for usage in MsgCreate method
491 tmpcs = cs;
492
493 //Store our window object pointer in thread local memory, so PMWINDOW.CPP can retrieve it
494 TEB *teb = GetThreadTEB();
495 if(teb == NULL) {
496 dprintf(("Window creation failed - teb == NULL")); //this is VERY bad
497 ExitProcess(666);
498 return FALSE;
499 }
500 teb->o.odin.newWindow = (ULONG)this;
501
502 DWORD dwOSWinStyle, dwOSFrameStyle;
503 OSLibWinConvertStyle(dwStyle,dwExStyle,&dwOSWinStyle, &dwOSFrameStyle);
504
505 // create PM windows - frame and client window
506 HWND hwndOS2Frame = (getParent()) ? getParent()->getOS2WindowHandle() : OSLIB_HWND_DESKTOP;
507 OS2Hwnd = OSLibWinCreateWindow(hwndOS2Frame,
508 dwOSWinStyle,
509 dwOSFrameStyle,
510 (char *)windowNameA,
511 (owner) ? owner->getOS2WindowHandle() : 0,
512 (hwndLinkAfter == HWND_BOTTOM) ? TRUE : FALSE,
513 0,
514 fTaskList,
515 fXDefault | fCXDefault,
516 windowClass->getStyle(),
517 &OS2HwndFrame);
518 if(OS2Hwnd == 0) {
519 dprintf(("Window creation failed!! OS LastError %0x", OSLibWinGetLastError()));
520 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
521 return FALSE;
522 }
523 OSLibWinSetVisibleRegionNotify(OS2Hwnd, TRUE);
524 state = STATE_CREATED;
525 SetLastError(0);
526 return TRUE;
527}
528//******************************************************************************
529//******************************************************************************
530static BOOL OSLibWinSetTitleBarTextA(HWND hwnd, LPSTR lpsz)
531{
532 LPSTR psz = NULL;
533 if(lpsz) {
534 psz = (LPSTR)_smalloc(strlen(lpsz) + 1);
535 CharToOemA(lpsz, psz);
536 }
537 BOOL rc = OSLibWinSetTitleBarText(hwnd, psz);
538 if (psz) {
539 _sfree(psz);
540 }
541 return rc;
542}
543//******************************************************************************
544//******************************************************************************
545BOOL Win32BaseWindow::MsgCreate(HWND hwndOS2)
546{
547 CREATESTRUCTA *cs = tmpcs; //pointer to CREATESTRUCT used in CreateWindowExA method
548 POINT maxSize, maxPos, minTrack, maxTrack;
549 HWND hwnd = getWindowHandle();
550 LRESULT (* CALLBACK localSend32)(HWND, UINT, WPARAM, LPARAM);
551
552 OS2Hwnd = hwndOS2;
553
554 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, getWindowHandle()) == FALSE) {
555 dprintf(("WM_CREATE: WinSetWindowULong %X failed!!", OS2Hwnd));
556 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
557 return FALSE;
558 }
559 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, WIN32PM_MAGIC) == FALSE) {
560 dprintf(("WM_CREATE: WinSetWindowULong2 %X failed!!", OS2Hwnd));
561 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
562 return FALSE;
563 }
564 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32FLAGS, 0) == FALSE) {
565 dprintf(("WM_CREATE: WinSetWindowULong2 %X failed!!", OS2Hwnd));
566 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
567 return FALSE;
568 }
569
570 if (HOOK_IsHooked( WH_CBT ))
571 {
572 CBT_CREATEWNDA cbtc;
573 LRESULT ret;
574
575 cbtc.lpcs = cs;
576 cbtc.hwndInsertAfter = hwndLinkAfter;
577 ret = (isUnicode) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, getWindowHandle(), (LPARAM)&cbtc)
578 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, getWindowHandle(), (LPARAM)&cbtc);
579 if(ret)
580 {
581 dprintf(("CBT-hook returned non-0 !!"));
582 SetLastError(ERROR_CAN_NOT_COMPLETE); //todo: wrong error
583 return FALSE;
584 }
585 //todo: if hook changes parent, we need to do so too!!!!!!!!!!
586 }
587
588 if (cs->style & WS_HSCROLL)
589 {
590 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
591 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
592 horzScrollInfo->MaxVal = 100;
593 horzScrollInfo->flags = ESB_ENABLE_BOTH;
594 }
595
596 if (cs->style & WS_VSCROLL)
597 {
598 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
599 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
600 vertScrollInfo->MaxVal = 100;
601 vertScrollInfo->flags = ESB_ENABLE_BOTH;
602 }
603
604 // initially allocate the window name fields
605 if(HIWORD(cs->lpszName))
606 {
607 if (!isUnicode)
608 {
609 windowNameLengthA = strlen(cs->lpszName);
610 windowNameA = (LPSTR)_smalloc(windowNameLengthA+1);
611 strcpy(windowNameA,cs->lpszName);
612
613 windowNameLengthW = lstrlenAtoW( windowNameA, -1 );
614 windowNameW = (LPWSTR)_smalloc(( windowNameLengthW + 1 ) * sizeof( WCHAR ) );
615 lstrcpyAtoW( windowNameW, windowNameA );
616 }
617 else
618 {
619 // Wide
620 windowNameLengthW = lstrlenW((LPWSTR)cs->lpszName);
621 windowNameW = (LPWSTR)_smalloc((windowNameLengthW+1)*sizeof(WCHAR));
622 strcpyW(windowNameW,(LPWSTR)cs->lpszName);
623
624 // windowNameW[lstrlenW((LPWSTR)cs->lpszName)] = 0; // need ?
625
626 // Ascii
627 windowNameLengthA = lstrlenWtoA( windowNameW, -1 );
628 windowNameA = (LPSTR)_smalloc( windowNameLengthA + 1 );
629 lstrcpyWtoA( windowNameA, windowNameW );
630 }
631
632 dprintf(("windowNameA 0x%lx to 0x%lx windowNameW : 0x%lx to 0x%lx",
633 windowNameA, windowNameA + windowNameLengthA,
634 windowNameW, windowNameW + windowNameLengthW ));
635
636 if(fOS2Look) {
637 OSLibWinSetTitleBarTextA(OS2HwndFrame, windowNameA);
638 }
639 }
640
641//SvL: This completely messes up MS Word 97 (no button bar, no menu)
642#if 0
643 //adjust CW_USEDEFAULT position
644 if (fXDefault | fCXDefault)
645 {
646 RECT rect;
647
648 //SvL: Returns invalid rectangle (not the expected shell default size)
649 OSLibWinQueryWindowRect(OS2Hwnd,&rect,RELATIVE_TO_SCREEN);
650 if (getParent()) mapWin32Rect(OSLIB_HWND_DESKTOP,getParent()->getOS2WindowHandle(),&rect);
651 if (fXDefault)
652 {
653 cs->x = rect.left;
654 cs->y = rect.top;
655 if (!fCXDefault)
656 {
657 //CB: todo: adjust pos to screen rect
658 }
659 }
660 if (fCXDefault)
661 {
662 cs->cx = rect.right-rect.left;
663 cs->cy = rect.bottom-rect.top;
664 }
665 }
666#endif
667
668 //Set icon from window or class
669 if (hIcon)
670 OSLibWinSetIcon(OS2HwndFrame,hIcon);
671 else
672 if (windowClass->getIcon())
673 OSLibWinSetIcon(OS2HwndFrame,windowClass->getIcon());
674
675 /* Get class or window DC if needed */
676 if(windowClass->getStyle() & CS_OWNDC) {
677 dprintf(("Class with CS_OWNDC style"));
678 ownDC = GetDCEx(getWindowHandle(), NULL, DCX_USESTYLE);
679 }
680 else
681 if (windowClass->getStyle() & CS_PARENTDC) {
682 fParentDC = TRUE;
683 ownDC = 0;
684 }
685 else
686 if (windowClass->getStyle() & CS_CLASSDC) {
687 dprintf(("WARNING: Class with CS_CLASSDC style!"));
688 //not a good solution, but it's a bit difficult to share a single
689 //DC among different windows... DevOpenDC apparently can't be used
690 //for window DCs and WinOpenWindowDC must be associated with a window
691 ownDC = GetDCEx(getWindowHandle(), NULL, DCX_USESTYLE);
692 }
693 /* Set the window menu */
694 if ((dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
695 {
696 if (cs->hMenu) {
697 ::SetMenu(getWindowHandle(), cs->hMenu);
698 }
699 else {
700 if (windowClass->getMenuNameA()) {
701 cs->hMenu = LoadMenuA(windowClass->getInstance(),windowClass->getMenuNameA());
702#if 0 //CB: hack for treeview test cases bug
703if (!cs->hMenu) cs->hMenu = LoadMenuA(windowClass->getInstance(),"MYAPP");
704#endif
705 if (cs->hMenu) ::SetMenu(getWindowHandle(), cs->hMenu );
706 }
707 }
708 }
709 else
710 {
711 setWindowId((DWORD)cs->hMenu);
712 }
713 hSysMenu = (dwStyle & WS_SYSMENU) ? MENU_GetSysMenu(Win32Hwnd,0):0;
714
715 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
716 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
717 {
718 GetMinMaxInfo(&maxSize, &maxPos, &minTrack, &maxTrack);
719 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
720 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
721 if (cs->cx < minTrack.x) cs->cx = minTrack.x;
722 if (cs->cy < minTrack.y) cs->cy = minTrack.y;
723 if (cs->cx < 0) cs->cx = 0;
724 if (cs->cy < 0) cs->cy = 0;
725 }
726
727 //set client & window rectangles from CreateWindowEx CREATESTRUCT
728 rectWindow.left = cs->x;
729 rectWindow.right = cs->x+cs->cx;
730 rectWindow.top = cs->y;
731 rectWindow.bottom = cs->y+cs->cy;
732 rectClient = rectWindow;
733 OffsetRect(&rectClient, -rectClient.left, -rectClient.top);
734
735 /* Send the WM_CREATE message
736 * Perhaps we shouldn't allow width/height changes as well.
737 * See p327 in "Internals".
738 */
739 maxPos.x = rectWindow.left; maxPos.y = rectWindow.top;
740
741 if(fTaskList) {
742 hTaskList = OSLibWinAddToTaskList(OS2HwndFrame, windowNameA, (cs->style & WS_VISIBLE) ? 1 : 0);
743 }
744
745 localSend32 = (isUnicode) ? ::SendMessageW : ::SendMessageA;
746
747 state = STATE_PRE_WMNCCREATE;
748 if(localSend32(getWindowHandle(), WM_NCCREATE,0,(LPARAM)cs))
749 {
750 RECT tmpRect;
751
752 //CB: recheck flags
753 if (cs->style & (WS_POPUP | WS_CHILD))
754 {
755 fXDefault = FALSE;
756 if (fCXDefault)
757 {
758 fCXDefault = FALSE;
759 cs->cx = cs->cy = 0;
760 rectWindow.right = rectWindow.left;
761 rectWindow.bottom = rectWindow.top;
762 }
763 }
764 tmpRect = rectWindow;
765 state = STATE_POST_WMNCCREATE;
766
767 //set the window size and update the client
768 //@@PF Popup children of inactive windows can thus bring inactive window
769 //on top, this is not correct, popup windows can be on top only if their owner
770 //is in foreground, otherwise they are linked after owner.
771 if (((dwStyle & (WS_CHILD|WS_POPUP)) == WS_POPUP) && getOwner() && (getOwner()->getWindowHandle() != GetForegroundWindow()))
772 {
773 hwndLinkAfter = getOwner()->getWindowHandle();
774 }
775 SetWindowPos(hwndLinkAfter, tmpRect.left, tmpRect.top, tmpRect.right-tmpRect.left, tmpRect.bottom-tmpRect.top,SWP_NOACTIVATE | SWP_NOREDRAW | SWP_FRAMECHANGED);
776
777 state = STATE_PRE_WMCREATE;
778 if (cs->style & WS_VISIBLE) dwStyle |= WS_VISIBLE; //program could change position in WM_CREATE
779 if( (localSend32(getWindowHandle(), WM_CREATE, 0, (LPARAM)cs )) != -1 )
780 {
781 state = STATE_POST_WMCREATE;
782
783 if(!(flags & WIN_NEED_SIZE))
784 {
785 SendMessageA(getWindowHandle(), WM_SIZE, SIZE_RESTORED,
786 MAKELONG(rectClient.right-rectClient.left,
787 rectClient.bottom-rectClient.top));
788
789 if(!::IsWindow(hwnd))
790 {
791 dprintf(("Createwindow: WM_SIZE destroyed window"));
792 goto end;
793 }
794 SendMessageA(getWindowHandle(), WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
795 if(!::IsWindow(hwnd))
796 {
797 dprintf(("Createwindow: WM_MOVE destroyed window"));
798 goto end;
799 }
800 }
801
802 if (getStyle() & (WS_MINIMIZE | WS_MAXIMIZE))
803 {
804 RECT newPos;
805 UINT swFlag = (getStyle() & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
806 setStyle(getStyle() & ~(WS_MAXIMIZE | WS_MINIMIZE));
807 MinMaximize(swFlag, &newPos);
808 swFlag = ((getStyle() & WS_CHILD) || GetActiveWindow()) ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
809 : SWP_NOZORDER | SWP_FRAMECHANGED;
810 SetWindowPos(0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag);
811 if(!::IsWindow(hwnd))
812 {
813 dprintf(("Createwindow: min/max destroyed window"));
814 goto end;
815 }
816 }
817
818 if( (getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY) )
819 {
820 /* Notify the parent window only */
821 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
822 {
823 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_CREATE, getWindowId()), (LPARAM)getWindowHandle());
824 }
825 if(!::IsWindow(hwnd))
826 {
827 dprintf(("Createwindow: WM_PARENTNOTIFY destroyed window"));
828 goto end;
829 }
830 }
831
832 if(cs->style & WS_VISIBLE) {
833 dwStyle &= ~WS_VISIBLE;
834 ShowWindow(sw);
835 }
836
837 /* Call WH_SHELL hook */
838 if (!(getStyle() & WS_CHILD) && !owner)
839 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWCREATED, getWindowHandle(), 0);
840
841 //Call custom Odin hook for window creation (for all windows)
842 HOOK_CallOdinHookA(HODIN_WINDOWCREATED, hwnd, 0);
843
844 SetLastError(0);
845 return TRUE;
846 }
847 }
848 dprintf(("Window creation FAILED (NCCREATE cancelled creation)"));
849 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
850end:
851 return FALSE;
852}
853//******************************************************************************
854//******************************************************************************
855ULONG Win32BaseWindow::MsgQuit()
856{
857 return SendMessageA(getWindowHandle(), WM_QUIT, 0, 0);
858}
859//******************************************************************************
860//******************************************************************************
861ULONG Win32BaseWindow::MsgClose()
862{
863 return SendMessageA(getWindowHandle(), WM_CLOSE,0,0);
864}
865//******************************************************************************
866//******************************************************************************
867ULONG Win32BaseWindow::MsgDestroy()
868{
869 ULONG rc;
870 Win32BaseWindow *child;
871 HWND hwnd = getWindowHandle();
872
873 state = STATE_DESTROYED;
874
875 if(fDestroyWindowCalled == FALSE)
876 {//this window was destroyed because DestroyWindow was called for its parent
877 //so: send a WM_PARENTNOTIFY now as that hasn't happened yet
878 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
879 {
880 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
881 {
882 /* Notify the parent window only */
883 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
884 }
885//// else DebugInt3();
886 }
887 }
888 SendMessageA(getWindowHandle(),WM_DESTROY, 0, 0);
889 if(::IsWindow(hwnd) == FALSE) {
890 //object already destroyed, so return immediately
891 return 1;
892 }
893 SendMessageA(getWindowHandle(),WM_NCDESTROY, 0, 0);
894
895 TIMER_KillTimerFromWindow(getWindowHandle());
896
897 if(getRefCount() == 0 && getFirstChild() == NULL && state == STATE_CREATED) {
898 delete this;
899 }
900 else {
901 //make sure no message can ever arrive for this window again (PM or from other win32 windows)
902 dprintf(("Mark window %x (%x) as deleted; refcount %d", getWindowHandle(), this, getRefCount()));
903 markDeleted();
904 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, 0);
905 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, 0);
906 if(Win32Hwnd) {
907 HwFreeWindowHandle(Win32Hwnd);
908 Win32Hwnd = 0;
909 }
910 // Decrement class window counter
911 // NOTE: Must be done before ReleaseDC call for ownDC!
912 if(windowClass) {
913 RELEASE_CLASSOBJ(windowClass);
914 }
915
916 if(ownDC) {
917 ReleaseDC(Win32Hwnd, ownDC);
918 ownDC = 0;
919 }
920 }
921 return 1;
922}
923//******************************************************************************
924//******************************************************************************
925ULONG Win32BaseWindow::MsgEnable(BOOL fEnable)
926{
927 if(fEnable) {
928 dwStyle &= ~WS_DISABLED;
929 }
930 else dwStyle |= WS_DISABLED;
931
932 return SendMessageA(getWindowHandle(),WM_ENABLE, fEnable, 0);
933}
934//******************************************************************************
935//TODO: SW_PARENTCLOSING/OPENING flag (lParam)
936//******************************************************************************
937ULONG Win32BaseWindow::MsgShow(BOOL fShow)
938{
939 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled) {
940 return 1;
941 }
942
943 if(fShow) {
944 setStyle(getStyle() | WS_VISIBLE);
945 if(getStyle() & WS_MINIMIZE) {
946 return ShowWindow(SW_RESTORE);
947 }
948 }
949 else setStyle(getStyle() & ~WS_VISIBLE);
950
951 //already sent from ShowWindow
952//// return SendMessageA(getWindowHandle(),WM_SHOWWINDOW, fShow, 0);
953 return 0;
954}
955//******************************************************************************
956//******************************************************************************
957ULONG Win32BaseWindow::MsgPosChanging(LPARAM lp)
958{
959 //SvL: Notes crashes when switching views (calls DestroyWindow -> PM sends
960 // a WM_WINDOWPOSCHANGED msg -> crash)
961 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled)
962 return 0;
963
964 return SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, lp);
965}
966//******************************************************************************
967//******************************************************************************
968ULONG Win32BaseWindow::MsgPosChanged(LPARAM lp)
969{
970 //SvL: Notes crashes when switching views (calls DestroyWindow -> PM sends
971 // a WM_WINDOWPOSCHANGED msg -> crash)
972 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled)
973 return 1;
974
975 return SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, lp);
976}
977//******************************************************************************
978//******************************************************************************
979ULONG Win32BaseWindow::MsgScroll(ULONG msg, ULONG scrollCode, ULONG scrollPos)
980{
981 //According to the SDK docs, the scrollbar handle (lParam) is 0 when the standard
982 //window scrollbars send these messages
983 return SendMessageA(getWindowHandle(),msg, MAKELONG(scrollCode, scrollPos), 0);
984}
985//******************************************************************************
986//******************************************************************************
987ULONG Win32BaseWindow::MsgActivate(BOOL fActivate, BOOL fMinimized, HWND hwnd, HWND hwndOS2Win)
988{
989 ULONG rc, procidhwnd = -1, threadidhwnd = 0;
990
991 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
992 if(fDestroyWindowCalled) {
993 return 0;
994 }
995
996 //According to SDK docs, if app returns FALSE & window is being deactivated,
997 //default processing is cancelled
998 //TODO: According to Wine we should proceed anyway if window is sysmodal
999 if(SendMessageA(getWindowHandle(),WM_NCACTIVATE, fActivate, 0) == FALSE && !fActivate)
1000 {
1001 dprintf(("WARNING: WM_NCACTIVATE return code = FALSE -> cancel processing"));
1002 return 0;
1003 }
1004 /* child windows get a WM_CHILDACTIVATE message */
1005 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1006 {
1007 if(fActivate) {//WM_CHILDACTIVE is for activation only
1008 SendMessageA(getWindowHandle(),WM_CHILDACTIVATE, 0, 0L);
1009 }
1010 return 0;
1011 }
1012
1013 return SendMessageA(getWindowHandle(),WM_ACTIVATE, MAKELONG((fActivate) ? WA_ACTIVE : WA_INACTIVE, fMinimized), hwnd);
1014}
1015//******************************************************************************
1016//******************************************************************************
1017ULONG Win32BaseWindow::MsgChildActivate(BOOL fActivate)
1018{
1019 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1020 if(fDestroyWindowCalled) {
1021 return 0;
1022 }
1023
1024 //According to SDK docs, if app returns FALSE & window is being deactivated,
1025 //default processing is cancelled
1026 //TODO: According to Wine we should proceed anyway if window is sysmodal
1027 if(SendMessageA(getWindowHandle(),WM_NCACTIVATE, fActivate, 0) == FALSE && !fActivate)
1028 {
1029 dprintf(("WARNING: WM_NCACTIVATE return code = FALSE -> cancel processing"));
1030 return 0;
1031 }
1032 /* child windows get a WM_CHILDACTIVATE message */
1033 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1034 {
1035 if(fActivate) {//WM_CHILDACTIVE is for activation only
1036 SendMessageA(getWindowHandle(),WM_CHILDACTIVATE, 0, 0L);
1037 }
1038 return 0;
1039 }
1040 DebugInt3();
1041 return 0;
1042}
1043//******************************************************************************
1044//******************************************************************************
1045ULONG Win32BaseWindow::DispatchMsgA(MSG *msg)
1046{
1047 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1048}
1049//******************************************************************************
1050//******************************************************************************
1051ULONG Win32BaseWindow::DispatchMsgW(MSG *msg)
1052{
1053 return SendMessageW(getWindowHandle(), msg->message, msg->wParam, msg->lParam);
1054}
1055//******************************************************************************
1056//******************************************************************************
1057ULONG Win32BaseWindow::MsgSetFocus(HWND hwnd)
1058{
1059 //Notify that focus has changed (necessary for SetFocus(0) handling)
1060 SetFocusChanged();
1061
1062 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1063 if(fDestroyWindowCalled) {
1064 return 0;
1065 }
1066
1067 // if in <= 8bpp mode, then we must send a WM_QUERYNEWPALETTE message here
1068 // this gives the app the chance to realize its palette
1069 if(ScreenBitsPerPel <= 8) {
1070 SendMessageA(getWindowHandle(),WM_QUERYNEWPALETTE, 0, 0);
1071 }
1072 return SendMessageA(getWindowHandle(),WM_SETFOCUS, hwnd, 0);
1073}
1074//******************************************************************************
1075//******************************************************************************
1076ULONG Win32BaseWindow::MsgKillFocus(HWND hwnd)
1077{
1078 //Notify that focus has changed (necessary for SetFocus(0) handling)
1079 SetFocusChanged();
1080
1081 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1082 if(fDestroyWindowCalled) {
1083 return 0;
1084 }
1085 return SendMessageA(getWindowHandle(),WM_KILLFOCUS, hwnd, 0);
1086}
1087//******************************************************************************
1088//******************************************************************************
1089ULONG Win32BaseWindow::MsgButton(MSG *msg)
1090{
1091 BOOL fClick = FALSE;
1092
1093 dprintf(("MsgButton %d at (%d,%d) %X %X", msg->message, msg->pt.x, msg->pt.y, msg->wParam, msg->lParam));
1094 switch(msg->message)
1095 {
1096 case WM_LBUTTONDBLCLK:
1097 case WM_RBUTTONDBLCLK:
1098 case WM_MBUTTONDBLCLK:
1099 if (!(windowClass && windowClass->getClassLongA(GCL_STYLE) & CS_DBLCLKS))
1100 {
1101 msg->message = msg->message - (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); //dblclick -> down
1102 return MsgButton(msg);
1103 }
1104 break;
1105 case WM_NCLBUTTONDBLCLK:
1106 case WM_NCRBUTTONDBLCLK:
1107 case WM_NCMBUTTONDBLCLK:
1108 //Docs say CS_DBLCLKS style doesn't matter for non-client double clicks
1109 fClick = TRUE;
1110 break;
1111
1112 case WM_LBUTTONDOWN:
1113 case WM_RBUTTONDOWN:
1114 case WM_MBUTTONDOWN:
1115 case WM_NCLBUTTONDOWN:
1116 case WM_NCRBUTTONDOWN:
1117 case WM_NCMBUTTONDOWN:
1118 case WM_LBUTTONUP:
1119 case WM_MBUTTONUP:
1120 case WM_RBUTTONUP:
1121 fClick = TRUE;
1122 break;
1123 }
1124
1125 if(fClick)
1126 {
1127 HWND hwndTop;
1128
1129 /* Activate the window if needed */
1130 hwndTop = GetTopParent();
1131
1132 HWND hwndActive = GetActiveWindow();
1133 if (hwndTop && (getWindowHandle() != hwndActive))
1134 {
1135 LONG ret = SendMessageA(getWindowHandle(),WM_MOUSEACTIVATE, hwndTop,
1136 MAKELONG( lastHitTestVal, msg->message) );
1137
1138 //SendMessageA(getWindowHandle(), msg->message, msg->wParam, msg->lParam);
1139 dprintf2(("WM_MOUSEACTIVATE returned %d foreground %x top %x", ret, GetForegroundWindow(), hwndTop));
1140#if 0
1141 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
1142 eatMsg = TRUE;
1143#endif
1144 //SvL: 0 is not documented, but experiments in NT4 show that
1145 // the window will get activated when it returns this.
1146 // (FreeCell is an example)
1147 if(((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT) || (ret == 0))
1148 && (hwndTop != GetForegroundWindow()) )
1149 {
1150 Win32BaseWindow *win32top = Win32BaseWindow::GetWindowFromHandle(hwndTop);
1151
1152 //SvL: Calling OSLibSetActiveWindow(hwndTop); causes focus problems
1153 if (win32top) {
1154 //Must use client window handle (not frame!!)
1155 SetFocus(win32top->getWindowHandle());
1156 RELEASE_WNDOBJ(win32top);
1157 }
1158 }
1159 }
1160 }
1161
1162 SendMessageA(getWindowHandle(),WM_SETCURSOR, getWindowHandle(), MAKELONG(lastHitTestVal, msg->message));
1163
1164 switch(msg->message)
1165 {
1166 case WM_LBUTTONDOWN:
1167 case WM_MBUTTONDOWN:
1168 case WM_RBUTTONDOWN:
1169 case WM_LBUTTONUP:
1170 case WM_MBUTTONUP:
1171 case WM_RBUTTONUP:
1172 {
1173 if (getParent())
1174 {
1175 dprintf(("notifying parent: %X %X", msg->wParam, msg->lParam));
1176 NotifyParent(msg->message, msg->wParam, /*0*/msg->lParam);
1177 }
1178 break;
1179 }
1180 }
1181 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1182}
1183//******************************************************************************
1184//******************************************************************************
1185ULONG Win32BaseWindow::MsgPaint(ULONG tmp, ULONG select)
1186{
1187 if (select && IsWindowIconic())
1188 return SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1189 else
1190 return SendMessageA(getWindowHandle(),WM_PAINT, 0, 0);
1191}
1192//******************************************************************************
1193//
1194// Win32BaseWindow::saveAndValidateUpdateRegion
1195//
1196// If an application doesn't validate the update region while processing
1197// WM_PAINT, then we must remember it for the next time. Also validates
1198// the current update region.
1199//
1200// Parameters:
1201// Returns:
1202//
1203// NOTE:
1204// Windows will only send a WM_PAINT once until another part of the
1205// window is invalidated. Unfortunately PM keeps on sending
1206// WM_PAINT messages until we validate the update region.
1207//
1208// This affects UpdateWindow, RedrawWindow, GetUpdateRgn, GetUpdateRect,
1209// BeginPaint and the next WM_PAINT message.
1210//
1211//******************************************************************************
1212void Win32BaseWindow::saveAndValidateUpdateRegion()
1213{
1214 if(hUpdateRegion == NULL) {
1215 hUpdateRegion = ::CreateRectRgn(0, 0, 1, 1);
1216 }
1217
1218 dprintf(("Win32BaseWindow::saveAndValidateUpdateRegion; marked dirty!"));
1219
1220 //save update region
1221 ::GetUpdateRgn(getWindowHandle(), hUpdateRegion, FALSE);
1222
1223 //and validate it so PM won't bother us again
1224 ::ValidateRgn(getWindowHandle(), hUpdateRegion);
1225
1226 //we just pretend the entire window is invalid. easier this way
1227 fDirtyUpdateRegion = TRUE;
1228}
1229//******************************************************************************
1230//
1231// Win32BaseWindow::checkForDirtyUpdateRegion
1232//
1233// If an application doesn't validate the update region while processing
1234// WM_PAINT, then we must remember it for the next time. If the window has
1235// a dirty update region, then invalidate that region.
1236//
1237// Parameters:
1238// Returns:
1239//
1240// NOTE:
1241//
1242//******************************************************************************
1243void Win32BaseWindow::checkForDirtyUpdateRegion()
1244{
1245 if(fDirtyUpdateRegion) {
1246 dprintf(("Win32BaseWindow::checkForDirtyUpdateRegion; marked dirty -> invalidate whole window!"));
1247 fDirtyUpdateRegion = FALSE;
1248 ::InvalidateRgn(getWindowHandle(), hUpdateRegion, TRUE);
1249 }
1250}
1251//******************************************************************************
1252//TODO: Is the clipper region of the window DC equal to the invalidated rectangle?
1253// (or are we simply erasing too much here)
1254//******************************************************************************
1255ULONG Win32BaseWindow::MsgEraseBackGround(HDC hdc)
1256{
1257 ULONG rc;
1258 HDC hdcErase = hdc;
1259
1260 if (hdcErase == 0) {
1261 DebugInt3();
1262 return 0;
1263 }
1264
1265 if(IsWindowIconic())
1266 rc = SendMessageA(getWindowHandle(),WM_ICONERASEBKGND, hdcErase, 0);
1267 else
1268 rc = SendMessageA(getWindowHandle(),WM_ERASEBKGND, hdcErase, 0);
1269
1270 return (rc);
1271}
1272//******************************************************************************
1273//******************************************************************************
1274ULONG Win32BaseWindow::MsgMouseMove(MSG *msg)
1275{
1276 //TODO: hiword should be 0 if window enters menu mode (SDK docs)
1277 //SDK: WM_SETCURSOR is not sent if the mouse is captured
1278 if(GetCapture() == 0) {
1279 SendMessageA(getWindowHandle(),WM_SETCURSOR, Win32Hwnd, MAKELONG(lastHitTestVal, msg->message));
1280 }
1281
1282 //translated message == WM_(NC)MOUSEMOVE
1283 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1284}
1285//******************************************************************************
1286//******************************************************************************
1287ULONG Win32BaseWindow::MsgChar(MSG *msg)
1288{
1289 if (IsWindowUnicode()) {
1290 // Unicode windows expect the character code in UTF-16 while we save it
1291 // in ascii format, so we need to convert before sending to the window
1292 if (msg->message == WINWM_CHAR) {
1293 CHAR charA;
1294 WCHAR charW;
1295
1296 charA = msg->wParam;
1297 MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
1298 msg->wParam= charW;
1299 dprintf(("MsgChar: Convert to Unicode src=%x res=%x", charA, charW));
1300 }
1301 return DispatchMsgW(msg);
1302 }
1303 return DispatchMsgA(msg);
1304}
1305//******************************************************************************
1306//******************************************************************************
1307ULONG Win32BaseWindow::MsgNCPaint(PRECT pUpdateRect, HRGN hrgnUpdate)
1308{
1309 ULONG rc;
1310 RECT client = rectClient;
1311
1312 if ((pUpdateRect->left >= client.left) && (pUpdateRect->left < client.right) &&
1313 (pUpdateRect->right >= client.left) && (pUpdateRect->right < client.right) &&
1314 (pUpdateRect->top >= client.top) && (pUpdateRect->top < client.bottom) &&
1315 (pUpdateRect->bottom >= client.top) && (pUpdateRect->bottom < client.bottom)
1316 && (!(getStyle() & WS_MINIMIZE)))
1317 {
1318 return 0;
1319 }
1320
1321 rc = SendMessageA(getWindowHandle(),WM_NCPAINT, hrgnUpdate, 0);
1322 //Send WM_PAINTICON here if minimized, because client window will
1323 //not receive a (valid) WM_PAINT message
1324 if (getStyle() & WS_MINIMIZE)
1325 {
1326 rc = SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1327 }
1328
1329 return rc;
1330}
1331//******************************************************************************
1332//Called when either the frame's size or position has changed (lpWndPos != NULL)
1333//or when the frame layout has changed (i.e. scrollbars added/removed) (lpWndPos == NULL)
1334//******************************************************************************
1335ULONG Win32BaseWindow::MsgFormatFrame(WINDOWPOS *lpWndPos)
1336{
1337 RECT oldWindowRect = rectWindow, client = rectClient, newWindowRect;
1338 RECT newClientRect;
1339 WINDOWPOS wndPos;
1340 ULONG rc;
1341
1342 if(lpWndPos)
1343 {
1344 //set new window rectangle
1345 setWindowRect(lpWndPos->x, lpWndPos->y, lpWndPos->x+lpWndPos->cx,
1346 lpWndPos->y+lpWndPos->cy);
1347 newWindowRect = rectWindow;
1348 }
1349 else {
1350 wndPos.hwnd = getWindowHandle();
1351 wndPos.hwndInsertAfter = 0;
1352 newWindowRect= rectWindow;
1353 wndPos.x = newWindowRect.left;
1354 wndPos.y = newWindowRect.top;
1355 wndPos.cx = newWindowRect.right - newWindowRect.left;
1356 wndPos.cy = newWindowRect.bottom - newWindowRect.top;
1357 wndPos.flags = SWP_FRAMECHANGED;
1358 lpWndPos = &wndPos;
1359 }
1360
1361 newClientRect = rectClient;
1362 rc = SendNCCalcSize(TRUE, &newWindowRect, &oldWindowRect, &client, lpWndPos, &newClientRect);
1363 rectClient = newClientRect; //must update rectClient here
1364
1365 dprintf(("MsgFormatFrame: old client rect (%d,%d)(%d,%d), new client (%d,%d)(%d,%d)", client.left, client.top, client.right, client.bottom, rectClient.left, rectClient.top, rectClient.right, rectClient.bottom));
1366 dprintf(("MsgFormatFrame: old window rect (%d,%d)(%d,%d), new window (%d,%d)(%d,%d)", oldWindowRect.left, oldWindowRect.top, oldWindowRect.right, oldWindowRect.bottom, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
1367
1368 if(!CanReceiveSizeMsgs() || !EqualRect(&client, &rectClient)) {
1369 OSLibWinSetClientPos(getOS2WindowHandle(), rectClient.left, rectClient.top, getClientWidth(), getClientHeight(), getWindowHeight());
1370 }
1371
1372#if 1
1373//this doesn't always work
1374// if(CanReceiveSizeMsgs() && (client.left != rectClient.left || client.top != rectClient.top))
1375 if(CanReceiveSizeMsgs() && ((oldWindowRect.right - oldWindowRect.left < rectClient.left
1376 || oldWindowRect.bottom - oldWindowRect.top < rectClient.top) ||
1377 (EqualRect(&oldWindowRect, &rectWindow) && (client.left != rectClient.left || client.top != rectClient.top))))
1378 {
1379 Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild();
1380
1381 //client rectangle has moved -> inform children
1382 dprintf(("MsgFormatFrame -> client rectangle has changed, move children"));
1383 while(child) {
1384 ::SetWindowPos(child->getWindowHandle(),
1385 HWND_TOP, child->getWindowRect()->left,
1386 child->getWindowRect()->top, 0, 0,
1387 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
1388 child = (Win32BaseWindow *)child->getNextChild();
1389 }
1390 }
1391#endif
1392 //WS_EX_TOOLWINDOW is incompatible with the OS2Look (titlebar thinner + smaller font)
1393 if(fOS2Look && ((dwStyle & WS_CAPTION) == WS_CAPTION) && !(dwExStyle & WS_EX_TOOLWINDOW))
1394 {
1395 RECT rect = {0};
1396 BOOL fCloseButton;
1397
1398 fCloseButton = !(windowClass && (windowClass->getClassLongA(GCL_STYLE) & CS_NOCLOSE));
1399
1400 int height = getWindowHeight();
1401 RECTLOS2 rectOS2;
1402
1403 AdjustRectOuter(&rect, FALSE);
1404
1405 rect.left = -rect.left;
1406 rect.top = rect.bottom - rect.top;
1407 rect.right = rectWindow.right - rectWindow.left - rect.right;
1408
1409 rectOS2.xLeft = rect.left;
1410 rectOS2.xRight = rect.right;
1411 rectOS2.yBottom = height - rect.top;
1412 rectOS2.yTop = height - rect.bottom;
1413
1414 //@@PF Disable close button as well when needed by application
1415 OSLibChangeCloseButtonState(getOS2FrameWindowHandle(), fCloseButton);
1416 OSLibWinPositionFrameControls(getOS2FrameWindowHandle(), &rectOS2,
1417 dwStyle, dwExStyle, IconForWindow(ICON_SMALL),
1418 fCloseButton, windowClass->getIcon() != NULL);
1419 }
1420 return rc;
1421}
1422//******************************************************************************
1423//******************************************************************************
1424ULONG Win32BaseWindow::MsgSetText(LPSTR lpsz, LONG cch)
1425{
1426 return SendMessageA(getWindowHandle(),WM_SETTEXT, 0, (LPARAM)lpsz);
1427}
1428//******************************************************************************
1429//******************************************************************************
1430ULONG Win32BaseWindow::MsgGetTextLength()
1431{
1432 return SendMessageA(getWindowHandle(),WM_GETTEXTLENGTH, 0, 0);
1433}
1434//******************************************************************************
1435//******************************************************************************
1436void Win32BaseWindow::MsgGetText(char *wndtext, ULONG textlength)
1437{
1438 SendMessageA(getWindowHandle(),WM_GETTEXT, textlength, (LPARAM)wndtext);
1439}
1440//******************************************************************************
1441//******************************************************************************
1442BOOL Win32BaseWindow::isMDIClient()
1443{
1444 return FALSE;
1445}
1446//******************************************************************************
1447//******************************************************************************
1448BOOL Win32BaseWindow::isMDIChild()
1449{
1450 return FALSE;
1451}
1452//******************************************************************************
1453//TODO: Not complete
1454//******************************************************************************
1455BOOL Win32BaseWindow::isFrameWindow()
1456{
1457 if(getParent() == NULL)
1458 return TRUE;
1459
1460 return FALSE;
1461}
1462//******************************************************************************
1463//******************************************************************************
1464BOOL Win32BaseWindow::isDesktopWindow()
1465{
1466 return FALSE;
1467}
1468//******************************************************************************
1469//******************************************************************************
1470BOOL Win32BaseWindow::isFakeWindow()
1471{
1472 return FALSE;
1473}
1474//******************************************************************************
1475//******************************************************************************
1476BOOL Win32BaseWindow::IsWindowIconic()
1477{
1478 return ((getStyle() & WS_MINIMIZE) && windowClass->getIcon());
1479}
1480//******************************************************************************
1481//******************************************************************************
1482SCROLLBAR_INFO *Win32BaseWindow::getScrollInfo(int nBar)
1483{
1484 switch(nBar)
1485 {
1486 case SB_HORZ:
1487 if (!horzScrollInfo)
1488 {
1489 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1490 if (!horzScrollInfo) break;
1491 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
1492 horzScrollInfo->MaxVal = 100;
1493 horzScrollInfo->flags = ESB_ENABLE_BOTH;
1494 }
1495 return horzScrollInfo;
1496
1497 case SB_VERT:
1498 if (!vertScrollInfo)
1499 {
1500 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1501 if (!vertScrollInfo) break;
1502 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
1503 vertScrollInfo->MaxVal = 100;
1504 vertScrollInfo->flags = ESB_ENABLE_BOTH;
1505 }
1506 return vertScrollInfo;
1507 }
1508
1509 return NULL;
1510}
1511//******************************************************************************
1512//******************************************************************************
1513LRESULT Win32BaseWindow::DefWndControlColor(UINT ctlType, HDC hdc)
1514{
1515 //SvL: Set background color to default button color (not window (white))
1516 if(ctlType == CTLCOLOR_BTN)
1517 {
1518 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1519 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1520 return GetSysColorBrush(COLOR_BTNFACE);
1521 }
1522 //SvL: Set background color to default dialog color if window is dialog
1523 if((ctlType == CTLCOLOR_DLG || ctlType == CTLCOLOR_STATIC) && IsDialog()) {
1524 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1525 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1526 return GetSysColorBrush(COLOR_BTNFACE);
1527 }
1528 if( ctlType == CTLCOLOR_SCROLLBAR)
1529 {
1530 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
1531 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
1532 SetTextColor( hdc, GetSysColor(COLOR_3DFACE));
1533 SetBkColor( hdc, bk);
1534
1535 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
1536 * we better use 0x55aa bitmap brush to make scrollbar's background
1537 * look different from the window background.
1538 */
1539 if (bk == GetSysColor(COLOR_WINDOW)) {
1540 return GetPattern55AABrush();
1541 }
1542
1543 UnrealizeObject( hb );
1544 return (LRESULT)hb;
1545 }
1546
1547 SetTextColor( hdc, GetSysColor(COLOR_WINDOWTEXT));
1548
1549 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
1550 {
1551 SetBkColor( hdc, GetSysColor(COLOR_WINDOW) );
1552 }
1553 else
1554 {
1555 SetBkColor( hdc, GetSysColor(COLOR_3DFACE) );
1556 return (LRESULT)GetSysColorBrush(COLOR_3DFACE);
1557 }
1558 return (LRESULT)GetSysColorBrush(COLOR_WINDOW);
1559}
1560//******************************************************************************
1561//******************************************************************************
1562LRESULT Win32BaseWindow::DefWndPrint(HDC hdc,ULONG uFlags)
1563{
1564 /*
1565 * Visibility flag.
1566 */
1567 if ( (uFlags & PRF_CHECKVISIBLE) &&
1568 !IsWindowVisible(getWindowHandle()) )
1569 return 0;
1570
1571 /*
1572 * Unimplemented flags.
1573 */
1574 if ( (uFlags & PRF_CHILDREN) ||
1575 (uFlags & PRF_OWNED) ||
1576 (uFlags & PRF_NONCLIENT) )
1577 {
1578 dprintf(("WM_PRINT message with unsupported flags\n"));
1579 }
1580
1581 /*
1582 * Background
1583 */
1584 if ( uFlags & PRF_ERASEBKGND)
1585 SendMessageA(getWindowHandle(),WM_ERASEBKGND, (WPARAM)hdc, 0);
1586
1587 /*
1588 * Client area
1589 */
1590 if ( uFlags & PRF_CLIENT)
1591 SendMessageA(getWindowHandle(),WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
1592
1593
1594 return 0;
1595}
1596//******************************************************************************
1597//******************************************************************************
1598LRESULT Win32BaseWindow::DefWindowProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
1599{
1600
1601 dprintf(("DefWndProc: winmsg: %x for %x Msg %s", Msg, Win32Hwnd, GetMsgText(/*HIWORD(lParam)*/Msg)));
1602
1603 switch(Msg)
1604 {
1605 case WM_CLOSE:
1606 dprintf(("DefWindowProcA: WM_CLOSE %x", getWindowHandle()));
1607 DestroyWindow();
1608 return 0;
1609
1610 case WM_GETTEXTLENGTH:
1611 return windowNameLengthA;
1612
1613 case WM_GETTEXT:
1614 if (!lParam || !wParam)
1615 return 0;
1616 if (!windowNameA)
1617 ((LPSTR)lParam)[0] = 0;
1618 else
1619 lstrcpynA(( LPSTR )lParam, windowNameA, wParam );
1620 return strlen(( LPSTR )lParam );
1621
1622 case WM_SETTEXT:
1623 {
1624 LPCSTR lpsz = (LPCSTR)lParam;
1625
1626 // reallocate if new buffer is larger
1627 if (!lParam)
1628 {
1629 free(windowNameA);
1630 free(windowNameW);
1631 windowNameLengthA = 0;
1632 windowNameLengthW = 0;
1633 windowNameA = NULL;
1634 windowNameW = NULL;
1635 }
1636 else
1637 {
1638 if (windowNameA)
1639 {
1640 free(windowNameA);
1641 windowNameA = NULL;
1642 }
1643
1644 if (windowNameW)
1645 {
1646 free(windowNameW);
1647 windowNameW = NULL;
1648 }
1649
1650 windowNameLengthA = strlen( lpsz );
1651 windowNameA = (LPSTR)_smalloc(windowNameLengthA+1);
1652 strcpy(windowNameA, lpsz);
1653 windowNameLengthW = lstrlenAtoW( lpsz, -1 );
1654 windowNameW = (LPWSTR)_smalloc(( windowNameLengthW + 1 )*sizeof(WCHAR));
1655 lstrcpyAtoW( windowNameW, windowNameA );
1656 }
1657
1658 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, lParam));
1659 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1660 {
1661 HandleNCPaint((HRGN)1);
1662 if(hTaskList) {
1663 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
1664 }
1665 if(fOS2Look) {
1666 OSLibWinSetTitleBarTextA(OS2HwndFrame, getWindowNameA());
1667 }
1668 }
1669
1670 return TRUE;
1671 }
1672
1673 case WM_SETREDRAW:
1674 {
1675 if (wParam)
1676 {
1677 setStyle(getStyle() | WS_VISIBLE);
1678 dprintf(("Enable window update for %x", getWindowHandle()));
1679 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, TRUE);
1680 }
1681 else
1682 {
1683 if (getStyle() & WS_VISIBLE)
1684 {
1685 setStyle(getStyle() & ~WS_VISIBLE);
1686 dprintf(("Disable window update for %x", getWindowHandle()));
1687 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, FALSE);
1688 }
1689 }
1690 return 0;
1691 }
1692
1693 case WM_CTLCOLORMSGBOX:
1694 case WM_CTLCOLOREDIT:
1695 case WM_CTLCOLORLISTBOX:
1696 case WM_CTLCOLORBTN:
1697 case WM_CTLCOLORDLG:
1698 case WM_CTLCOLORSTATIC:
1699 case WM_CTLCOLORSCROLLBAR:
1700 return DefWndControlColor(Msg - WM_CTLCOLORMSGBOX, (HDC)wParam);
1701
1702 case WM_CTLCOLOR:
1703 return DefWndControlColor(HIWORD(lParam), (HDC)wParam);
1704
1705 case WM_VKEYTOITEM:
1706 case WM_CHARTOITEM:
1707 return -1;
1708
1709 case WM_PARENTNOTIFY:
1710 return 0;
1711
1712 case WM_MOUSEACTIVATE:
1713 {
1714 HWND hwnd = getWindowHandle();
1715
1716 dprintf(("DefWndProc: WM_MOUSEACTIVATE for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1717 if (::GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
1718 {
1719 LONG ret = ::SendMessageW( ::GetParent(hwnd), WM_MOUSEACTIVATE, wParam, lParam );
1720 if (ret) return ret;
1721 }
1722
1723 /* Caption clicks are handled by the NC_HandleNCLButtonDown() */
1724 return (LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE;
1725 }
1726
1727 case WM_ACTIVATE:
1728 /* The default action in Windows is to set the keyboard focus to
1729 * the window, if it's being activated and not minimized */
1730 if (LOWORD(wParam) != WA_INACTIVE) {
1731 if(!(getStyle() & WS_MINIMIZE))
1732 SetFocus(getWindowHandle());
1733 }
1734 return 0;
1735
1736 case WM_SETCURSOR:
1737 {
1738 dprintf(("DefWndProc: WM_SETCURSOR for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1739 if((getStyle() & WS_CHILD))
1740 {
1741 if(getParent()) {
1742 LRESULT rc = SendMessageA(getParent()->getWindowHandle(), WM_SETCURSOR, wParam, lParam);
1743 if(rc) return rc;
1744 }
1745 }
1746 if (wParam == getWindowHandle())
1747 {
1748 HCURSOR hCursor;
1749
1750 switch(LOWORD(lParam))
1751 {
1752 case HTCLIENT:
1753 hCursor = windowClass ? windowClass->getCursor():LoadCursorA(0,IDC_ARROWA);
1754 break;
1755
1756 case HTLEFT:
1757 case HTRIGHT:
1758 hCursor = LoadCursorA(0,IDC_SIZEWEA);
1759 break;
1760
1761 case HTTOP:
1762 case HTBOTTOM:
1763 hCursor = LoadCursorA(0,IDC_SIZENSA);
1764 break;
1765
1766 case HTTOPLEFT:
1767 case HTBOTTOMRIGHT:
1768 hCursor = LoadCursorA(0,IDC_SIZENWSEA);
1769 break;
1770
1771 case HTTOPRIGHT:
1772 case HTBOTTOMLEFT:
1773 hCursor = LoadCursorA(0,IDC_SIZENESWA);
1774 break;
1775
1776 default:
1777 hCursor = LoadCursorA(0,IDC_ARROWA);
1778 break;
1779 }
1780
1781 if (hCursor)
1782 {
1783 SetCursor(hCursor);
1784 return 1;
1785 }
1786 else return 0;
1787 }
1788 else return 0;
1789 }
1790
1791 case WM_MOUSEMOVE:
1792 return 0;
1793
1794 case WM_MOUSEWHEEL:
1795 if (::GetWindowLongA( getWindowHandle(), GWL_STYLE ) & WS_CHILD)
1796 return ::SendMessageA( ::GetParent(getWindowHandle()), WM_MOUSEWHEEL, wParam, lParam );
1797 break;
1798
1799 case WM_WINDOWPOSCHANGED:
1800 {
1801 PWINDOWPOS wpos = (PWINDOWPOS)lParam;
1802 WPARAM wp = SIZE_RESTORED;
1803
1804 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1805 //show otherwise
1806 if (!(wpos->flags & SWP_NOMOVE) && !(wpos->flags & SWP_NOCLIENTMOVE))
1807 {
1808 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left,rectClient.top));
1809 }
1810 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1811 //show otherwise
1812 if (!(wpos->flags & SWP_NOSIZE) && !(wpos->flags & SWP_NOCLIENTSIZE))
1813 {
1814 if (dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
1815 else
1816 if (dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
1817
1818 SendMessageA(getWindowHandle(),WM_SIZE, wp, MAKELONG(rectClient.right - rectClient.left,
1819 rectClient.bottom - rectClient.top));
1820 }
1821 return 0;
1822 }
1823 case WM_WINDOWPOSCHANGING:
1824 return HandleWindowPosChanging((WINDOWPOS *)lParam);
1825
1826 case WM_ERASEBKGND:
1827 case WM_ICONERASEBKGND:
1828 {
1829 HBRUSH hBrush;
1830 RECT rect;
1831 int rc;
1832
1833 if (!windowClass || (!windowClass->getBackgroundBrush()
1834 && !(getStyle() & WS_MINIMIZE))) return 0;
1835
1836 //PF For PM desktop/MDI icons allocate brush as well to avoid
1837 //garbage in icons
1838
1839 if (!windowClass->getBackgroundBrush())
1840 hBrush = GetStockObject(GRAY_BRUSH);
1841 else
1842 {
1843 hBrush = windowClass->getBackgroundBrush();
1844 if (hBrush <= (HBRUSH)(SYSCOLOR_GetLastColor()+1))
1845 hBrush = GetSysColorBrush(hBrush-1);
1846 }
1847
1848
1849 rc = GetClipBox( (HDC)wParam, &rect );
1850 if ((rc == SIMPLEREGION) || (rc == COMPLEXREGION))
1851 FillRect( (HDC)wParam, &rect, hBrush);
1852
1853 return 1;
1854 }
1855
1856 case WM_PRINT:
1857 return DefWndPrint(wParam,lParam);
1858
1859 case WM_SYNCPAINT:
1860 RedrawWindow(getWindowHandle(), NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN);
1861 return 0;
1862
1863 case WM_PAINTICON:
1864 case WM_PAINT:
1865 {
1866 PAINTSTRUCT ps;
1867 HDC hdc = BeginPaint(getWindowHandle(), &ps );
1868 if( hdc )
1869 {
1870 if( (getStyle() & WS_MINIMIZE) && (getWindowClass()->getIcon() || hIcon))
1871 {
1872 int x = (rectWindow.right - rectWindow.left - GetSystemMetrics(SM_CXICON))/2;
1873 int y = (rectWindow.bottom - rectWindow.top - GetSystemMetrics(SM_CYICON))/2;
1874 dprintf(("Painting class icon: vis rect=(%i,%i - %i,%i)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom ));
1875 DrawIcon(hdc, x, y, hIcon ? hIcon:getWindowClass()->getIcon() );
1876 }
1877 EndPaint(getWindowHandle(), &ps );
1878 }
1879 return 0;
1880 }
1881
1882 case WM_GETDLGCODE:
1883 return 0;
1884
1885 case WM_NCPAINT:
1886 return HandleNCPaint((HRGN)wParam);
1887
1888 case WM_NCACTIVATE:
1889 return HandleNCActivate(wParam);
1890
1891 case WM_NCCREATE:
1892 return(TRUE);
1893
1894 case WM_NCDESTROY:
1895 return 0;
1896
1897 case WM_NCCALCSIZE:
1898 return HandleNCCalcSize((BOOL)wParam,(RECT*)lParam);
1899
1900 case WM_NCLBUTTONDOWN:
1901 return HandleNCLButtonDown(wParam,lParam);
1902
1903 case WM_LBUTTONDBLCLK:
1904 case WM_NCLBUTTONDBLCLK:
1905 return HandleNCLButtonDblClk(wParam,lParam);
1906
1907 case WM_NCRBUTTONDOWN:
1908 case WM_NCRBUTTONDBLCLK:
1909 case WM_NCMBUTTONDOWN:
1910 case WM_NCMBUTTONDBLCLK:
1911 if (lastHitTestVal == HTERROR) MessageBeep(MB_ICONEXCLAMATION);
1912 return 0;
1913
1914 case WM_NCRBUTTONUP:
1915 return HandleNCRButtonUp(wParam,lParam);
1916
1917 case WM_NCMBUTTONUP:
1918 return 0;
1919
1920 case WM_NCHITTEST:
1921 {
1922 POINT point;
1923 LRESULT retvalue;
1924
1925 point.x = (SHORT)LOWORD(lParam);
1926 point.y = (SHORT)HIWORD(lParam);
1927
1928 retvalue = HandleNCHitTest(point);
1929#if 0 //CB: let the Corel people fix the bugs first
1930 if(retvalue == HTMENU)
1931 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,TRUE);
1932 else
1933 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,FALSE);
1934#endif
1935 dprintf(("Hittest: %X", retvalue));
1936 return retvalue;
1937 }
1938
1939 case WM_SYSCOMMAND:
1940 {
1941 POINT point;
1942
1943 point.x = LOWORD(lParam);
1944 point.y = HIWORD(lParam);
1945 return HandleSysCommand(wParam,&point);
1946 }
1947
1948 case WM_KEYDOWN:
1949 if(wParam == VK_F10) iF10Key = VK_F10;
1950 break;
1951
1952 case WM_SYSKEYDOWN:
1953 {
1954 if( HIWORD(lParam) & KEYDATA_ALT )
1955 {
1956 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1957 if( wParam == VK_MENU && !iMenuSysKey )
1958 iMenuSysKey = 1;
1959 else
1960 iMenuSysKey = 0;
1961
1962 iF10Key = 0;
1963
1964 if( wParam == VK_F4 ) /* try to close the window */
1965 {
1966 HWND top = GetTopParent();
1967 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
1968 PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
1969 }
1970
1971 //Default OS/2 app behaviour for system keys
1972 if(fOS2Look)
1973 {
1974 if( wParam == VK_F5 ) /* try to restore the window */
1975 {
1976 HWND top = GetTopParent();
1977 /* No checks needed SC_RESTORE handler does them */
1978 PostMessageW( top, WM_SYSCOMMAND, SC_RESTORE, 0 );
1979 }
1980
1981 if( wParam == VK_F7 ) /* size the window */
1982 {
1983 HWND top = GetTopParent();
1984 PostMessageW( top, WM_SYSCOMMAND, SC_MOVE, 0 );
1985 }
1986
1987 if( wParam == VK_F8 ) /* move the window */
1988 {
1989 HWND top = GetTopParent();
1990 if ( GetWindowLongA(top, GWL_STYLE) & WS_SIZEBOX)
1991 PostMessageW( top, WM_SYSCOMMAND, SC_SIZE, 0 );
1992 }
1993
1994 if( wParam == VK_F9 ) /* try to minimize the window */
1995 {
1996 HWND top = GetTopParent();
1997 if ( GetWindowLongA(top, GWL_STYLE) & WS_MINIMIZEBOX)
1998 PostMessageW( top, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
1999 }
2000
2001 if( wParam == VK_F10 ) /* try to maximize the window */
2002 {
2003 HWND top = GetTopParent();
2004 if ( GetWindowLongA(top, GWL_STYLE) & WS_MAXIMIZEBOX)
2005 PostMessageW( top, WM_SYSCOMMAND, SC_MAXIMIZE, 0 );
2006 }
2007 }
2008
2009 }
2010 else if( wParam == VK_F10 )
2011 iF10Key = 1;
2012 else
2013 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
2014 SendMessageW(getWindowHandle(), WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
2015 return 0;
2016 }
2017
2018 case WM_KEYUP:
2019 //Single Alt down + up always generates WM_SYSKEYUP
2020 iMenuSysKey = 0;
2021 // no break;
2022 case WM_SYSKEYUP:
2023 /* Press and release F10 or ALT */
2024 if (((wParam == VK_MENU) && iMenuSysKey) ||
2025 ((wParam == VK_F10) && iF10Key))
2026 ::SendMessageW( GetTopParent(), WM_SYSCOMMAND, SC_KEYMENU, 0L );
2027 iMenuSysKey = iF10Key = 0;
2028 break;
2029
2030 case WM_SYSCHAR:
2031 {
2032 iMenuSysKey = 0;
2033 if (wParam == VK_RETURN && (getStyle() & WS_MINIMIZE))
2034 {
2035 PostMessageA(getWindowHandle(), WM_SYSCOMMAND,
2036 (WPARAM)SC_RESTORE, 0L );
2037 break;
2038 }
2039 if((HIWORD(lParam) & KEYDATA_ALT) && wParam)
2040 {
2041 if (wParam == VK_TAB || wParam == VK_ESCAPE || wParam == VK_F4)
2042 break;
2043 if (wParam == VK_SPACE && (getStyle() & WS_CHILD)) {
2044 ::SendMessageW(GetParent(), Msg, wParam, lParam );
2045 }
2046 else ::SendMessageA(getWindowHandle(), WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
2047 }
2048#if 0
2049 else /* check for Ctrl-Esc */
2050 if (wParam != VK_ESCAPE) MessageBeep(0);
2051 break;
2052#endif
2053 }
2054
2055 case WM_SETHOTKEY:
2056 hotkey = wParam;
2057 return 1; //CB: always successful
2058
2059 case WM_GETHOTKEY:
2060 return hotkey;
2061
2062 case WM_RBUTTONUP:
2063 {
2064 POINT pt;
2065 pt.x = SLOWORD(lParam);
2066 pt.y = SHIWORD(lParam);
2067 ClientToScreen(getWindowHandle(), &pt);
2068 SendMessageA( getWindowHandle(), WM_CONTEXTMENU, getWindowHandle(),MAKELPARAM(pt.x, pt.y) );
2069 }
2070 break;
2071
2072 case WM_CONTEXTMENU:
2073 if ((dwStyle & WS_CHILD) && getParent())
2074 SendMessageA(getParent()->getWindowHandle(), WM_CONTEXTMENU,wParam,lParam);
2075 else
2076 {
2077 LONG hitcode;
2078 POINT pt;
2079 if (!GetSysMenu()) return 0;
2080 pt.x = SLOWORD(lParam);
2081 pt.y = SHIWORD(lParam);
2082 hitcode = HandleNCHitTest(pt);
2083
2084 /* Track system popup if click was in the caption area. */
2085 if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
2086 TrackPopupMenu(GetSysMenu(),
2087 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
2088 pt.x, pt.y, 0, getWindowHandle(), NULL);
2089 }
2090 return 0;
2091
2092 case WM_SHOWWINDOW:
2093 if (!lParam) return 0; /* sent from ShowWindow */
2094 if (!(dwStyle & WS_POPUP) || !owner) return 0;
2095 if ((dwStyle & WS_VISIBLE) && wParam) return 0;
2096 else if (!(dwStyle & WS_VISIBLE) && !wParam) return 0;
2097 ShowWindow(wParam ? SW_SHOW:SW_HIDE);
2098 return 0;
2099
2100 case WM_CANCELMODE:
2101 if (getParent() == windowDesktop) EndMenu();
2102 if (GetCapture() == Win32Hwnd) ReleaseCapture();
2103 return 0;
2104
2105 case WM_DROPOBJECT:
2106 return DRAG_FILE;
2107
2108 case WM_QUERYDROPOBJECT:
2109 return (dwExStyle & WS_EX_ACCEPTFILES) ? 1:0;
2110
2111 case WM_QUERYDRAGICON:
2112 {
2113 HICON hDragIcon = windowClass->getCursor();
2114 UINT len;
2115
2116 if(hDragIcon) return (LRESULT)hDragIcon;
2117 for(len = 1; len < 64; len++)
2118 {
2119 hDragIcon = LoadIconA(hInstance,MAKEINTRESOURCEA(len));
2120 if(hDragIcon)
2121 return (LRESULT)hDragIcon;
2122 }
2123 return (LRESULT)LoadIconA(0,IDI_APPLICATIONA);
2124 }
2125
2126 case WM_QUERYOPEN:
2127 case WM_QUERYENDSESSION:
2128 return 1;
2129
2130 case WM_NOTIFYFORMAT:
2131 return IsWindowUnicode() ? NFR_UNICODE:NFR_ANSI;
2132
2133 case WM_SETICON:
2134 case WM_GETICON:
2135 {
2136 LRESULT result = 0;
2137
2138 /* Set the appropriate icon members in the window structure. */
2139 if (wParam == ICON_SMALL)
2140 {
2141 result = hIconSm;
2142 if (Msg == WM_SETICON)
2143 hIconSm = (HICON)lParam;
2144 }
2145 else
2146 {
2147 result = hIcon;
2148 if (Msg == WM_SETICON)
2149 {
2150 hIcon = (HICON)lParam;
2151 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2152 OSLibWinSetIcon(OS2HwndFrame,hIcon);
2153 }
2154 }
2155 if ((Msg == WM_SETICON) && ((dwStyle & WS_CAPTION) == WS_CAPTION))
2156 HandleNCPaint((HRGN)1);
2157
2158 return result;
2159 }
2160
2161 case WM_HELP:
2162 if (getParent()) SendMessageA(getParent()->getWindowHandle(), Msg,wParam,lParam);
2163 break;
2164
2165 case WM_NOTIFY:
2166 return 0; //comctl32 controls expect this
2167
2168 case WM_IME_CHAR:
2169 if( wParam & 0xFF00 ) // DBCS ?
2170 SendMessageA( getWindowHandle(), WM_CHAR, ( WPARAM )( BYTE )( wParam >> 8 ), lParam );
2171 SendMessageA( getWindowHandle(), WM_CHAR, ( WPARAM )( BYTE )( wParam & 0xFF ), lParam );
2172 break;
2173
2174 default:
2175 return 0;
2176 }
2177 return 0;
2178}
2179//******************************************************************************
2180//******************************************************************************
2181LRESULT Win32BaseWindow::DefWindowProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
2182{
2183 switch(Msg)
2184 {
2185 case WM_GETTEXTLENGTH:
2186 return windowNameLengthW;
2187
2188 case WM_GETTEXT:
2189 if (!lParam || !wParam)
2190 return 0;
2191 if (!windowNameW)
2192 ((LPWSTR)lParam)[0] = 0;
2193 else
2194 lstrcpynW(( LPWSTR )lParam, windowNameW, wParam );
2195
2196 return strlenW(( LPWSTR )lParam );
2197
2198 case WM_SETTEXT:
2199 {
2200 LPWSTR lpsz = (LPWSTR)lParam;
2201
2202 // reallocate if new buffer is larger
2203 if (!lParam)
2204 {
2205 free(windowNameA);
2206 free(windowNameW);
2207 windowNameLengthA = 0;
2208 windowNameLengthW = 0;
2209 windowNameA = NULL;
2210 windowNameW = NULL;
2211 }
2212 else
2213 {
2214 if (windowNameA)
2215 {
2216 free(windowNameA);
2217 windowNameA = NULL;
2218 }
2219
2220 if (windowNameW)
2221 {
2222 free(windowNameW);
2223 windowNameW = NULL;
2224 }
2225
2226 windowNameLengthW = lstrlenW( lpsz );
2227 windowNameW = (LPWSTR)_smalloc((windowNameLengthW+1)*sizeof(WCHAR));
2228 strcpyW(windowNameW, lpsz);
2229 windowNameLengthA = lstrlenWtoA( lpsz, -1 );
2230 windowNameA = (LPSTR)_smalloc( windowNameLengthA + 1 );
2231 lstrcpyWtoA( windowNameA, windowNameW );
2232 }
2233
2234 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, windowNameA));
2235 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2236 {
2237 HandleNCPaint((HRGN)1);
2238 if(hTaskList) {
2239 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
2240 }
2241 if(fOS2Look) {
2242 OSLibWinSetTitleBarTextA(OS2HwndFrame, getWindowNameA());
2243 }
2244 }
2245
2246 return TRUE;
2247 }
2248
2249 case WM_IME_CHAR:
2250 SendMessageW( getWindowHandle(), WM_CHAR, wParam, lParam );
2251 return 0;
2252
2253 default:
2254 return DefWindowProcA(Msg, wParam, lParam);
2255 }
2256}
2257//******************************************************************************
2258//******************************************************************************
2259void Win32BaseWindow::NotifyParent(UINT Msg, WPARAM wParam, LPARAM lParam)
2260{
2261 Win32BaseWindow *window = this;
2262 Win32BaseWindow *parentwindow;
2263
2264 while(window)
2265 {
2266 if(window->getStyle() & WS_CHILD && !(window->getExStyle() & WS_EX_NOPARENTNOTIFY) )
2267 {
2268 /* Notify the parent window only */
2269 parentwindow = window->getParent();
2270 if(parentwindow) {
2271 /* PF We should map points for each window accordingly! */
2272 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN || Msg == WM_RBUTTONDOWN ||
2273 Msg == WM_LBUTTONUP || Msg == WM_MBUTTONUP || Msg == WM_RBUTTONUP)
2274 {
2275 POINTS pt = MAKEPOINTS(lParam);
2276 POINT point;
2277
2278 point.x = pt.x;
2279 point.y = pt.y;
2280
2281 MapWindowPoints(getWindowHandle(),parentwindow->getWindowHandle(), &point, 1);
2282 lParam = MAKELPARAM(point.x, point.y);
2283 }
2284 SendMessageA(parentwindow->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(Msg, getWindowId()), lParam );
2285 }
2286
2287 }
2288 else break;
2289
2290 window = parentwindow;
2291 }
2292}
2293//******************************************************************************
2294// Returns the big or small icon for the window, falling back to the
2295// class as windows does.
2296//******************************************************************************
2297HICON Win32BaseWindow::IconForWindow(WPARAM fType)
2298{
2299 HICON hWndIcon;
2300
2301 if (fType == ICON_BIG)
2302 {
2303 if (hIcon)
2304 hWndIcon = hIcon;
2305 else
2306 if (windowClass && windowClass->getIcon())
2307 hWndIcon = windowClass->getIcon();
2308 else
2309 if (!(dwStyle & DS_MODALFRAME))
2310 {//SvL: load it as shared or else we'll leak icons
2311 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2312 }
2313 else hWndIcon = 0;
2314 }
2315 else
2316 {
2317 if (hIconSm)
2318 hWndIcon = hIconSm;
2319 else
2320 if (hIcon)
2321 hWndIcon = hIcon;
2322 else
2323 if (windowClass && windowClass->getIconSm())
2324 hWndIcon = windowClass->getIconSm();
2325 else
2326 if (windowClass && windowClass->getIcon())
2327 hWndIcon = windowClass->getIcon();
2328 else
2329 if (!(dwStyle & DS_MODALFRAME))
2330 {//SvL: load it as shared or else we'll leak icons
2331 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2332 }
2333 else hWndIcon = 0;
2334 }
2335
2336 return hWndIcon;
2337}
2338//******************************************************************************
2339//******************************************************************************
2340BOOL Win32BaseWindow::ShowWindow(ULONG nCmdShow)
2341{
2342 ULONG swp = 0;
2343 HWND hWinAfter;
2344 BOOL rc,wasVisible,showFlag;
2345 RECT newPos = {0, 0, 0, 0};
2346
2347 dprintf(("ShowWindow %x %x", getWindowHandle(), nCmdShow));
2348 wasVisible = (getStyle() & WS_VISIBLE) != 0;
2349
2350 dwOldStyle = getStyle();
2351
2352 /*
2353 * SW_SHOWDEFAULT is an reference to the startup info wShowWindow member.
2354 */
2355 if (nCmdShow == SW_SHOWDEFAULT)
2356 {
2357 nCmdShow = GetProcessDword(0, GPD_STARTF_SHOWWINDOW);
2358 dprintf(("ShowWindow: GetProcessDword(0, GPD_STARTF_SHOWWINDOW) -> %x", nCmdShow));
2359 }
2360
2361
2362 switch(nCmdShow)
2363 {
2364 case SW_HIDE:
2365 if (!wasVisible) goto END;
2366
2367 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER;
2368 break;
2369
2370 case SW_SHOWMINNOACTIVE:
2371 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2372 /* fall through */
2373 case SW_SHOWMINIMIZED:
2374 swp |= SWP_SHOWWINDOW;
2375 /* fall through */
2376 case SW_MINIMIZE:
2377 swp |= SWP_FRAMECHANGED;
2378 if( !(getStyle() & WS_MINIMIZE) ) {
2379 swp |= MinMaximize(SW_MINIMIZE, &newPos );
2380 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2381 }
2382 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2383 break;
2384
2385 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
2386 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2387 if( !(getStyle() & WS_MAXIMIZE) ) {
2388 swp |= MinMaximize(SW_MAXIMIZE, &newPos );
2389 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2390 }
2391 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2392 break;
2393
2394 case SW_SHOWNA:
2395 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2396 /* fall through */
2397 case SW_SHOW:
2398 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2399
2400 /*
2401 * ShowWindow has a little peculiar behavior that if the
2402 * window is already the topmost window, it will not
2403 * activate it.
2404 */
2405 if (::GetTopWindow((HWND)0)==getWindowHandle() && (wasVisible || GetActiveWindow() == getWindowHandle()))
2406 swp |= SWP_NOACTIVATE;
2407
2408 break;
2409
2410 case SW_SHOWNOACTIVATE:
2411 swp |= SWP_NOZORDER | SWP_NOACTIVATE;
2412 /* fall through */
2413 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
2414 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2415 case SW_RESTORE:
2416 dprintf(("ShowWindow:restoring window"));
2417
2418 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2419 if( getStyle() & (WS_MINIMIZE | WS_MAXIMIZE) ) {
2420 swp |= MinMaximize(SW_RESTORE, &newPos );
2421 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2422 }
2423 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2424 break;
2425 }
2426
2427 showFlag = (nCmdShow != SW_HIDE);
2428 if (showFlag != wasVisible)
2429 {
2430 SendMessageA(getWindowHandle(),WM_SHOWWINDOW, showFlag, 0 );
2431 if (!::IsWindow( getWindowHandle() )) goto END;
2432 }
2433
2434 /* We can't activate a child window */
2435 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_MDICHILD))
2436 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2437
2438 if (!(getStyle() & WS_MINIMIZE)) {
2439 SetWindowPos(HWND_TOP, newPos.left, newPos.top, newPos.right, newPos.bottom, LOWORD(swp), TRUE);
2440 }
2441 else OSLibWinMinimizeWindow(getOS2FrameWindowHandle());
2442
2443 if(!(swp & SWP_NOACTIVATE) && (!(getStyle() & WS_MINIMIZE))) {
2444 OSLibWinSetActiveWindow(OS2HwndFrame);
2445 }
2446
2447 if (flags & WIN_NEED_SIZE)
2448 {
2449 /* should happen only in CreateWindowEx() */
2450 int wParam = SIZE_RESTORED;
2451
2452 flags &= ~WIN_NEED_SIZE;
2453 if (dwStyle & WS_MAXIMIZE)
2454 wParam = SIZE_MAXIMIZED;
2455 else
2456 if (dwStyle & WS_MINIMIZE)
2457 wParam = SIZE_MINIMIZED;
2458
2459 SendMessageA(getWindowHandle(),WM_SIZE, wParam,
2460 MAKELONG(rectClient.right-rectClient.left,
2461 rectClient.bottom-rectClient.top));
2462 SendMessageA(getWindowHandle(),WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
2463 }
2464//testestest
2465 //temporary workaround for file dialogs with template dialog child
2466 //they don't redraw when switching directories
2467 //For some reason the new child's (syslistview32) update rectangle stays
2468 //empty after its parent is made visible with ShowWindow
2469 //TODO: find real cause
2470 if(!wasVisible) {
2471 InvalidateRect(getWindowHandle(), NULL, TRUE);
2472 }
2473//testestest
2474
2475END:
2476 fMinMaxChange = FALSE;
2477 return wasVisible;
2478}
2479//******************************************************************************
2480//******************************************************************************
2481BOOL Win32BaseWindow::SetWindowPos(HWND hwndInsertAfter, int x, int y, int cx,
2482 int cy, UINT fuFlags, BOOL fShowWindow)
2483{
2484 BOOL rc = FALSE;
2485 Win32BaseWindow *window;
2486 HWND hParent = 0;
2487 RECT oldClientRect = rectClient;
2488
2489 if (fuFlags &
2490 ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
2491 SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
2492 SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
2493 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_DEFERERASE |
2494 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS))
2495 {
2496 dprintf(("ERROR: SetWindowPos; UNKNOWN flag"));
2497 return FALSE;
2498 }
2499
2500 if( fuFlags & (SWP_DEFERERASE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS)) {
2501 dprintf(("WARNING: SetWindowPos; unsupported flag"));
2502 }
2503
2504 if(IsWindowDestroyed()) {
2505 //changing the position of a window that's being destroyed can cause crashes in PMMERGE
2506 dprintf(("SetWindowPos; window already destroyed"));
2507 return TRUE;
2508 }
2509
2510 if(state >= STATE_CREATED) {
2511 /* Fix redundant flags */
2512 if(getStyle() & WS_VISIBLE) {
2513 fuFlags &= ~SWP_SHOWWINDOW;
2514 }
2515 else
2516 {
2517 if (!(fuFlags & SWP_SHOWWINDOW))
2518 fuFlags |= SWP_NOREDRAW;
2519 fuFlags &= ~SWP_HIDEWINDOW;
2520 }
2521 //SvL: These checks are causing problems in Lotus Notes 6
2522 // It's not entirely clear why, but child windows are not placed
2523 // correctly when enabling them.
2524#if 0
2525 if((rectWindow.right - rectWindow.left == cx) && (rectWindow.bottom - rectWindow.top == cy)) {
2526 fuFlags |= SWP_NOSIZE; /* Already the right size */
2527 }
2528
2529 if((rectWindow.left == x) && (rectWindow.top == y)) {
2530 fuFlags |= SWP_NOMOVE; /* Already the right position */
2531 }
2532#endif
2533
2534 if(getWindowHandle() == GetActiveWindow()) {
2535 fuFlags |= SWP_NOACTIVATE; /* Already active */
2536 }
2537 else
2538 if((getStyle() & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2539 {
2540 if(!(fuFlags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2541 {
2542 fuFlags &= ~SWP_NOZORDER;
2543 hwndInsertAfter = HWND_TOP;
2544 }
2545 }
2546 }
2547
2548 /* TODO: Check hwndInsertAfter */
2549
2550 //Note: Solitaire crashes when receiving WM_SIZE messages before WM_CREATE
2551 if(state < STATE_POST_WMNCCREATE)
2552 {//don't change size; modify internal structures only
2553 //TODO: not 100% correct yet (activate)
2554 dprintf2(("state < STATE_POST_WMNCCREATE"));
2555 if(!(fuFlags & SWP_NOZORDER)) {
2556 hwndLinkAfter = hwndInsertAfter;
2557 }
2558 if(!(fuFlags & SWP_NOMOVE)) {
2559 rectWindow.bottom = (rectWindow.bottom - rectWindow.top) + y;
2560 rectWindow.top = y;
2561 rectWindow.right = (rectWindow.right - rectWindow.left) + x;
2562 rectWindow.left = x;
2563 }
2564 if(!(fuFlags & SWP_NOSIZE)) {
2565 rectWindow.bottom = rectWindow.top + cy;
2566 rectWindow.right = rectWindow.left + cx;
2567 }
2568 return TRUE;
2569 }
2570
2571 WINDOWPOS wpos;
2572 SWP swp, swpOld;
2573 wpos.flags = fuFlags;
2574 wpos.cy = cy;
2575 wpos.cx = cx;
2576 wpos.x = x;
2577 wpos.y = y;
2578 wpos.hwndInsertAfter = hwndInsertAfter;
2579 wpos.hwnd = getWindowHandle();
2580
2581 if(~fuFlags & (SWP_NOMOVE | SWP_NOSIZE))
2582 {
2583 if (isChild())
2584 {
2585 if(!getParent()) {
2586 dprintf(("WARNING: Win32BaseWindow::SetWindowPos window %x is child but has no parent!!", getWindowHandle()));
2587 }
2588 }
2589 OSLibWinQueryWindowPos(OS2HwndFrame, &swpOld);
2590 }
2591 if((dwOldStyle & WS_MINIMIZE) && (getStyle() & WS_MINIMIZE))
2592 {//don't allow size changes if the window is minimized
2593 //we will update the restore position at the end of this method
2594 if(!(wpos.flags & SWP_NOSIZE)) {
2595 //TODO: updating the window rectangle doesn't look right
2596 wpos.flags |= SWP_NOSIZE;
2597 rectWindow.right = rectWindow.left + wpos.cx;
2598 rectWindow.bottom = rectWindow.top + wpos.cy;
2599 dprintf(("WARNING: Don't allow size change for minimized window; only save new restore position"));
2600 dprintf(("new window rectangle (%d,%d)(%d,%d)", rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2601 }
2602 }
2603
2604 // Hack alert: This makes sure the tooltips windows in OpenOffice don't
2605 // activate the owner windows too.
2606 // First condition takes care of SetWindowPos during window
2607 // creation. The 2nd one for calls made by OpenOffice
2608 if(((getStyle() & WS_POPUP) && (getExStyle() & WS_EX_TOPMOST)) || (fuFlags & SWP_NOOWNERZORDER))
2609 {
2610 //SWP_NOOWNERZORDER means only the z-order of this window changes; it
2611 //should not affect the owner
2612 //PM doesn't support this feature, so this hack might work
2613 wpos.flags |= SWP_NOZORDER;
2614 }
2615
2616 if(getParent()) {
2617 OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, getParent()->getClientHeight(),
2618 OS2HwndFrame);
2619 }
2620 else OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, OSLibQueryScreenHeight(), OS2HwndFrame);
2621
2622 if (swp.fl == 0) {
2623 dprintf2(("swp.fl == 0"));
2624 if(fuFlags & SWP_FRAMECHANGED)
2625 {
2626 NotifyFrameChanged(&wpos, &oldClientRect);
2627 }
2628 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)) && !(fuFlags & (SWP_NOSIZE | SWP_NOMOVE)))
2629 {
2630 //Restore position always changes when the window position is changed
2631 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2632 windowpos.rcNormalPosition = rectWindow;
2633 }
2634 return TRUE;
2635 }
2636
2637// if ((swp.fl & SWPOS_ZORDER) && (swp.hwndInsertBehind > HWNDOS_BOTTOM))
2638 if ((swp.hwndInsertBehind > HWNDOS_BOTTOM))
2639 {
2640 Win32BaseWindow *wndBehind = Win32BaseWindow::GetWindowFromHandle(swp.hwndInsertBehind);
2641 if(wndBehind) {
2642 swp.hwndInsertBehind = wndBehind->getOS2FrameWindowHandle();
2643 RELEASE_WNDOBJ(wndBehind);
2644 }
2645 else {
2646 dprintf(("ERROR: SetWindowPos: hwndInsertBehind %x invalid!",swp.hwndInsertBehind));
2647 swp.hwndInsertBehind = 0;
2648 }
2649 }
2650 swp.hwnd = OS2HwndFrame;
2651
2652 //SvL: Must also deactivate the window when hiding it or else focus won't
2653 // change. (NOTE: make sure this doesn't cause regressions (01-02-2003)
2654 if((swp.fl & (SWPOS_HIDE|SWPOS_DEACTIVATE)) == (SWPOS_HIDE|SWPOS_DEACTIVATE))
2655 {
2656 //we must make sure the owner is not disabled or else the focus will
2657 //be switched to the wrong window
2658 Win32BaseWindow *topOwner;
2659
2660 if(getOwner() == NULL) {
2661 windowDesktop->addRef();
2662 topOwner = windowDesktop;
2663 }
2664 else topOwner = GetWindowFromHandle(getOwner()->GetTopParent());
2665
2666 if(topOwner != NULL) {
2667 DWORD dwStyle = topOwner->GetWindowLong(GWL_STYLE, FALSE);
2668 if(dwStyle & WS_DISABLED) {
2669 swp.fl &= ~SWPOS_DEACTIVATE;
2670 }
2671 }
2672 else DebugInt3();
2673 }
2674
2675 if(fuFlags & SWP_SHOWWINDOW && !IsWindowVisible(getWindowHandle())) {
2676 setStyle(getStyle() | WS_VISIBLE);
2677 if(hTaskList) {
2678 dprintf(("Adding window %x to tasklist", getWindowHandle()));
2679 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 1);
2680 }
2681 }
2682 else
2683 if((fuFlags & SWP_HIDEWINDOW) && IsWindowVisible(getWindowHandle())) {
2684 setStyle(getStyle() & ~WS_VISIBLE);
2685 if(hTaskList && !(getStyle() & WS_MINIMIZE)) {
2686 dprintf(("Removing window %x from tasklist", getWindowHandle()));
2687 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 0);
2688 }
2689 }
2690 dprintf (("WinSetWindowPos %x %x (%d,%d)(%d,%d) %x", swp.hwnd, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, swp.fl));
2691
2692 rc = OSLibWinSetMultWindowPos(&swp, 1);
2693 if(rc == FALSE)
2694 {
2695 dprintf(("OSLibWinSetMultWindowPos failed! Error %x",OSLibWinGetLastError()));
2696 return 0;
2697 }
2698
2699 if((fuFlags & SWP_FRAMECHANGED) && (fuFlags & (SWP_NOMOVE | SWP_NOSIZE) == (SWP_NOMOVE | SWP_NOSIZE)))
2700 {
2701 NotifyFrameChanged(&wpos, &oldClientRect);
2702 }
2703 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)))
2704 {
2705 //Restore position always changes when the window position is changed
2706 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2707 windowpos.rcNormalPosition = rectWindow;
2708 }
2709 //MSDN says the entire client area will be invalidated when SWP_NOCOPYBITS
2710 //is specified (fixes repaint issues when window is made smaller)
2711 if((fuFlags & (SWP_NOCOPYBITS|SWP_NOREDRAW)) == SWP_NOCOPYBITS) {
2712 InvalidateRect(getWindowHandle(), NULL, TRUE);
2713 }
2714
2715 if(!(fuFlags & SWP_NOSIZE))
2716 {
2717 // We must call this function or open DC will get out of sync
2718 // (PM will not always send us a WM_VRNENABLED message)
2719 RecalcVisibleRegion(this);
2720 }
2721 return (rc);
2722}
2723//******************************************************************************
2724//Called by ScrollWindowEx (dc.cpp) to notify child window that it has moved
2725//******************************************************************************
2726BOOL Win32BaseWindow::ScrollWindow(int dx, int dy)
2727{
2728 rectWindow.left += dx;
2729 rectWindow.right += dx;
2730 rectWindow.top += dy;
2731 rectWindow.bottom += dy;
2732 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left, rectClient.top));
2733 return TRUE;
2734}
2735//******************************************************************************
2736//******************************************************************************
2737void Win32BaseWindow::NotifyFrameChanged(WINDOWPOS *wpos, RECT *oldClientRect)
2738{
2739 HRGN hrgn, hrgnClient;
2740 RECT rect;
2741
2742 MsgFormatFrame(NULL);
2743
2744 if(RECT_WIDTH(rectClient) != RECT_WIDTH(*oldClientRect) ||
2745 RECT_HEIGHT(rectClient) != RECT_HEIGHT(*oldClientRect))
2746 {
2747 wpos->flags &= ~(SWP_NOSIZE|SWP_NOCLIENTSIZE);
2748 wpos->cx = RECT_WIDTH(rectWindow);
2749 wpos->cy = RECT_HEIGHT(rectWindow);
2750 }
2751
2752 if(rectClient.left != oldClientRect->left ||
2753 rectClient.top != oldClientRect->top)
2754 {
2755 wpos->flags &= ~(SWP_NOMOVE|SWP_NOCLIENTMOVE);
2756 wpos->x = rectWindow.left;
2757 wpos->y = rectWindow.top;
2758 }
2759
2760 WINDOWPOS wpOld = *wpos;
2761 if(!(wpos->flags & SWP_NOSENDCHANGING))
2762 SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, (LPARAM)wpos);
2763
2764 if ((wpos->hwndInsertAfter != wpOld.hwndInsertAfter) ||
2765 (wpos->x != wpOld.x) || (wpos->y != wpOld.y) || (wpos->cx != wpOld.cx) || (wpos->cy != wpOld.cy) || (wpos->flags != wpOld.flags))
2766 {
2767 dprintf(("WARNING, NotifyFrameChanged: TODO -> adjust flags!!!!"));
2768 SetWindowPos(wpos->hwndInsertAfter, wpos->x, wpos->y, wpos->cx, wpos->cy, wpos->flags | SWP_NOSENDCHANGING);
2769 }
2770 else SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, (LPARAM)wpos);
2771
2772 //Calculate invalid areas
2773 rect = rectWindow;
2774 OffsetRect(&rect, -rectWindow.left, -rectWindow.top);
2775 hrgn = CreateRectRgnIndirect(&rect);
2776 if (!hrgn) {
2777 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2778 return;
2779 }
2780 rect = rectClient;
2781 hrgnClient = CreateRectRgnIndirect(&rect);
2782 if (!hrgn) {
2783 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2784 return;
2785 }
2786 CombineRgn(hrgn, hrgn, hrgnClient, RGN_DIFF);
2787 DeleteObject(hrgnClient);
2788
2789 if(!EqualRect(oldClientRect, &rectClient)) {
2790 UnionRect(oldClientRect, oldClientRect, &rectClient);
2791 hrgnClient = CreateRectRgnIndirect(oldClientRect);
2792 if (!hrgn) {
2793 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2794 return;
2795 }
2796 CombineRgn(hrgn, hrgn, hrgnClient, RGN_OR);
2797 DeleteObject(hrgnClient);
2798 }
2799 RedrawWindow(getWindowHandle(), NULL, hrgn, RDW_ALLCHILDREN |
2800 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
2801 DeleteObject(hrgn);
2802}
2803//******************************************************************************
2804//TODO: Check how this api really works in NT
2805//******************************************************************************
2806BOOL Win32BaseWindow::SetWindowPlacement(WINDOWPLACEMENT *wndpl)
2807{
2808 dprintf(("SetWindowPlacement %x min (%d,%d)", getWindowHandle(), wndpl->ptMinPosition.x, wndpl->ptMinPosition.y));
2809 dprintf(("SetWindowPlacement %x max (%d,%d)", getWindowHandle(), wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y));
2810 dprintf(("SetWindowPlacement %x norm (%d,%d)(%d,%d)", getWindowHandle(), wndpl->rcNormalPosition.left, wndpl->rcNormalPosition.top, wndpl->rcNormalPosition.right, wndpl->rcNormalPosition.bottom));
2811 windowpos.ptMinPosition = wndpl->ptMinPosition;
2812 windowpos.ptMaxPosition = wndpl->ptMaxPosition;
2813 windowpos.rcNormalPosition = wndpl->rcNormalPosition;
2814
2815 if(getStyle() & WS_MINIMIZE )
2816 {
2817 //TODO: Why can't this be (0,0)?
2818 if(wndpl->flags & WPF_SETMINPOSITION && !(!windowpos.ptMinPosition.x && !windowpos.ptMinPosition.y)) {
2819 SetWindowPos(0, windowpos.ptMinPosition.x, windowpos.ptMinPosition.y,
2820 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2821 }
2822 }
2823 else
2824 if(getStyle() & WS_MAXIMIZE )
2825 {
2826 //TODO: Why can't this be (0,0)?
2827 if(windowpos.ptMaxPosition.x != 0 || windowpos.ptMaxPosition.y != 0 )
2828 SetWindowPos(0, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
2829 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2830 }
2831 else {
2832 SetWindowPos(0, windowpos.rcNormalPosition.left, windowpos.rcNormalPosition.top,
2833 windowpos.rcNormalPosition.right - windowpos.rcNormalPosition.left,
2834 windowpos.rcNormalPosition.bottom - windowpos.rcNormalPosition.top,
2835 SWP_NOZORDER | SWP_NOACTIVATE );
2836 }
2837 ShowWindow(wndpl->showCmd);
2838 if( ::IsWindow(getWindowHandle()) && getStyle() & WS_MINIMIZE )
2839 {
2840 /* SDK: ...valid only the next time... */
2841 if(wndpl->flags & WPF_RESTORETOMAXIMIZED)
2842 setFlags(getFlags() | WIN_RESTORE_MAX);
2843 }
2844 return TRUE;
2845}
2846//******************************************************************************
2847//******************************************************************************
2848BOOL Win32BaseWindow::GetWindowPlacement(LPWINDOWPLACEMENT wndpl)
2849{
2850 wndpl->length = sizeof(*wndpl);
2851 if(getStyle() & WS_MINIMIZE )
2852 wndpl->showCmd = SW_SHOWMINIMIZED;
2853 else wndpl->showCmd = (getStyle() & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
2854
2855 //TODO: Verify if this is correct -> SDK docs claim this flag must always be set to 0
2856 if(getFlags() & WIN_RESTORE_MAX )
2857 wndpl->flags = WPF_RESTORETOMAXIMIZED;
2858 else wndpl->flags = 0;
2859
2860 wndpl->ptMinPosition = windowpos.ptMinPosition;
2861 wndpl->ptMaxPosition = windowpos.ptMaxPosition;
2862 //Must be in parent coordinates (or screen if no parent); verified in NT4, SP6
2863 wndpl->rcNormalPosition = windowpos.rcNormalPosition;
2864
2865 return TRUE;
2866}
2867//******************************************************************************
2868//Also destroys all the child windows (destroy children first, parent last)
2869//TODO: Don't rely on PM to do the right thing. Send WM_(NC)DESTROY &
2870// destroy children ourselves (see Wine)
2871//******************************************************************************
2872BOOL Win32BaseWindow::DestroyWindow()
2873{
2874 HWND hwnd = getWindowHandle();
2875
2876 dprintf(("DestroyWindow %x", hwnd));
2877
2878#if 0
2879 /* Look whether the focus is within the tree of windows we will
2880 * be destroying.
2881 */
2882 HWND hwndFocus = GetFocus();
2883 if (hwndFocus == hwnd || ::IsChild( hwnd, hwndFocus ))
2884 {
2885 HWND parent = GetAncestor( hwnd, GA_PARENT );
2886 if (parent == GetDesktopWindow()) parent = 0;
2887 SetFocus( parent );
2888 }
2889#endif
2890 /* Call hooks */
2891 if(HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, getWindowHandle(), 0L))
2892 {
2893 return FALSE;
2894 }
2895
2896 if(!(getStyle() & WS_CHILD) && getOwner() == NULL)
2897 {
2898 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWDESTROYED, getWindowHandle(), 0L);
2899 /* FIXME: clean up palette - see "Internals" p.352 */
2900 }
2901
2902 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
2903 {
2904 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
2905 {
2906 /* Notify the parent window only */
2907 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
2908 if(!::IsWindow(hwnd) )
2909 {
2910 return TRUE;
2911 }
2912 }
2913//// else DebugInt3();
2914 }
2915 //Must remove the switch entry here to avoid problems with XWorkPlace
2916 if(hTaskList) {
2917 OSLibWinRemoveFromTasklist(hTaskList);
2918 hTaskList = 0;
2919 }
2920
2921 /* Hide the window */
2922 if(IsWindowVisible(getWindowHandle()))
2923 {
2924 SetWindowPos(0, 0, 0, 0, 0, SWP_HIDEWINDOW |
2925 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2926 if(!::IsWindow(hwnd))
2927 {
2928 return TRUE;
2929 }
2930 }
2931 dprintf(("DestroyWindow %x -> HIDDEN", hwnd));
2932
2933 // check the handle for the last active popup window
2934 Win32BaseWindow* owner = getOwner();
2935 if (NULL != owner)
2936 {
2937 if (owner->getLastActive() == hwnd)
2938 owner->setLastActive( owner->getWindowHandle() );
2939
2940 //SvL: Not sure this is correct, but it solves the problem of reassigning
2941 // activation. A disabled window will never be activated ->
2942 // possible that the wrong window is chosen by PM.
2943 // PM chooses another window to be activated before WM_DESTROY is
2944 // sent. VPC enables the owner when it receives that message,
2945 // but by then it's too late.
2946 // (MFC created modeless dialog)
2947 //TODO: This might be the wrong place to do it. EndDialog is called,
2948 // so perhaps it should be done there. (although Wine only
2949 // enables the owner if the dialog is modal)
2950 ::EnableWindow(owner->getWindowHandle(), 1);
2951 }
2952
2953 fDestroyWindowCalled = TRUE;
2954
2955//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2956// handler; must postpone it
2957 if(fChildDestructionInProgress) {
2958 dprintf(("Postponing parent destruction because of dying child"));
2959 OSLibPostMessageDirect(OS2HwndFrame, WIN32APP_POSTPONEDESTROY, 0, 0);
2960 return TRUE;
2961 }
2962
2963 BOOL fOldChildDestructionInProgress = FALSE;
2964 if(GetParent()) {
2965 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2966 if(window) {
2967 fOldChildDestructionInProgress = window->IsChildDestructionInProgress();
2968 window->SetChildDestructionInProgress(TRUE);
2969 RELEASE_WNDOBJ(window);
2970 }
2971 }
2972//hack end
2973
2974 BOOL ret = OSLibWinDestroyWindow(OS2HwndFrame);
2975
2976//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2977// handler; must postpone it
2978 if(GetParent()) {
2979 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2980 if(window) {
2981 window->SetChildDestructionInProgress(fOldChildDestructionInProgress);
2982 RELEASE_WNDOBJ(window);
2983 }
2984 }
2985//hack end
2986 return ret;
2987}
2988//******************************************************************************
2989//******************************************************************************
2990Win32BaseWindow *Win32BaseWindow::getParent()
2991{
2992 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2993 //experiment
2994#if 0
2995 return ((ULONG)wndparent == (ULONG)windowDesktop) ? NULL : wndparent;
2996#else
2997 return wndparent;
2998#endif
2999}
3000//******************************************************************************
3001// Win32BaseWindow::GetParent
3002//
3003// If the window is a child window, then return the parent window handle.
3004// If it's a popup window, then return the owner
3005//
3006// Returns window handle of parent or owner window
3007//
3008// Note: does not set last error if no parent (verified in NT4, SP6)
3009//******************************************************************************
3010HWND Win32BaseWindow::GetParent()
3011{
3012 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3013
3014 if(getStyle() & WS_CHILD)
3015 {
3016 if(wndparent) {
3017 return wndparent->getWindowHandle();
3018 }
3019 dprintf(("WARNING: GetParent: WS_CHILD but no parent!!"));
3020 DebugInt3();
3021 return 0;
3022 }
3023 else
3024 if(getStyle() & WS_POPUP)
3025 return (getOwner()) ? getOwner()->getWindowHandle() : 0;
3026 else return 0;
3027}
3028//******************************************************************************
3029//******************************************************************************
3030HWND Win32BaseWindow::SetParent(HWND hwndNewParent)
3031{
3032 HWND oldhwnd;
3033 Win32BaseWindow *newparent;
3034 Win32BaseWindow *oldparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3035 BOOL fShow = FALSE;
3036
3037 if(oldparent) {
3038 oldhwnd = oldparent->getWindowHandle();
3039 oldparent->removeChild(this);
3040 }
3041 else oldhwnd = 0;
3042
3043 /* Windows hides the window first, then shows it again
3044 * including the WM_SHOWWINDOW messages and all */
3045 if(IsWindowCreated() && (getStyle() & WS_VISIBLE)) {
3046 ShowWindow(SW_HIDE);
3047 fShow = TRUE;
3048 }
3049 if(oldparent) {
3050 //release parent here (increased refcount during creation)
3051 RELEASE_WNDOBJ(oldparent);
3052 }
3053 newparent = GetWindowFromHandle(hwndNewParent);
3054 if(newparent && !newparent->isDesktopWindow())
3055 {
3056 setParent(newparent);
3057 getParent()->addChild(this);
3058 fParentChange = TRUE;
3059 // in case we haven't finished creating the window whose parent we're
3060 // setting here, the OS/2 HWND might not exist yet and we call the PM
3061 // API with a NULLHANDLE - no problem
3062 // when we create the OS/2 window lateron, we will create it with the
3063 // right parent anyway.
3064 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
3065 if(!(getStyle() & WS_CHILD))
3066 {
3067 if(getWindowId())
3068 {
3069 DestroyMenu( (HMENU) getWindowId() );
3070 setWindowId(0);
3071 }
3072 }
3073 //SvL: Even though the win32 coordinates might not change, the PM
3074 // coordinates can. We must make sure the control stays at the
3075 // same position (y) relative to the (new) parent.
3076 // TODO: shouldn't we check the state of the window and not do it in INIT state?
3077 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
3078 SWP_NOACTIVATE|SWP_NOSIZE);
3079 fParentChange = FALSE;
3080 }
3081 else {
3082 if(newparent) RELEASE_WNDOBJ(newparent);
3083
3084 setParent(windowDesktop);
3085 windowDesktop->addRef();
3086 windowDesktop->addChild(this);
3087 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
3088
3089 //Do not change the window id!
3090//// setWindowId(0);
3091 }
3092 /* SetParent additionally needs to make hwndChild the topmost window
3093 in the x-order and send the expected WM_WINDOWPOSCHANGING and
3094 WM_WINDOWPOSCHANGED notification messages.
3095 */
3096 if(state >= STATE_PRE_WMNCCREATE) {
3097 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
3098 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
3099
3100 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
3101 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
3102 }
3103 return oldhwnd;
3104}
3105//******************************************************************************
3106//******************************************************************************
3107BOOL Win32BaseWindow::IsChild(HWND hwndParent)
3108{
3109 // PH: Optimizer won't unroll calls to getParent() even
3110 // in release build.
3111 Win32BaseWindow *_parent = getParent();
3112
3113 if(_parent)
3114 {
3115 if(_parent->getWindowHandle() == hwndParent)
3116 return TRUE;
3117
3118 return _parent->IsChild(hwndParent);
3119 }
3120 else
3121 return 0;
3122}
3123//******************************************************************************
3124//******************************************************************************
3125HWND Win32BaseWindow::GetTopWindow()
3126{
3127 HWND hwndTop;
3128 Win32BaseWindow *topwindow;
3129
3130 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3131 if(!isDesktopWindow())
3132 {
3133 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3134 //Note: GetTopWindow can't return a window that hasn't processed
3135 // WM_NCCREATE yet (verified in NT4, SP6)
3136 if(topwindow) {
3137 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3138 hwndTop = topwindow->getWindowHandle();
3139 }
3140 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3141 RELEASE_WNDOBJ(topwindow);
3142 return hwndTop;
3143 }
3144 if(topwindow) RELEASE_WNDOBJ(topwindow);
3145 return 0;
3146 }
3147 while(hwndTop) {
3148 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3149 //Note: GetTopWindow can't return a window that hasn't processed
3150 // WM_NCCREATE yet (verified in NT4, SP6)
3151 if(topwindow) {
3152 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3153 hwndTop = topwindow->getWindowHandle();
3154 }
3155 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3156 RELEASE_WNDOBJ(topwindow);
3157 return hwndTop;
3158 }
3159 if(topwindow) RELEASE_WNDOBJ(topwindow);
3160 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
3161 }
3162
3163 return 0;
3164}
3165//******************************************************************************
3166// Get the top-level parent for a child window.
3167//******************************************************************************
3168HWND Win32BaseWindow::GetTopParent()
3169{
3170 Win32BaseWindow *window = this;
3171 HWND hwndTopParent = 0;
3172
3173 lock();
3174 while(window && (window->getStyle() & WS_CHILD))
3175 {
3176 window = window->getParent();
3177 }
3178 if(window) {
3179 hwndTopParent = window->getWindowHandle();
3180 }
3181 unlock();
3182 return hwndTopParent;
3183}
3184//******************************************************************************
3185//TODO: Should not enumerate children that are created during the enumeration!
3186//TODO: Do this more efficiently
3187//******************************************************************************
3188BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
3189{
3190 BOOL rc = TRUE;
3191 HWND hwnd;
3192 Win32BaseWindow *prevchild = 0, *child = 0;
3193
3194 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
3195 lock();
3196 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
3197 {
3198 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
3199 hwnd = child->getWindowHandle();
3200 if(child->IsWindowDestroyed() || child->getOwner()) {
3201 continue; //shouldn't have an owner (Wine)
3202 }
3203 child->addRef();
3204 unlock();
3205 if(WrapCallback2((WNDPROC)lpfn, hwnd, lParam) == FALSE)
3206 {
3207 child->release();
3208 return FALSE;
3209 }
3210 child->release();
3211 lock();
3212 //check if the window still exists
3213 if(!::IsWindow(hwnd))
3214 {
3215 child = prevchild;
3216 if(child == NULL) break;
3217 continue;
3218 }
3219 if(child->getFirstChild() != NULL)
3220 {
3221 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
3222 child->addRef();
3223 unlock();
3224 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
3225 {
3226 child->release();
3227 return FALSE;
3228 }
3229 child->release();
3230 lock();
3231 }
3232 prevchild = child;
3233 }
3234 unlock();
3235 return rc;
3236}
3237//******************************************************************************
3238//Enumerate first-level children only and check thread id
3239//NOTE: NT4 returns first-level children in Z-order!
3240//******************************************************************************
3241BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
3242{
3243 Win32BaseWindow *wnd = NULL;
3244 HWND henum, hwnd, hwndWin32;
3245 ULONG tid, pid;
3246 BOOL rc;
3247
3248 //Enumerate all top-level windows and check the process and thread ids
3249 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3250 hwnd = OSLibWinGetNextWindow(henum);
3251
3252 while(hwnd)
3253 {
3254 wnd = GetWindowFromOS2FrameHandle(hwnd);
3255 if(wnd) {
3256 hwndWin32 = wnd->getWindowHandle();
3257 }
3258 else hwndWin32 = 0;
3259
3260 if(wnd) RELEASE_WNDOBJ(wnd);
3261
3262 if(hwndWin32) {
3263 OSLibWinQueryWindowProcess(hwnd, &pid, &tid);
3264
3265 if(dwThreadId == tid) {
3266 dprintf(("EnumThreadWindows: Found Window %x", hwndWin32));
3267 if((rc = WrapCallback2((WNDPROC)lpfn, hwndWin32, lParam)) == FALSE) {
3268 break;
3269 }
3270 }
3271 }
3272 hwnd = OSLibWinGetNextWindow(henum);
3273 }
3274 OSLibWinEndEnumWindows(henum);
3275 return TRUE;
3276}
3277//******************************************************************************
3278//Enumerate first-level children only
3279//******************************************************************************
3280BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
3281{
3282 Win32BaseWindow *window;
3283 BOOL rc;
3284 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
3285 DWORD dwStyle;
3286
3287 dprintf(("EnumWindows %x %x", lpfn, lParam));
3288
3289 for(int i=0;i<MAX_WINDOW_HANDLES;i++)
3290 {
3291 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3292 if(window) {
3293 if(window->getWindowHandle() != hwnd) {
3294 dprintf(("CORRUPT WINDOW %x %x", window, hwnd));
3295 }
3296 RELEASE_WNDOBJ(window);
3297 dwStyle = ::GetWindowLongA(hwnd, GWL_STYLE);
3298 if ((dwStyle & WS_POPUP) || ((dwStyle & WS_CAPTION) == WS_CAPTION))
3299 {
3300 dprintf2(("EnumWindows: Found Window %x", hwnd));
3301 if((rc = WrapCallback2((WNDPROC)lpfn, hwnd, lParam)) == FALSE) {
3302 break;
3303 }
3304 }
3305 }
3306 hwnd++;
3307 }
3308 return TRUE;
3309}
3310//******************************************************************************
3311//******************************************************************************
3312HWND Win32BaseWindow::FindWindowById(int id)
3313{
3314 HWND hwnd;
3315
3316 lock();
3317 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3318 {
3319 if (child->getWindowId() == id)
3320 {
3321 hwnd = child->getWindowHandle();
3322 unlock();
3323 return hwnd;
3324 }
3325 }
3326 unlock();
3327 return 0;
3328}
3329//******************************************************************************
3330//TODO:
3331//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3332//the current process owns them.
3333//******************************************************************************
3334HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3335{
3336 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3337 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3338 Win32BaseWindow *firstchild = child;
3339
3340 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3341 if((hwndParent != 0 && !parent) ||
3342 (hwndChildAfter != 0 && !child) ||
3343 (hwndParent == 0 && hwndChildAfter != 0))
3344 {
3345 if(parent) RELEASE_WNDOBJ(parent);
3346 if(firstchild) RELEASE_WNDOBJ(firstchild);
3347 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3348 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3349 return 0;
3350 }
3351 SetLastError(0);
3352 if(hwndParent != 0)
3353 {//if the current process owns the window, just do a quick search
3354 lock(&critsect);
3355 child = (Win32BaseWindow *)parent->getFirstChild();
3356 if(hwndChildAfter != 0)
3357 {
3358 while(child)
3359 {
3360 if(child->getWindowHandle() == hwndChildAfter)
3361 {
3362 child = (Win32BaseWindow *)child->getNextChild();
3363 break;
3364 }
3365 child = (Win32BaseWindow *)child->getNextChild();
3366 }
3367 }
3368 while(child)
3369 {
3370 //According to Wine, the class doesn't need to be specified
3371 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3372 (!lpszWindow || child->hasWindowName(lpszWindow)))
3373 {
3374 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3375 HWND hwndChild = child->getWindowHandle();
3376 unlock(&critsect);
3377 if(parent) RELEASE_WNDOBJ(parent);
3378 if(firstchild) RELEASE_WNDOBJ(firstchild);
3379 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3380 return hwndChild;
3381 }
3382 child = (Win32BaseWindow *)child->getNextChild();
3383 }
3384 unlock(&critsect);
3385 if(parent) RELEASE_WNDOBJ(parent);
3386 if(firstchild) RELEASE_WNDOBJ(firstchild);
3387 }
3388 else {
3389 Win32BaseWindow *wnd;
3390 HWND henum, hwnd;
3391
3392 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3393 hwnd = OSLibWinGetNextWindow(henum);
3394
3395 while(hwnd)
3396 {
3397 wnd = GetWindowFromOS2FrameHandle(hwnd);
3398 if(wnd) {
3399 //According to Wine, the class doesn't need to be specified
3400 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3401 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3402 {
3403 OSLibWinEndEnumWindows(henum);
3404 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3405 HWND hwndret = wnd->getWindowHandle();
3406 RELEASE_WNDOBJ(wnd);
3407 return hwndret;
3408 }
3409 RELEASE_WNDOBJ(wnd);
3410 }
3411 hwnd = OSLibWinGetNextWindow(henum);
3412 }
3413 OSLibWinEndEnumWindows(henum);
3414 if(parent) RELEASE_WNDOBJ(parent);
3415 if(firstchild) RELEASE_WNDOBJ(firstchild);
3416 }
3417 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3418 return 0;
3419}
3420//******************************************************************************
3421//******************************************************************************
3422HWND Win32BaseWindow::GetWindow(UINT uCmd)
3423{
3424 HWND hwndRelated = 0;
3425 Win32BaseWindow *window;
3426
3427 switch(uCmd)
3428 {
3429 case GW_HWNDFIRST:
3430 window = (Win32BaseWindow *)getParent();
3431 if(window)
3432 {
3433 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3434 window = GetWindowFromOS2FrameHandle(hwndRelated);
3435 if(window) {
3436 hwndRelated = window->getWindowHandle();
3437 RELEASE_WNDOBJ(window);
3438 }
3439 else hwndRelated = 0;
3440 }
3441 else {
3442 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3443 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3444 }
3445 break;
3446
3447 case GW_HWNDLAST:
3448 window = (Win32BaseWindow *)getParent();
3449 if(window) {
3450 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3451 dprintf(("os2 handle %x", hwndRelated));
3452 window = GetWindowFromOS2FrameHandle(hwndRelated);
3453 if(window) {
3454 hwndRelated = window->getWindowHandle();
3455 RELEASE_WNDOBJ(window);
3456 }
3457 else hwndRelated = 0;
3458 }
3459 else {
3460 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3461 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3462 }
3463 break;
3464
3465 case GW_HWNDNEXT:
3466 if(getParent()) {
3467 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3468 window = GetWindowFromOS2FrameHandle(hwndRelated);
3469 if(window) {
3470 hwndRelated = window->getWindowHandle();
3471 RELEASE_WNDOBJ(window);
3472 }
3473 else hwndRelated = 0;
3474 }
3475 else {
3476 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3477 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3478 }
3479 break;
3480
3481 case GW_HWNDPREV:
3482 if(getParent()) {
3483 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3484 window = GetWindowFromOS2FrameHandle(hwndRelated);
3485 if(window) {
3486 hwndRelated = window->getWindowHandle();
3487 RELEASE_WNDOBJ(window);
3488 }
3489 else hwndRelated = 0;
3490 }
3491 else {
3492 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3493 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3494 }
3495 break;
3496
3497 case GW_OWNER:
3498 {
3499 Win32BaseWindow *owner = getOwner();
3500 if(owner) {
3501 hwndRelated = owner->getWindowHandle();
3502 }
3503 break;
3504 }
3505
3506 case GW_CHILD:
3507 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3508 window = GetWindowFromOS2FrameHandle(hwndRelated);
3509
3510 //Before a window has processed WM_NCCREATE:
3511 //- GetWindow(parent, GW_CHILD) can't return that window handle
3512 //(verified in NT4, SP6)
3513 if(window) {
3514 if(window->state >= STATE_POST_WMNCCREATE) {
3515 hwndRelated = window->getWindowHandle();
3516 RELEASE_WNDOBJ(window);
3517 }
3518 else {
3519 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3520 RELEASE_WNDOBJ(window);
3521 }
3522 }
3523 else hwndRelated = 0;
3524
3525 break;
3526
3527 //for internal use only
3528 case GW_HWNDNEXTCHILD:
3529 lock();
3530 window = (Win32BaseWindow *)getNextChild();
3531 if(window) {
3532 hwndRelated = window->getWindowHandle();
3533 }
3534 else hwndRelated = 0;
3535 unlock();
3536 break;
3537
3538 case GW_HWNDPREVCHILD:
3539 DebugInt3();
3540 break;
3541
3542 case GW_HWNDFIRSTCHILD:
3543 lock();
3544 window = (Win32BaseWindow *)getFirstChild();
3545 if(window) {
3546 hwndRelated = window->getWindowHandle();
3547 }
3548 else hwndRelated = 0;
3549 unlock();
3550 break;
3551
3552 case GW_HWNDLASTCHILD:
3553 lock();
3554 window = (Win32BaseWindow *)getFirstChild();
3555 if(window) {
3556 while (window->getNextChild())
3557 {
3558 window = (Win32BaseWindow *)window->getNextChild();
3559 }
3560 hwndRelated = window->getWindowHandle();
3561 }
3562 else hwndRelated = 0;
3563 unlock();
3564 break;
3565 }
3566end:
3567 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3568 return hwndRelated;
3569}
3570//******************************************************************************
3571//******************************************************************************
3572PRECT Win32BaseWindow::getWindowRect()
3573{
3574 return &rectWindow;
3575}
3576//******************************************************************************
3577//******************************************************************************
3578HWND Win32BaseWindow::SetActiveWindow()
3579{
3580 HWND hwndActive;
3581
3582 dprintf(("SetActiveWindow %x", getWindowHandle()));
3583 if(getStyle() & WS_CHILD) {
3584// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3585 dprintf(("WARNING: Window is a child or disabled"));
3586 return 0;
3587 }
3588
3589 if(GetActiveWindow() == getWindowHandle()) {
3590 dprintf(("Window already active"));
3591 return getWindowHandle();
3592 }
3593 if (HOOK_IsHooked( WH_CBT ))
3594 {
3595 CBTACTIVATESTRUCT cbta;
3596 LRESULT ret;
3597
3598 cbta.fMouse = FALSE;
3599 cbta.hWndActive = GetActiveWindow();
3600 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3601 if(ret)
3602 {
3603 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3604 return cbta.hWndActive;
3605 }
3606 }
3607 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3608
3609// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3610// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3611// }
3612 hwndActive = GetActiveWindow();
3613 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3614}
3615//******************************************************************************
3616//Used to change active status of an mdi window
3617//******************************************************************************
3618BOOL Win32BaseWindow::DeactivateChildWindow()
3619{
3620 /* child windows get a WM_CHILDACTIVATE message */
3621 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3622 {
3623 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3624 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3625 return TRUE;
3626 }
3627 DebugInt3(); //should not be called for non-child window
3628 return FALSE;
3629}
3630//******************************************************************************
3631//WM_ENABLE is sent to hwnd, but not to its children (as it should be)
3632//******************************************************************************
3633BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3634{
3635 BOOL rc;
3636
3637 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3638 //return true if previous state was disabled, else false (sdk docs)
3639 rc = (getStyle() & WS_DISABLED) != 0;
3640 if(rc && !fEnable) {
3641 SendMessageA(getWindowHandle(), WM_CANCELMODE, 0, 0);
3642 }
3643 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3644 if(fEnable == FALSE) {
3645 //SvL: No need to clear focus as PM already does this
3646 if(getWindowHandle() == GetCapture()) {
3647 ReleaseCapture(); /* A disabled window can't capture the mouse */
3648 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3649 }
3650 }
3651 return rc;
3652}
3653//******************************************************************************
3654//******************************************************************************
3655BOOL Win32BaseWindow::CloseWindow()
3656{
3657 if (::GetWindowLongW( getWindowHandle() , GWL_STYLE ) & WS_CHILD) return FALSE;
3658 ShowWindow( SW_MINIMIZE );
3659 return TRUE;
3660}
3661//******************************************************************************
3662//TODO: Not be 100% correct; should return active window of current thread
3663// or NULL when there is none -> WinQueryActiveWindow just returns
3664// the current active window
3665//******************************************************************************
3666HWND Win32BaseWindow::GetActiveWindow()
3667{
3668 HWND hwndActive;
3669
3670 hwndActive = OSLibWinQueryActiveWindow();
3671 return OS2ToWin32Handle(hwndActive);
3672}
3673//******************************************************************************
3674//******************************************************************************
3675BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3676{
3677 INT len = GetWindowTextLength(fUnicode);
3678 BOOL res;
3679
3680 if (wndname == NULL)
3681 return (len == 0);
3682
3683 len++;
3684 if (fUnicode)
3685 {
3686 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3687
3688 GetWindowTextW(text,len);
3689 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3690 free(text);
3691 }
3692 else
3693 {
3694 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3695
3696 GetWindowTextA(text,len);
3697 res = (strcmp(text,wndname) == 0);
3698 free(text);
3699 }
3700
3701 return res;
3702}
3703//******************************************************************************
3704//******************************************************************************
3705CHAR *Win32BaseWindow::getWindowNamePtrA()
3706{
3707 INT len = GetWindowTextLength(FALSE);
3708 CHAR *text;
3709
3710 if (len == 0) return NULL;
3711 len++;
3712 text = (CHAR*)malloc(len*sizeof(CHAR));
3713 GetWindowTextA(text,len);
3714
3715 return text;
3716}
3717//******************************************************************************
3718//******************************************************************************
3719WCHAR *Win32BaseWindow::getWindowNamePtrW()
3720{
3721 INT len = GetWindowTextLength(TRUE);
3722 WCHAR *text;
3723
3724 if (len == 0) return NULL;
3725 len++;
3726 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3727 GetWindowTextW(text,len);
3728
3729 return text;
3730}
3731//******************************************************************************
3732//******************************************************************************
3733VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3734{
3735 if (namePtr) free(namePtr);
3736}
3737//******************************************************************************
3738//When using this API for a window that was created by a different process, NT
3739//does NOT send WM_GETTEXTLENGTH.
3740//******************************************************************************
3741int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3742{
3743 //if the destination window is created by this process, send message
3744 if(dwProcessId == currentProcessId)
3745 {
3746 if(fUnicode) {
3747 return SendMessageW(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3748 }
3749 else return SendMessageA(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3750 }
3751 //else get data directory from window structure
3752 //TODO: must lock window structure.... (TODO)
3753 return fUnicode ? windowNameLengthW : windowNameLengthA;
3754}
3755//******************************************************************************
3756//When using this API for a window that was created by a different process, NT
3757//does NOT send WM_GETTEXT.
3758//******************************************************************************
3759int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3760{
3761 //if the destination window is created by this process, send message
3762 if(dwProcessId == currentProcessId) {
3763 return SendMessageA(getWindowHandle(),WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3764 }
3765
3766 //else get data directory from window structure
3767 if (!lpsz || !cch) return 0;
3768 if (!windowNameA) lpsz[0] = 0;
3769 else lstrcpynA( lpsz, windowNameA, cch );
3770 return strlen( lpsz );
3771}
3772//******************************************************************************
3773//When using this API for a window that was created by a different process, NT
3774//does NOT send WM_GETTEXT.
3775//******************************************************************************
3776int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3777{
3778 //if the destination window is created by this process, send message
3779 if(dwProcessId == currentProcessId) {
3780 return ::SendMessageW(getWindowHandle(), WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3781 }
3782 //else get data directory from window structure
3783 if (!lpsz || !cch)
3784 return 0;
3785 if (!windowNameW)
3786 lpsz[0] = 0;
3787 else
3788 lstrcpynW( lpsz, windowNameW, cch );
3789
3790 return strlenW( lpsz );
3791}
3792//******************************************************************************
3793//TODO: How does this work when the target window belongs to a different process???
3794//******************************************************************************
3795BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3796{
3797 return SendMessageA(getWindowHandle(),WM_SETTEXT,0,(LPARAM)lpsz);
3798}
3799//******************************************************************************
3800//******************************************************************************
3801BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3802{
3803 return SendMessageW(getWindowHandle(), WM_SETTEXT,0,(LPARAM)lpsz);
3804}
3805//******************************************************************************
3806//******************************************************************************
3807LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3808{
3809 LONG oldval;
3810
3811 switch(index) {
3812 case GWL_EXSTYLE:
3813 {
3814 STYLESTRUCT ss;
3815
3816 if(dwExStyle == value) {
3817 oldval = value;
3818 break;
3819 }
3820 ss.styleOld = dwExStyle;
3821 ss.styleNew = value;
3822 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3823 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3824 setExStyle(ss.styleNew);
3825 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3826
3827 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3828 getStyle(), getExStyle(),ss.styleOld);
3829
3830 oldval = ss.styleOld;
3831 break;
3832 }
3833 case GWL_STYLE:
3834 {
3835 STYLESTRUCT ss;
3836
3837 //SvL: TODO: Can you change minimize or maximize status here too?
3838
3839 if(dwStyle == value) {
3840 oldval = value;
3841 break;
3842 }
3843 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3844
3845 //Changing WS_CHILD style is allowed
3846 ss.styleOld = getStyle();
3847 ss.styleNew = value;
3848 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3849 setStyle(ss.styleNew);
3850 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3851
3852 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3853 getStyle(), getExStyle(),ss.styleOld);
3854
3855 //TODO: Might not be correct to use ShowWindow here
3856 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3857 if(ss.styleNew & WS_VISIBLE)
3858 ShowWindow(SW_SHOWNOACTIVATE);
3859 else ShowWindow(SW_HIDE);
3860 }
3861
3862#ifdef DEBUG
3863 PrintWindowStyle(ss.styleNew, 0);
3864#endif
3865 oldval = ss.styleOld;
3866 break;
3867 }
3868 case GWL_WNDPROC:
3869 {
3870 //Note: Type of SetWindowLong determines new window proc type
3871 // UNLESS the new window proc has already been registered
3872 // (use the old type in that case)
3873 // (VERIFIED in NT 4, SP6)
3874 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3875 if(type == WIN_PROC_INVALID) {
3876 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3877 }
3878 oldval = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3879 dprintf(("SetWindowLong%c GWL_WNDPROC %x old %x new wndproc %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), oldval, value));
3880 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3881 break;
3882 }
3883 case GWL_HINSTANCE:
3884 oldval = hInstance;
3885 hInstance = value;
3886 break;
3887
3888 case GWL_HWNDPARENT:
3889 dprintf(("GWL_ID GWL_HWNDPARENT %x, new %x", GetParent(), value));
3890 oldval = SetParent((HWND)value);
3891 break;
3892
3893 case GWL_ID:
3894 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3895 oldval = getWindowId();
3896 setWindowId(value);
3897 break;
3898
3899 case GWL_USERDATA:
3900 oldval = userData;
3901 userData = value;
3902 break;
3903
3904 default:
3905 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3906 {
3907 oldval = *(ULONG *)(userWindowBytes + index);
3908 *(ULONG *)(userWindowBytes + index) = value;
3909 break;
3910 }
3911 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3912 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3913 return 0;
3914 }
3915 //Note: NT4, SP6 does not set the last error to 0
3916 SetLastError(ERROR_SUCCESS);
3917 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3918 return oldval;
3919}
3920//******************************************************************************
3921//******************************************************************************
3922ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3923{
3924 ULONG value;
3925
3926 switch(index) {
3927 case GWL_EXSTYLE:
3928 value = dwExStyle;
3929 break;
3930 case GWL_STYLE:
3931 value = dwStyle;
3932 break;
3933 case GWL_WNDPROC:
3934 value = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3935 break;
3936 case GWL_HINSTANCE:
3937 value = hInstance;
3938 break;
3939 case GWL_HWNDPARENT:
3940 value = GetParent();
3941 break;
3942 case GWL_ID:
3943 value = getWindowId();
3944 break;
3945 case GWL_USERDATA:
3946 value = userData;
3947 break;
3948 default:
3949 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3950 {
3951 value = *(ULONG *)(userWindowBytes + index);
3952 break;
3953 }
3954 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3955 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3956 return 0;
3957 }
3958 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3959 //Note: NT4, SP6 does not set the last error to 0
3960 SetLastError(ERROR_SUCCESS);
3961 return value;
3962}
3963//******************************************************************************
3964//******************************************************************************
3965WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3966{
3967 WORD oldval;
3968
3969 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3970 {
3971 oldval = *(WORD *)(userWindowBytes + index);
3972 *(WORD *)(userWindowBytes + index) = value;
3973 //Note: NT4, SP6 does not set the last error to 0
3974 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3975 SetLastError(ERROR_SUCCESS);
3976 return oldval;
3977 }
3978 switch(index)
3979 {
3980 case GWW_HINSTANCE:
3981 oldval = hInstance;
3982 hInstance = value;
3983 break;
3984
3985 case GWW_HWNDPARENT:
3986 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3987 break;
3988
3989 case GWW_ID:
3990 oldval = getWindowId();
3991 setWindowId(value);
3992 break;
3993
3994 default:
3995 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3996 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3997 return 0;
3998 }
3999 //Note: NT4, SP6 does not set the last error to 0
4000 SetLastError(ERROR_SUCCESS);
4001 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
4002 return oldval;
4003}
4004//******************************************************************************
4005//******************************************************************************
4006WORD Win32BaseWindow::GetWindowWord(int index)
4007{
4008 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
4009 {
4010 //Note: NT4, SP6 does not set the last error to 0
4011 SetLastError(ERROR_SUCCESS);
4012 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
4013 return *(WORD *)(userWindowBytes + index);
4014 }
4015 switch(index)
4016 {
4017 case GWW_ID:
4018 if(HIWORD(getWindowId()))
4019 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
4020 return (WORD)getWindowId();
4021
4022 case GWW_HWNDPARENT:
4023 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
4024 return (WORD) GetParent();
4025
4026 case GWW_HINSTANCE:
4027 if (HIWORD(hInstance))
4028 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
4029 return (WORD)hInstance;
4030 }
4031
4032 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
4033 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
4034 return 0;
4035}
4036//******************************************************************************
4037// Win32BaseWindow::setVisibleRgnNotifyProc
4038//
4039// Sets the visible region change notification handler. Called when
4040// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4041//
4042// Parameters:
4043// VISRGN_NOTIFY_PROC lpNotifyProc - notification handler
4044// DWORD dwUserData - caller supplied parameter for handler invocations
4045//
4046// Returns:
4047// TRUE - Success
4048// FALSE - Failure
4049//
4050//******************************************************************************
4051BOOL Win32BaseWindow::setVisibleRgnNotifyProc(VISRGN_NOTIFY_PROC lpNotifyProc, DWORD dwUserData)
4052{
4053 lpVisRgnNotifyProc = lpNotifyProc;
4054 dwVisRgnNotifyParam = dwUserData;
4055 return TRUE;
4056}
4057//******************************************************************************
4058// Win32BaseWindow::callVisibleRgnNotifyProc
4059//
4060// Call the visible region change notification handler. Called when
4061// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4062//
4063// Parameters:
4064// BOOL fDrawingAllowed - drawing is allowed or not
4065//
4066// Returns:
4067// TRUE - Success
4068// FALSE - Failure
4069//
4070//******************************************************************************
4071void Win32BaseWindow::callVisibleRgnNotifyProc(BOOL fDrawingAllowed)
4072{
4073 if(fDrawingAllowed) {
4074 fWindowLocked = TRUE;
4075 }
4076 else {
4077 fWindowLocked = FALSE;
4078 }
4079 if(lpVisRgnNotifyProc) {
4080 lpVisRgnNotifyProc(getWindowHandle(), fDrawingAllowed, dwVisRgnNotifyParam);
4081 }
4082}
4083//******************************************************************************
4084// Win32BaseWindow::queryOpenDCs
4085//
4086// Return the DCs that are currently open for this window
4087//
4088// Parameters:
4089// HDC *phdcWindow - pointer to HDC array (IN)
4090// int chdcWindow - size of HDC array (IN)
4091// int *pnrdcs - number of HDCs returned (OUT)
4092//
4093// Returns:
4094// TRUE - Success
4095// FALSE - Failure
4096//
4097//******************************************************************************
4098BOOL Win32BaseWindow::queryOpenDCs(HDC *phdcWindow, int chdcWindow, int *pnrdcs)
4099{
4100 if(nrOpenDCs == 0) return FALSE;
4101
4102 if(chdcWindow < nrOpenDCs) {
4103 DebugInt3();
4104 return FALSE;
4105 }
4106
4107 lock(&critsect);
4108 int j = 0;
4109 for(int i=0;i<MAX_OPENDCS && j<nrOpenDCs;i++) {
4110 if(hdcWindow[i] != 0) {
4111 phdcWindow[j] = hdcWindow[i];
4112 j++;
4113 }
4114 }
4115 unlock(&critsect);
4116 *pnrdcs = nrOpenDCs;
4117 return TRUE;
4118}
4119//******************************************************************************
4120// Win32BaseWindow::addOpenDC
4121//
4122// Add DC to list of open DCS
4123//
4124// Parameters:
4125// HDC hdc - HDC to be added to our list of open DCs
4126//
4127// Returns:
4128//
4129//******************************************************************************
4130void Win32BaseWindow::addOpenDC(HDC hdc)
4131{
4132 lock(&critsect);
4133 for(int i=0;i<MAX_OPENDCS;i++) {
4134 if(hdcWindow[i] == 0) {
4135 hdcWindow[i] = hdc;
4136 break;
4137 }
4138 }
4139 unlock(&critsect);
4140 if(i == MAX_OPENDCS) {
4141 dprintf(("Open DCs:"));
4142 for(int i=0;i<MAX_OPENDCS;i++) {
4143 dprintf(("Window %x DC %x", WindowFromDC(hdcWindow[i]), hdcWindow[i]));
4144 }
4145 DebugInt3(); //no room!
4146 return;
4147 }
4148
4149 dprintf2(("Win32BaseWindow::addOpenDC %x %x %d", getWindowHandle(), hdc, nrOpenDCs+1));
4150 nrOpenDCs++;
4151}
4152//******************************************************************************
4153// Win32BaseWindow::removeOpenDC
4154//
4155// Remove DC from list of open DCS
4156//
4157// Parameters:
4158// HDC hdc - HDC to be removed from our list of open DCs
4159//
4160// Returns:
4161//
4162//******************************************************************************
4163void Win32BaseWindow::removeOpenDC(HDC hdc)
4164{
4165 if(nrOpenDCs == 0) {
4166 dprintf(("Win32BaseWindow::removeOpenDC %x hdc %x not found!! (1)", getWindowHandle(), hdc));
4167 //Some applications call ReleaseDC before EndPaint
4168// DebugInt3();
4169 return;
4170 }
4171 lock(&critsect);
4172 for(int i=0;i<MAX_OPENDCS;i++) {
4173 if(hdcWindow[i] == hdc) {
4174 hdcWindow[i] = 0;
4175 break;
4176 }
4177 }
4178 unlock(&critsect);
4179 if(i == MAX_OPENDCS) {
4180 dprintf(("Win32BaseWindow::removeOpenDC hdc %x not found!!", hdc));
4181 DebugInt3(); //not found
4182 return;
4183 }
4184 dprintf2(("Win32BaseWindow::removeOpenDC %x %x", getWindowHandle(), hdc, nrOpenDCs-1));
4185 nrOpenDCs--;
4186}
4187//******************************************************************************
4188//Locates window in linked list and increases reference count (if found)
4189//Window object must be unreferenced after usage
4190//******************************************************************************
4191Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
4192{
4193 Win32BaseWindow *window;
4194
4195////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
4196//// while browsing
4197//// Not thread safe now!
4198//// lock(&critsect);
4199 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
4200 if(window) {
4201//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
4202 window->addRef();
4203 }
4204//// unlock(&critsect);
4205 return window;
4206 }
4207//// unlock(&critsect);
4208// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
4209 return NULL;
4210}
4211//******************************************************************************
4212//Locates window in linked list and increases reference count (if found)
4213//Window object must be unreferenced after usage
4214//******************************************************************************
4215Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
4216{
4217 DWORD magic;
4218 HWND hwnd;
4219
4220 if(hwndOS2 == OSLIB_HWND_DESKTOP)
4221 {
4222 windowDesktop->addRef();
4223 return windowDesktop;
4224 }
4225
4226 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
4227 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
4228
4229 if(hwnd && CheckMagicDword(magic)) {
4230 return GetWindowFromHandle(hwnd);
4231 }
4232// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
4233
4234 //Now check if it's a fake window
4235 Win32FakeWindow *window = Win32FakeWindow::GetWindowFromOS2Handle(hwndOS2);
4236 if(window) {
4237 return window;
4238 }
4239 return 0;
4240}
4241//******************************************************************************
4242//Locates window in linked list and increases reference count (if found)
4243//Window object must be unreferenced after usage
4244//******************************************************************************
4245Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
4246{
4247 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
4248}
4249//******************************************************************************
4250//******************************************************************************
4251HWND WIN32API Win32ToOS2Handle(HWND hwnd)
4252{
4253 HWND hwndOS2;
4254
4255 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4256
4257 if(window) {
4258 hwndOS2 = window->getOS2WindowHandle();
4259 RELEASE_WNDOBJ(window);
4260 return hwndOS2;
4261 }
4262// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4263 return hwnd;
4264}
4265//******************************************************************************
4266//******************************************************************************
4267HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
4268{
4269 HWND hwndOS2;
4270
4271 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4272
4273 if(window) {
4274 hwndOS2 = window->getOS2FrameWindowHandle();
4275 RELEASE_WNDOBJ(window);
4276 return hwndOS2;
4277 }
4278// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4279 return hwnd;
4280}
4281//******************************************************************************
4282//******************************************************************************
4283HWND WIN32API OS2ToWin32Handle(HWND hwnd)
4284{
4285 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
4286 HWND hwndWin32;
4287
4288 if(window) {
4289 hwndWin32 = window->getWindowHandle();
4290 RELEASE_WNDOBJ(window);
4291 return hwndWin32;
4292 }
4293 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
4294 if(window) {
4295 hwndWin32 = window->getWindowHandle();
4296 RELEASE_WNDOBJ(window);
4297 return hwndWin32;
4298 }
4299
4300// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
4301 return 0;
4302// else return hwnd; //OS/2 window handle
4303}
4304#ifdef DEBUG
4305LONG Win32BaseWindow::addRef()
4306{
4307// dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
4308 return GenericObject::addRef();
4309}
4310//******************************************************************************
4311//******************************************************************************
4312LONG Win32BaseWindow::release(char *function, int line)
4313{
4314// dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
4315 return GenericObject::release();
4316}
4317#endif
4318//******************************************************************************
4319//******************************************************************************
4320GenericObject *Win32BaseWindow::windows = NULL;
4321VMutex Win32BaseWindow::critsect;
4322
4323//******************************************************************************
4324//******************************************************************************
4325#ifdef DEBUG
4326void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
4327{
4328 char style[256] = "";
4329 char exstyle[256] = "";
4330
4331 /* Window styles */
4332 if(dwStyle & WS_CHILD)
4333 strcat(style, "WS_CHILD ");
4334 if(dwStyle & WS_POPUP)
4335 strcat(style, "WS_POPUP ");
4336 if(dwStyle & WS_VISIBLE)
4337 strcat(style, "WS_VISIBLE ");
4338 if(dwStyle & WS_DISABLED)
4339 strcat(style, "WS_DISABLED ");
4340 if(dwStyle & WS_CLIPSIBLINGS)
4341 strcat(style, "WS_CLIPSIBLINGS ");
4342 if(dwStyle & WS_CLIPCHILDREN)
4343 strcat(style, "WS_CLIPCHILDREN ");
4344 if(dwStyle & WS_MAXIMIZE)
4345 strcat(style, "WS_MAXIMIZE ");
4346 if(dwStyle & WS_MINIMIZE)
4347 strcat(style, "WS_MINIMIZE ");
4348 if(dwStyle & WS_GROUP)
4349 strcat(style, "WS_GROUP ");
4350 if(dwStyle & WS_TABSTOP)
4351 strcat(style, "WS_TABSTOP ");
4352
4353 if((dwStyle & WS_CAPTION) == WS_CAPTION)
4354 strcat(style, "WS_CAPTION ");
4355 if(dwStyle & WS_DLGFRAME)
4356 strcat(style, "WS_DLGFRAME ");
4357 if(dwStyle & WS_BORDER)
4358 strcat(style, "WS_BORDER ");
4359
4360 if(dwStyle & WS_VSCROLL)
4361 strcat(style, "WS_VSCROLL ");
4362 if(dwStyle & WS_HSCROLL)
4363 strcat(style, "WS_HSCROLL ");
4364 if(dwStyle & WS_SYSMENU)
4365 strcat(style, "WS_SYSMENU ");
4366 if(dwStyle & WS_THICKFRAME)
4367 strcat(style, "WS_THICKFRAME ");
4368 if(dwStyle & WS_MINIMIZEBOX)
4369 strcat(style, "WS_MINIMIZEBOX ");
4370 if(dwStyle & WS_MAXIMIZEBOX)
4371 strcat(style, "WS_MAXIMIZEBOX ");
4372
4373 if(dwExStyle & WS_EX_DLGMODALFRAME)
4374 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
4375 if(dwExStyle & WS_EX_ACCEPTFILES)
4376 strcat(exstyle, "WS_EX_ACCEPTFILES ");
4377 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
4378 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
4379 if(dwExStyle & WS_EX_TOPMOST)
4380 strcat(exstyle, "WS_EX_TOPMOST ");
4381 if(dwExStyle & WS_EX_TRANSPARENT)
4382 strcat(exstyle, "WS_EX_TRANSPARENT ");
4383
4384 if(dwExStyle & WS_EX_MDICHILD)
4385 strcat(exstyle, "WS_EX_MDICHILD ");
4386 if(dwExStyle & WS_EX_TOOLWINDOW)
4387 strcat(exstyle, "WS_EX_TOOLWINDOW ");
4388 if(dwExStyle & WS_EX_WINDOWEDGE)
4389 strcat(exstyle, "WS_EX_WINDOWEDGE ");
4390 if(dwExStyle & WS_EX_CLIENTEDGE)
4391 strcat(exstyle, "WS_EX_CLIENTEDGE ");
4392 if(dwExStyle & WS_EX_CONTEXTHELP)
4393 strcat(exstyle, "WS_EX_CONTEXTHELP ");
4394 if(dwExStyle & WS_EX_RIGHT)
4395 strcat(exstyle, "WS_EX_RIGHT ");
4396 if(dwExStyle & WS_EX_LEFT)
4397 strcat(exstyle, "WS_EX_LEFT ");
4398 if(dwExStyle & WS_EX_RTLREADING)
4399 strcat(exstyle, "WS_EX_RTLREADING ");
4400 if(dwExStyle & WS_EX_LTRREADING)
4401 strcat(exstyle, "WS_EX_LTRREADING ");
4402 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
4403 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
4404 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
4405 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
4406 if(dwExStyle & WS_EX_CONTROLPARENT)
4407 strcat(exstyle, "WS_EX_CONTROLPARENT ");
4408 if(dwExStyle & WS_EX_STATICEDGE)
4409 strcat(exstyle, "WS_EX_STATICEDGE ");
4410 if(dwExStyle & WS_EX_APPWINDOW)
4411 strcat(exstyle, "WS_EX_APPWINDOW ");
4412
4413 dprintf(("Window style: %x %s", dwStyle, style));
4414 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
4415}
4416#endif
4417//******************************************************************************
4418//******************************************************************************
Note: See TracBrowser for help on using the repository browser.