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

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

Keep track of all open DCs and query the visible region during WM_VRNENABLED to work around a PM bug

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