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

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

Undo interpreting strings as ANSI for certain OSLib APIs modified in the previous commits as it breaks the common logic where many other OSLib calls (e.g. all dealig with file names) seem to expect the OEM (OS/2) encoding.

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