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

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

user32: Fixed incorrect code page translation of window title text (seen if the target window PM thread is already switched to the Windows ANSI code page as in case of windows created on threads other than main, like in Java). See #24.

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