source: trunk/src/user32/win32wbase.cpp

Last change on this file was 22135, checked in by dmik, 8 years ago

user32: Make r22134 actually work.

It would not due to using a virtual function from the base destructor
(which always calls the base version instead of the derived).

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