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

Last change on this file since 21987 was 21987, checked in by dmik, 13 years ago

user32: Fix WM_MOUSEACTIVATE and WM_PARENTNOTIFY behavior.

In particular:

  • Don't send these messages on mouse button release.
  • Send WM_PARENTNOTIFY before WM_MOUSEACTIVATE.

Both changes reflect the actual behavior of Windows XP.

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