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

Last change on this file since 10275 was 10275, checked in by sandervl, 22 years ago

PM windows should have no owner if none is specified. (instead of their parent)

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