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

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

Do not send any SetWindowPos related messages if the state of the window doesn't change

File size: 152.4 KB
Line 
1/* $Id: win32wbase.cpp,v 1.373 2003-05-14 11:40:17 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 NotifyParent(msg->message, msg->wParam, 0);
1182 break;
1183 }
1184 }
1185 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1186}
1187//******************************************************************************
1188//******************************************************************************
1189ULONG Win32BaseWindow::MsgPaint(ULONG tmp, ULONG select)
1190{
1191 if (select && IsWindowIconic())
1192 return SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1193 else
1194 return SendMessageA(getWindowHandle(),WM_PAINT, 0, 0);
1195}
1196//******************************************************************************
1197//
1198// Win32BaseWindow::saveAndValidateUpdateRegion
1199//
1200// If an application doesn't validate the update region while processing
1201// WM_PAINT, then we must remember it for the next time. Also validates
1202// the current update region.
1203//
1204// Parameters:
1205// Returns:
1206//
1207// NOTE:
1208// Windows will only send a WM_PAINT once until another part of the
1209// window is invalidated. Unfortunately PM keeps on sending
1210// WM_PAINT messages until we validate the update region.
1211//
1212// This affects UpdateWindow, RedrawWindow, GetUpdateRgn, GetUpdateRect,
1213// BeginPaint and the next WM_PAINT message.
1214//
1215//******************************************************************************
1216void Win32BaseWindow::saveAndValidateUpdateRegion()
1217{
1218 if(hUpdateRegion == NULL) {
1219 hUpdateRegion = ::CreateRectRgn(0, 0, 1, 1);
1220 }
1221
1222 dprintf(("Win32BaseWindow::saveAndValidateUpdateRegion; marked dirty!"));
1223
1224 //save update region
1225 ::GetUpdateRgn(getWindowHandle(), hUpdateRegion, FALSE);
1226
1227 //and validate it so PM won't bother us again
1228 ::ValidateRgn(getWindowHandle(), hUpdateRegion);
1229
1230 //we just pretend the entire window is invalid. easier this way
1231 fDirtyUpdateRegion = TRUE;
1232}
1233//******************************************************************************
1234//
1235// Win32BaseWindow::checkForDirtyUpdateRegion
1236//
1237// If an application doesn't validate the update region while processing
1238// WM_PAINT, then we must remember it for the next time. If the window has
1239// a dirty update region, then invalidate that region.
1240//
1241// Parameters:
1242// Returns:
1243//
1244// NOTE:
1245//
1246//******************************************************************************
1247void Win32BaseWindow::checkForDirtyUpdateRegion()
1248{
1249 if(fDirtyUpdateRegion) {
1250 dprintf(("Win32BaseWindow::checkForDirtyUpdateRegion; marked dirty -> invalidate whole window!"));
1251 fDirtyUpdateRegion = FALSE;
1252 ::InvalidateRgn(getWindowHandle(), hUpdateRegion, TRUE);
1253 }
1254}
1255//******************************************************************************
1256//TODO: Is the clipper region of the window DC equal to the invalidated rectangle?
1257// (or are we simply erasing too much here)
1258//******************************************************************************
1259ULONG Win32BaseWindow::MsgEraseBackGround(HDC hdc)
1260{
1261 ULONG rc;
1262 HDC hdcErase = hdc;
1263
1264 if (hdcErase == 0)
1265 hdcErase = GetDC(getWindowHandle());
1266
1267 if(IsWindowIconic())
1268 rc = SendMessageA(getWindowHandle(),WM_ICONERASEBKGND, hdcErase, 0);
1269 else
1270 rc = SendMessageA(getWindowHandle(),WM_ERASEBKGND, hdcErase, 0);
1271 if (hdc == 0)
1272 ReleaseDC(getWindowHandle(), hdcErase);
1273 return (rc);
1274}
1275//******************************************************************************
1276//******************************************************************************
1277ULONG Win32BaseWindow::MsgMouseMove(MSG *msg)
1278{
1279 //TODO: hiword should be 0 if window enters menu mode (SDK docs)
1280 //SDK: WM_SETCURSOR is not sent if the mouse is captured
1281 if(GetCapture() == 0) {
1282 SendMessageA(getWindowHandle(),WM_SETCURSOR, Win32Hwnd, MAKELONG(lastHitTestVal, msg->message));
1283 }
1284
1285 //translated message == WM_(NC)MOUSEMOVE
1286 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1287}
1288//******************************************************************************
1289//******************************************************************************
1290ULONG Win32BaseWindow::MsgChar(MSG *msg)
1291{
1292 return DispatchMsgA(msg);
1293}
1294//******************************************************************************
1295//TODO: Should use update region, not rectangle
1296//******************************************************************************
1297ULONG Win32BaseWindow::MsgNCPaint(PRECT pUpdateRect)
1298{
1299 HRGN hrgn;
1300 ULONG rc;
1301 RECT client = rectClient;
1302
1303 if ((pUpdateRect->left >= client.left) && (pUpdateRect->left < client.right) &&
1304 (pUpdateRect->right >= client.left) && (pUpdateRect->right < client.right) &&
1305 (pUpdateRect->top >= client.top) && (pUpdateRect->top < client.bottom) &&
1306 (pUpdateRect->bottom >= client.top) && (pUpdateRect->bottom < client.bottom)
1307 && (!(getStyle() & WS_MINIMIZE)))
1308 {
1309 return 0;
1310 }
1311
1312 dprintf(("MsgNCPaint (%d,%d)(%d,%d)", pUpdateRect->left, pUpdateRect->top, pUpdateRect->right, pUpdateRect->bottom));
1313 hrgn = CreateRectRgnIndirect(pUpdateRect);
1314
1315 rc = SendMessageA(getWindowHandle(),WM_NCPAINT, hrgn, 0);
1316 //Send WM_PAINTICON here if minimized, because client window will
1317 //not receive a (valid) WM_PAINT message
1318 if (getStyle() & WS_MINIMIZE)
1319 {
1320 rc = SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1321 }
1322
1323 DeleteObject(hrgn);
1324
1325 return rc;
1326}
1327//******************************************************************************
1328//Called when either the frame's size or position has changed (lpWndPos != NULL)
1329//or when the frame layout has changed (i.e. scrollbars added/removed) (lpWndPos == NULL)
1330//******************************************************************************
1331ULONG Win32BaseWindow::MsgFormatFrame(WINDOWPOS *lpWndPos)
1332{
1333 RECT oldWindowRect = rectWindow, client = rectClient, newWindowRect;
1334 RECT newClientRect;
1335 WINDOWPOS wndPos;
1336 ULONG rc;
1337
1338 if(lpWndPos)
1339 {
1340 //set new window rectangle
1341 setWindowRect(lpWndPos->x, lpWndPos->y, lpWndPos->x+lpWndPos->cx,
1342 lpWndPos->y+lpWndPos->cy);
1343 newWindowRect = rectWindow;
1344 }
1345 else {
1346 wndPos.hwnd = getWindowHandle();
1347 wndPos.hwndInsertAfter = 0;
1348 newWindowRect= rectWindow;
1349 wndPos.x = newWindowRect.left;
1350 wndPos.y = newWindowRect.top;
1351 wndPos.cx = newWindowRect.right - newWindowRect.left;
1352 wndPos.cy = newWindowRect.bottom - newWindowRect.top;
1353 wndPos.flags = SWP_FRAMECHANGED;
1354 lpWndPos = &wndPos;
1355 }
1356
1357 newClientRect = rectClient;
1358 rc = SendNCCalcSize(TRUE, &newWindowRect, &oldWindowRect, &client, lpWndPos, &newClientRect);
1359 rectClient = newClientRect; //must update rectClient here
1360
1361 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));
1362 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));
1363
1364 if(!CanReceiveSizeMsgs() || !EqualRect(&client, &rectClient)) {
1365 OSLibWinSetClientPos(getOS2WindowHandle(), rectClient.left, rectClient.top, getClientWidth(), getClientHeight(), getWindowHeight());
1366 }
1367
1368#if 1
1369//this doesn't always work
1370// if(CanReceiveSizeMsgs() && (client.left != rectClient.left || client.top != rectClient.top))
1371 if(CanReceiveSizeMsgs() && ((oldWindowRect.right - oldWindowRect.left < rectClient.left
1372 || oldWindowRect.bottom - oldWindowRect.top < rectClient.top) ||
1373 (EqualRect(&oldWindowRect, &rectWindow) && (client.left != rectClient.left || client.top != rectClient.top))))
1374 {
1375 Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild();
1376
1377 //client rectangle has moved -> inform children
1378 dprintf(("MsgFormatFrame -> client rectangle has changed, move children"));
1379 while(child) {
1380 ::SetWindowPos(child->getWindowHandle(),
1381 HWND_TOP, child->getWindowRect()->left,
1382 child->getWindowRect()->top, 0, 0,
1383 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
1384 child = (Win32BaseWindow *)child->getNextChild();
1385 }
1386 }
1387#endif
1388 //WS_EX_TOOLWINDOW is incompatible with the OS2Look (titlebar thinner + smaller font)
1389 if(fOS2Look && ((dwStyle & WS_CAPTION) == WS_CAPTION) && !(dwExStyle & WS_EX_TOOLWINDOW))
1390 {
1391 RECT rect = {0};
1392 BOOL fCloseButton;
1393
1394 fCloseButton = !(windowClass && (windowClass->getClassLongA(GCL_STYLE) & CS_NOCLOSE));
1395
1396 int height = getWindowHeight();
1397 RECTLOS2 rectOS2;
1398
1399 AdjustRectOuter(&rect, FALSE);
1400
1401 rect.left = -rect.left;
1402 rect.top = rect.bottom - rect.top;
1403 rect.right = rectWindow.right - rectWindow.left - rect.right;
1404
1405 rectOS2.xLeft = rect.left;
1406 rectOS2.xRight = rect.right;
1407 rectOS2.yBottom = height - rect.top;
1408 rectOS2.yTop = height - rect.bottom;
1409
1410 //@@PF Disable close button as well when needed by application
1411 OSLibChangeCloseButtonState(getOS2FrameWindowHandle(), fCloseButton);
1412 OSLibWinPositionFrameControls(getOS2FrameWindowHandle(), &rectOS2,
1413 dwStyle, dwExStyle, IconForWindow(ICON_SMALL),
1414 fCloseButton, windowClass->getIcon() != NULL);
1415 }
1416 return rc;
1417}
1418//******************************************************************************
1419//******************************************************************************
1420ULONG Win32BaseWindow::MsgSetText(LPSTR lpsz, LONG cch)
1421{
1422 return SendMessageA(getWindowHandle(),WM_SETTEXT, 0, (LPARAM)lpsz);
1423}
1424//******************************************************************************
1425//******************************************************************************
1426ULONG Win32BaseWindow::MsgGetTextLength()
1427{
1428 return SendMessageA(getWindowHandle(),WM_GETTEXTLENGTH, 0, 0);
1429}
1430//******************************************************************************
1431//******************************************************************************
1432void Win32BaseWindow::MsgGetText(char *wndtext, ULONG textlength)
1433{
1434 SendMessageA(getWindowHandle(),WM_GETTEXT, textlength, (LPARAM)wndtext);
1435}
1436//******************************************************************************
1437//******************************************************************************
1438BOOL Win32BaseWindow::isMDIClient()
1439{
1440 return FALSE;
1441}
1442//******************************************************************************
1443//******************************************************************************
1444BOOL Win32BaseWindow::isMDIChild()
1445{
1446 return FALSE;
1447}
1448//******************************************************************************
1449//TODO: Not complete
1450//******************************************************************************
1451BOOL Win32BaseWindow::isFrameWindow()
1452{
1453 if(getParent() == NULL)
1454 return TRUE;
1455
1456 return FALSE;
1457}
1458//******************************************************************************
1459//******************************************************************************
1460BOOL Win32BaseWindow::isDesktopWindow()
1461{
1462 return FALSE;
1463}
1464//******************************************************************************
1465//******************************************************************************
1466BOOL Win32BaseWindow::isFakeWindow()
1467{
1468 return FALSE;
1469}
1470//******************************************************************************
1471//******************************************************************************
1472BOOL Win32BaseWindow::IsWindowIconic()
1473{
1474 return ((getStyle() & WS_MINIMIZE) && windowClass->getIcon());
1475}
1476//******************************************************************************
1477//******************************************************************************
1478SCROLLBAR_INFO *Win32BaseWindow::getScrollInfo(int nBar)
1479{
1480 switch(nBar)
1481 {
1482 case SB_HORZ:
1483 if (!horzScrollInfo)
1484 {
1485 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1486 if (!horzScrollInfo) break;
1487 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
1488 horzScrollInfo->MaxVal = 100;
1489 horzScrollInfo->flags = ESB_ENABLE_BOTH;
1490 }
1491 return horzScrollInfo;
1492
1493 case SB_VERT:
1494 if (!vertScrollInfo)
1495 {
1496 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1497 if (!vertScrollInfo) break;
1498 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
1499 vertScrollInfo->MaxVal = 100;
1500 vertScrollInfo->flags = ESB_ENABLE_BOTH;
1501 }
1502 return vertScrollInfo;
1503 }
1504
1505 return NULL;
1506}
1507//******************************************************************************
1508//******************************************************************************
1509LRESULT Win32BaseWindow::DefWndControlColor(UINT ctlType, HDC hdc)
1510{
1511 //SvL: Set background color to default button color (not window (white))
1512 if(ctlType == CTLCOLOR_BTN)
1513 {
1514 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1515 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1516 return GetSysColorBrush(COLOR_BTNFACE);
1517 }
1518 //SvL: Set background color to default dialog color if window is dialog
1519 if((ctlType == CTLCOLOR_DLG || ctlType == CTLCOLOR_STATIC) && IsDialog()) {
1520 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1521 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1522 return GetSysColorBrush(COLOR_BTNFACE);
1523 }
1524 if( ctlType == CTLCOLOR_SCROLLBAR)
1525 {
1526 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
1527 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
1528 SetTextColor( hdc, GetSysColor(COLOR_3DFACE));
1529 SetBkColor( hdc, bk);
1530
1531 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
1532 * we better use 0x55aa bitmap brush to make scrollbar's background
1533 * look different from the window background.
1534 */
1535 if (bk == GetSysColor(COLOR_WINDOW)) {
1536 return GetPattern55AABrush();
1537 }
1538
1539 UnrealizeObject( hb );
1540 return (LRESULT)hb;
1541 }
1542
1543 SetTextColor( hdc, GetSysColor(COLOR_WINDOWTEXT));
1544
1545 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
1546 {
1547 SetBkColor( hdc, GetSysColor(COLOR_WINDOW) );
1548 }
1549 else
1550 {
1551 SetBkColor( hdc, GetSysColor(COLOR_3DFACE) );
1552 return (LRESULT)GetSysColorBrush(COLOR_3DFACE);
1553 }
1554 return (LRESULT)GetSysColorBrush(COLOR_WINDOW);
1555}
1556//******************************************************************************
1557//******************************************************************************
1558LRESULT Win32BaseWindow::DefWndPrint(HDC hdc,ULONG uFlags)
1559{
1560 /*
1561 * Visibility flag.
1562 */
1563 if ( (uFlags & PRF_CHECKVISIBLE) &&
1564 !IsWindowVisible(getWindowHandle()) )
1565 return 0;
1566
1567 /*
1568 * Unimplemented flags.
1569 */
1570 if ( (uFlags & PRF_CHILDREN) ||
1571 (uFlags & PRF_OWNED) ||
1572 (uFlags & PRF_NONCLIENT) )
1573 {
1574 dprintf(("WM_PRINT message with unsupported flags\n"));
1575 }
1576
1577 /*
1578 * Background
1579 */
1580 if ( uFlags & PRF_ERASEBKGND)
1581 SendMessageA(getWindowHandle(),WM_ERASEBKGND, (WPARAM)hdc, 0);
1582
1583 /*
1584 * Client area
1585 */
1586 if ( uFlags & PRF_CLIENT)
1587 SendMessageA(getWindowHandle(),WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
1588
1589
1590 return 0;
1591}
1592//******************************************************************************
1593//******************************************************************************
1594LRESULT Win32BaseWindow::DefWindowProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
1595{
1596 switch(Msg)
1597 {
1598 case WM_CLOSE:
1599 dprintf(("DefWindowProcA: WM_CLOSE %x", getWindowHandle()));
1600 DestroyWindow();
1601 return 0;
1602
1603 case WM_GETTEXTLENGTH:
1604 return windowNameLength;
1605
1606 case WM_GETTEXT:
1607 if (!lParam || !wParam)
1608 return 0;
1609 if (!windowNameA)
1610 ((LPSTR)lParam)[0] = 0;
1611 else
1612 memcpy((LPSTR)lParam, windowNameA, min(windowNameLength+1, wParam) );
1613 return min(windowNameLength, wParam);
1614
1615 case WM_SETTEXT:
1616 {
1617 LPCSTR lpsz = (LPCSTR)lParam;
1618
1619 // reallocate if new buffer is larger
1620 if (!lParam)
1621 {
1622 free(windowNameA);
1623 free(windowNameW);
1624 windowNameLength = 0;
1625 windowNameA = NULL;
1626 windowNameW = NULL;
1627 }
1628 else
1629 {
1630 // determine length of new text
1631 int iTextLength = strlen(lpsz);
1632
1633 if (windowNameLength < iTextLength)
1634 {
1635 if (windowNameA)
1636 {
1637 free(windowNameA);
1638 windowNameA = NULL;
1639 }
1640
1641 if (windowNameW)
1642 {
1643 free(windowNameW);
1644 windowNameW = NULL;
1645 }
1646 }
1647
1648 windowNameLength = iTextLength;
1649 if(!windowNameA)
1650 windowNameA = (LPSTR)_smalloc(windowNameLength+1);
1651 memcpy(windowNameA, lpsz, windowNameLength+1);
1652 if(!windowNameW)
1653 windowNameW = (LPWSTR)_smalloc((windowNameLength+1)*sizeof(WCHAR));
1654 lstrcpynAtoW(windowNameW, windowNameA, windowNameLength+1);
1655 }
1656
1657 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, lParam));
1658 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1659 {
1660 HandleNCPaint((HRGN)1);
1661 if(hTaskList) {
1662 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
1663 }
1664 if(fOS2Look) {
1665 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
1666 }
1667 }
1668
1669 return TRUE;
1670 }
1671
1672 case WM_SETREDRAW:
1673 {
1674 if (wParam)
1675 {
1676 setStyle(getStyle() | WS_VISIBLE);
1677 dprintf(("Enable window update for %x", getWindowHandle()));
1678 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, TRUE);
1679 }
1680 else
1681 {
1682 if (getStyle() & WS_VISIBLE)
1683 {
1684 setStyle(getStyle() & ~WS_VISIBLE);
1685 dprintf(("Disable window update for %x", getWindowHandle()));
1686 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, FALSE);
1687 }
1688 }
1689 return 0;
1690 }
1691
1692 case WM_CTLCOLORMSGBOX:
1693 case WM_CTLCOLOREDIT:
1694 case WM_CTLCOLORLISTBOX:
1695 case WM_CTLCOLORBTN:
1696 case WM_CTLCOLORDLG:
1697 case WM_CTLCOLORSTATIC:
1698 case WM_CTLCOLORSCROLLBAR:
1699 return DefWndControlColor(Msg - WM_CTLCOLORMSGBOX, (HDC)wParam);
1700
1701 case WM_CTLCOLOR:
1702 return DefWndControlColor(HIWORD(lParam), (HDC)wParam);
1703
1704 case WM_VKEYTOITEM:
1705 case WM_CHARTOITEM:
1706 return -1;
1707
1708 case WM_PARENTNOTIFY:
1709 return 0;
1710
1711 case WM_MOUSEACTIVATE:
1712 {
1713 HWND hwnd = getWindowHandle();
1714
1715 dprintf(("DefWndProc: WM_MOUSEACTIVATE for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1716 if (::GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
1717 {
1718 LONG ret = ::SendMessageW( ::GetParent(hwnd), WM_MOUSEACTIVATE, wParam, lParam );
1719 if (ret) return ret;
1720 }
1721
1722 /* Caption clicks are handled by the NC_HandleNCLButtonDown() */
1723 return (LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE;
1724 }
1725
1726 case WM_ACTIVATE:
1727 /* The default action in Windows is to set the keyboard focus to
1728 * the window, if it's being activated and not minimized */
1729 if (LOWORD(wParam) != WA_INACTIVE) {
1730 if(!(getStyle() & WS_MINIMIZE))
1731 SetFocus(getWindowHandle());
1732 }
1733 return 0;
1734
1735 case WM_SETCURSOR:
1736 {
1737 dprintf(("DefWndProc: WM_SETCURSOR for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1738 if((getStyle() & WS_CHILD))
1739 {
1740 if(getParent()) {
1741 LRESULT rc = SendMessageA(getParent()->getWindowHandle(), WM_SETCURSOR, wParam, lParam);
1742 if(rc) return rc;
1743 }
1744 }
1745 if (wParam == getWindowHandle())
1746 {
1747 HCURSOR hCursor;
1748
1749 switch(LOWORD(lParam))
1750 {
1751 case HTCLIENT:
1752 hCursor = windowClass ? windowClass->getCursor():LoadCursorA(0,IDC_ARROWA);
1753 break;
1754
1755 case HTLEFT:
1756 case HTRIGHT:
1757 hCursor = LoadCursorA(0,IDC_SIZEWEA);
1758 break;
1759
1760 case HTTOP:
1761 case HTBOTTOM:
1762 hCursor = LoadCursorA(0,IDC_SIZENSA);
1763 break;
1764
1765 case HTTOPLEFT:
1766 case HTBOTTOMRIGHT:
1767 hCursor = LoadCursorA(0,IDC_SIZENWSEA);
1768 break;
1769
1770 case HTTOPRIGHT:
1771 case HTBOTTOMLEFT:
1772 hCursor = LoadCursorA(0,IDC_SIZENESWA);
1773 break;
1774
1775 default:
1776 hCursor = LoadCursorA(0,IDC_ARROWA);
1777 break;
1778 }
1779
1780 if (hCursor)
1781 {
1782 SetCursor(hCursor);
1783 return 1;
1784 }
1785 else return 0;
1786 }
1787 else return 0;
1788 }
1789
1790 case WM_MOUSEMOVE:
1791 return 0;
1792
1793 case WM_MOUSEWHEEL:
1794 if (::GetWindowLongA( getWindowHandle(), GWL_STYLE ) & WS_CHILD)
1795 return ::SendMessageA( ::GetParent(getWindowHandle()), WM_MOUSEWHEEL, wParam, lParam );
1796 break;
1797
1798 case WM_WINDOWPOSCHANGED:
1799 {
1800 PWINDOWPOS wpos = (PWINDOWPOS)lParam;
1801 WPARAM wp = SIZE_RESTORED;
1802
1803 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1804 //show otherwise
1805 if (!(wpos->flags & SWP_NOMOVE) && !(wpos->flags & SWP_NOCLIENTMOVE))
1806 {
1807 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left,rectClient.top));
1808 }
1809 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1810 //show otherwise
1811 if (!(wpos->flags & SWP_NOSIZE) && !(wpos->flags & SWP_NOCLIENTSIZE))
1812 {
1813 if (dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
1814 else
1815 if (dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
1816
1817 SendMessageA(getWindowHandle(),WM_SIZE, wp, MAKELONG(rectClient.right - rectClient.left,
1818 rectClient.bottom - rectClient.top));
1819 }
1820 return 0;
1821 }
1822 case WM_WINDOWPOSCHANGING:
1823 return HandleWindowPosChanging((WINDOWPOS *)lParam);
1824
1825 case WM_ERASEBKGND:
1826 case WM_ICONERASEBKGND:
1827 {
1828 HBRUSH hBrush;
1829 RECT rect;
1830 int rc;
1831
1832 if (!windowClass || (!windowClass->getBackgroundBrush()
1833 && !(getStyle() & WS_MINIMIZE))) return 0;
1834
1835 //PF For PM desktop/MDI icons allocate brush as well to avoid
1836 //garbage in icons
1837
1838 if (!windowClass->getBackgroundBrush())
1839 hBrush = GetStockObject(GRAY_BRUSH);
1840 else
1841 {
1842 hBrush = windowClass->getBackgroundBrush();
1843 if (hBrush <= (HBRUSH)(SYSCOLOR_GetLastColor()+1))
1844 hBrush = GetSysColorBrush(hBrush-1);
1845 }
1846
1847
1848 rc = GetClipBox( (HDC)wParam, &rect );
1849 if ((rc == SIMPLEREGION) || (rc == COMPLEXREGION))
1850 FillRect( (HDC)wParam, &rect, hBrush);
1851
1852 return 1;
1853 }
1854
1855 case WM_PRINT:
1856 return DefWndPrint(wParam,lParam);
1857
1858 case WM_SYNCPAINT:
1859 RedrawWindow(getWindowHandle(), NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN);
1860 return 0;
1861
1862 case WM_PAINTICON:
1863 case WM_PAINT:
1864 {
1865 PAINTSTRUCT ps;
1866 HDC hdc = BeginPaint(getWindowHandle(), &ps );
1867 if( hdc )
1868 {
1869 if( (getStyle() & WS_MINIMIZE) && (getWindowClass()->getIcon() || hIcon))
1870 {
1871 int x = (rectWindow.right - rectWindow.left - GetSystemMetrics(SM_CXICON))/2;
1872 int y = (rectWindow.bottom - rectWindow.top - GetSystemMetrics(SM_CYICON))/2;
1873 dprintf(("Painting class icon: vis rect=(%i,%i - %i,%i)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom ));
1874 DrawIcon(hdc, x, y, hIcon ? hIcon:getWindowClass()->getIcon() );
1875 }
1876 EndPaint(getWindowHandle(), &ps );
1877 }
1878 return 0;
1879 }
1880
1881 case WM_GETDLGCODE:
1882 return 0;
1883
1884 case WM_NCPAINT:
1885 return HandleNCPaint((HRGN)wParam);
1886
1887 case WM_NCACTIVATE:
1888 return HandleNCActivate(wParam);
1889
1890 case WM_NCCREATE:
1891 return(TRUE);
1892
1893 case WM_NCDESTROY:
1894 return 0;
1895
1896 case WM_NCCALCSIZE:
1897 return HandleNCCalcSize((BOOL)wParam,(RECT*)lParam);
1898
1899 case WM_NCLBUTTONDOWN:
1900 return HandleNCLButtonDown(wParam,lParam);
1901
1902 case WM_LBUTTONDBLCLK:
1903 case WM_NCLBUTTONDBLCLK:
1904 return HandleNCLButtonDblClk(wParam,lParam);
1905
1906 case WM_NCRBUTTONDOWN:
1907 case WM_NCRBUTTONDBLCLK:
1908 case WM_NCMBUTTONDOWN:
1909 case WM_NCMBUTTONDBLCLK:
1910 if (lastHitTestVal == HTERROR) MessageBeep(MB_ICONEXCLAMATION);
1911 return 0;
1912
1913 case WM_NCRBUTTONUP:
1914 return HandleNCRButtonUp(wParam,lParam);
1915
1916 case WM_NCMBUTTONUP:
1917 return 0;
1918
1919 case WM_NCHITTEST:
1920 {
1921 POINT point;
1922 LRESULT retvalue;
1923
1924 point.x = (SHORT)LOWORD(lParam);
1925 point.y = (SHORT)HIWORD(lParam);
1926
1927 retvalue = HandleNCHitTest(point);
1928#if 0 //CB: let the Corel people fix the bugs first
1929 if(retvalue == HTMENU)
1930 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,TRUE);
1931 else
1932 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,FALSE);
1933#endif
1934 return retvalue;
1935 }
1936
1937 case WM_SYSCOMMAND:
1938 {
1939 POINT point;
1940
1941 point.x = LOWORD(lParam);
1942 point.y = HIWORD(lParam);
1943 return HandleSysCommand(wParam,&point);
1944 }
1945
1946 case WM_KEYDOWN:
1947 if(wParam == VK_F10) iF10Key = VK_F10;
1948 break;
1949
1950 case WM_SYSKEYDOWN:
1951 {
1952 if( HIWORD(lParam) & KEYDATA_ALT )
1953 {
1954 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1955 if( wParam == VK_MENU && !iMenuSysKey )
1956 iMenuSysKey = 1;
1957 else
1958 iMenuSysKey = 0;
1959
1960 iF10Key = 0;
1961
1962 if( wParam == VK_F4 ) /* try to close the window */
1963 {
1964 HWND top = GetTopParent();
1965 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
1966 PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
1967 }
1968
1969 //Default OS/2 app behaviour for system keys
1970 if(fOS2Look)
1971 {
1972 if( wParam == VK_F5 ) /* try to restore the window */
1973 {
1974 HWND top = GetTopParent();
1975 /* No checks needed SC_RESTORE handler does them */
1976 PostMessageW( top, WM_SYSCOMMAND, SC_RESTORE, 0 );
1977 }
1978
1979 if( wParam == VK_F7 ) /* size the window */
1980 {
1981 HWND top = GetTopParent();
1982 PostMessageW( top, WM_SYSCOMMAND, SC_MOVE, 0 );
1983 }
1984
1985 if( wParam == VK_F8 ) /* move the window */
1986 {
1987 HWND top = GetTopParent();
1988 if ( GetWindowLongA(top, GWL_STYLE) & WS_SIZEBOX)
1989 PostMessageW( top, WM_SYSCOMMAND, SC_SIZE, 0 );
1990 }
1991
1992 if( wParam == VK_F9 ) /* try to minimize the window */
1993 {
1994 HWND top = GetTopParent();
1995 if ( GetWindowLongA(top, GWL_STYLE) & WS_MINIMIZEBOX)
1996 PostMessageW( top, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
1997 }
1998
1999 if( wParam == VK_F10 ) /* try to maximize the window */
2000 {
2001 HWND top = GetTopParent();
2002 if ( GetWindowLongA(top, GWL_STYLE) & WS_MAXIMIZEBOX)
2003 PostMessageW( top, WM_SYSCOMMAND, SC_MAXIMIZE, 0 );
2004 }
2005 }
2006
2007 }
2008 else if( wParam == VK_F10 )
2009 iF10Key = 1;
2010 else
2011 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
2012 SendMessageW(getWindowHandle(), WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
2013
2014 Win32BaseWindow *siblingWindow;
2015 HWND sibling;
2016 char nameBuffer [40], mnemonic;
2017 int nameLength;
2018
2019 GetWindowTextA (nameBuffer, 40);
2020
2021 // search all sibling to see it this key is their mnemonic
2022 sibling = GetWindow (GW_HWNDFIRST);
2023 while (sibling != 0) {
2024 siblingWindow = GetWindowFromHandle (sibling);
2025 nameLength = siblingWindow->GetWindowTextA (nameBuffer, 40);
2026
2027 // find the siblings mnemonic
2028 mnemonic = '\0';
2029 for (int i=0 ; i<nameLength ; i++) {
2030 if (IsDBCSLeadByte(nameBuffer[i])) {
2031 // Skip DBCS
2032 continue;
2033 }
2034 if (nameBuffer [i] == '&') {
2035 mnemonic = nameBuffer [i+1];
2036 if ((mnemonic >= 'a') && (mnemonic <= 'z'))
2037 mnemonic -= 32; // make it uppercase
2038 break; // stop searching
2039 }
2040 }
2041
2042 // key matches siblings mnemonic, send mouseclick
2043 if (mnemonic == (char) wParam) {
2044 ::SendMessageA(siblingWindow->getWindowHandle(), BM_CLICK, 0, 0);
2045 }
2046 sibling = siblingWindow->GetNextWindow (GW_HWNDNEXT);
2047 RELEASE_WNDOBJ(siblingWindow);
2048 }
2049
2050 return 0;
2051 }
2052
2053 case WM_KEYUP:
2054 //Single Alt down + up always generates WM_SYSKEYUP
2055 iMenuSysKey = 0;
2056 // no break;
2057 case WM_SYSKEYUP:
2058 /* Press and release F10 or ALT */
2059 if (((wParam == VK_MENU) && iMenuSysKey) ||
2060 ((wParam == VK_F10) && iF10Key))
2061 ::SendMessageW( GetTopParent(), WM_SYSCOMMAND, SC_KEYMENU, 0L );
2062 iMenuSysKey = iF10Key = 0;
2063 break;
2064
2065 case WM_SYSCHAR:
2066 {
2067 iMenuSysKey = 0;
2068 if (wParam == VK_RETURN && (getStyle() & WS_MINIMIZE))
2069 {
2070 PostMessageA(getWindowHandle(), WM_SYSCOMMAND,
2071 (WPARAM)SC_RESTORE, 0L );
2072 break;
2073 }
2074 if((HIWORD(lParam) & KEYDATA_ALT) && wParam)
2075 {
2076 if (wParam == VK_TAB || wParam == VK_ESCAPE || wParam == VK_F4)
2077 break;
2078 if (wParam == VK_SPACE && (getStyle() & WS_CHILD)) {
2079 ::SendMessageW(GetParent(), Msg, wParam, lParam );
2080 }
2081 else ::SendMessageA(getWindowHandle(), WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
2082 }
2083#if 0
2084 else /* check for Ctrl-Esc */
2085 if (wParam != VK_ESCAPE) MessageBeep(0);
2086 break;
2087#endif
2088 }
2089
2090 case WM_SETHOTKEY:
2091 hotkey = wParam;
2092 return 1; //CB: always successful
2093
2094 case WM_GETHOTKEY:
2095 return hotkey;
2096
2097 case WM_RBUTTONUP:
2098 {
2099 POINT pt;
2100 pt.x = SLOWORD(lParam);
2101 pt.y = SHIWORD(lParam);
2102 ClientToScreen(getWindowHandle(), &pt);
2103 SendMessageA( getWindowHandle(), WM_CONTEXTMENU, getWindowHandle(),MAKELPARAM(pt.x, pt.y) );
2104 }
2105 break;
2106
2107 case WM_CONTEXTMENU:
2108 if ((dwStyle & WS_CHILD) && getParent())
2109 SendMessageA(getParent()->getWindowHandle(), WM_CONTEXTMENU,wParam,lParam);
2110 else
2111 {
2112 LONG hitcode;
2113 POINT pt;
2114 if (!GetSysMenu()) return 0;
2115 pt.x = SLOWORD(lParam);
2116 pt.y = SHIWORD(lParam);
2117 hitcode = HandleNCHitTest(pt);
2118
2119 /* Track system popup if click was in the caption area. */
2120 if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
2121 TrackPopupMenu(GetSysMenu(),
2122 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
2123 pt.x, pt.y, 0, getWindowHandle(), NULL);
2124 }
2125 return 0;
2126
2127 case WM_SHOWWINDOW:
2128 if (!lParam) return 0; /* sent from ShowWindow */
2129 if (!(dwStyle & WS_POPUP) || !owner) return 0;
2130 if ((dwStyle & WS_VISIBLE) && wParam) return 0;
2131 else if (!(dwStyle & WS_VISIBLE) && !wParam) return 0;
2132 ShowWindow(wParam ? SW_SHOW:SW_HIDE);
2133 return 0;
2134
2135 case WM_CANCELMODE:
2136 if (getParent() == windowDesktop) EndMenu();
2137 if (GetCapture() == Win32Hwnd) ReleaseCapture();
2138 return 0;
2139
2140 case WM_DROPOBJECT:
2141 return DRAG_FILE;
2142
2143 case WM_QUERYDROPOBJECT:
2144 return (dwExStyle & WS_EX_ACCEPTFILES) ? 1:0;
2145
2146 case WM_QUERYDRAGICON:
2147 {
2148 HICON hDragIcon = windowClass->getCursor();
2149 UINT len;
2150
2151 if(hDragIcon) return (LRESULT)hDragIcon;
2152 for(len = 1; len < 64; len++)
2153 {
2154 hDragIcon = LoadIconA(hInstance,MAKEINTRESOURCEA(len));
2155 if(hDragIcon)
2156 return (LRESULT)hDragIcon;
2157 }
2158 return (LRESULT)LoadIconA(0,IDI_APPLICATIONA);
2159 }
2160
2161 case WM_QUERYOPEN:
2162 case WM_QUERYENDSESSION:
2163 return 1;
2164
2165 case WM_NOTIFYFORMAT:
2166 return IsWindowUnicode() ? NFR_UNICODE:NFR_ANSI;
2167
2168 case WM_SETICON:
2169 case WM_GETICON:
2170 {
2171 LRESULT result = 0;
2172
2173 /* Set the appropriate icon members in the window structure. */
2174 if (wParam == ICON_SMALL)
2175 {
2176 result = hIconSm;
2177 if (Msg == WM_SETICON)
2178 hIconSm = (HICON)lParam;
2179 }
2180 else
2181 {
2182 result = hIcon;
2183 if (Msg == WM_SETICON)
2184 {
2185 hIcon = (HICON)lParam;
2186 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2187 OSLibWinSetIcon(OS2HwndFrame,hIcon);
2188 }
2189 }
2190 if ((Msg == WM_SETICON) && ((dwStyle & WS_CAPTION) == WS_CAPTION))
2191 HandleNCPaint((HRGN)1);
2192
2193 return result;
2194 }
2195
2196 case WM_HELP:
2197 if (getParent()) SendMessageA(getParent()->getWindowHandle(), Msg,wParam,lParam);
2198 break;
2199
2200 case WM_NOTIFY:
2201 return 0; //comctl32 controls expect this
2202
2203 default:
2204 return 0;
2205 }
2206 return 0;
2207}
2208//******************************************************************************
2209//******************************************************************************
2210LRESULT Win32BaseWindow::DefWindowProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
2211{
2212 switch(Msg)
2213 {
2214 case WM_GETTEXTLENGTH:
2215 return windowNameLength;
2216
2217 case WM_GETTEXT:
2218 if (!lParam || !wParam)
2219 return 0;
2220 if (!windowNameW)
2221 ((LPWSTR)lParam)[0] = 0;
2222 else
2223 memcpy((LPSTR)lParam, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), wParam) );
2224 return min(windowNameLength, wParam);
2225
2226 case WM_SETTEXT:
2227 {
2228 LPWSTR lpsz = (LPWSTR)lParam;
2229
2230 // reallocate if new buffer is larger
2231 if (!lParam)
2232 {
2233 free(windowNameA);
2234 free(windowNameW);
2235 windowNameLength = 0;
2236 windowNameA = NULL;
2237 windowNameW = NULL;
2238 }
2239 else
2240 {
2241 // determine length of new text
2242 int iTextLength = lstrlenW(lpsz);
2243
2244 if (windowNameLength < iTextLength)
2245 {
2246 if (windowNameA)
2247 {
2248 free(windowNameA);
2249 windowNameA = NULL;
2250 }
2251
2252 if (windowNameW)
2253 {
2254 free(windowNameW);
2255 windowNameW = NULL;
2256 }
2257 }
2258
2259 windowNameLength = iTextLength;
2260 if(!windowNameW)
2261 windowNameW = (LPWSTR)_smalloc((windowNameLength+1)*sizeof(WCHAR));
2262 memcpy(windowNameW, lpsz, (windowNameLength+1) * sizeof(WCHAR));
2263 if(!windowNameA)
2264 windowNameA = (LPSTR)_smalloc(windowNameLength+1);
2265 lstrcpynWtoA(windowNameA, windowNameW, windowNameLength+1);
2266 }
2267
2268 dprintf(("WM_SETTEXT of %x\n",Win32Hwnd));
2269 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2270 {
2271 HandleNCPaint((HRGN)1);
2272 if(hTaskList) {
2273 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
2274 }
2275 if(fOS2Look) {
2276 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
2277 }
2278 }
2279
2280 return TRUE;
2281 }
2282
2283 default:
2284 return DefWindowProcA(Msg, wParam, lParam);
2285 }
2286}
2287//******************************************************************************
2288//******************************************************************************
2289void Win32BaseWindow::NotifyParent(UINT Msg, WPARAM wParam, LPARAM lParam)
2290{
2291 Win32BaseWindow *window = this;
2292 Win32BaseWindow *parentwindow;
2293
2294 while(window)
2295 {
2296 if(window->getStyle() & WS_CHILD && !(window->getExStyle() & WS_EX_NOPARENTNOTIFY) )
2297 {
2298 /* Notify the parent window only */
2299 parentwindow = window->getParent();
2300 if(parentwindow) {
2301 /* PF We should map points for each window accordingly! */
2302 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN || Msg == WM_RBUTTONDOWN)
2303 {
2304 POINTS pt = MAKEPOINTS(lParam);
2305 POINT point;
2306
2307 point.x = pt.x;
2308 point.y = pt.y;
2309
2310 MapWindowPoints(getWindowHandle(),parentwindow->getWindowHandle(), &point, 1);
2311 lParam = MAKELPARAM(point.x, point.y);
2312 }
2313 SendMessageA(parentwindow->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(Msg, getWindowId()), lParam );
2314 }
2315
2316 }
2317 else break;
2318
2319 window = parentwindow;
2320 }
2321}
2322//******************************************************************************
2323// Returns the big or small icon for the window, falling back to the
2324// class as windows does.
2325//******************************************************************************
2326HICON Win32BaseWindow::IconForWindow(WPARAM fType)
2327{
2328 HICON hWndIcon;
2329
2330 if (fType == ICON_BIG)
2331 {
2332 if (hIcon)
2333 hWndIcon = hIcon;
2334 else
2335 if (windowClass && windowClass->getIcon())
2336 hWndIcon = windowClass->getIcon();
2337 else
2338 if (!(dwStyle & DS_MODALFRAME))
2339 {//SvL: load it as shared or else we'll leak icons
2340 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2341 }
2342 else hWndIcon = 0;
2343 }
2344 else
2345 {
2346 if (hIconSm)
2347 hWndIcon = hIconSm;
2348 else
2349 if (hIcon)
2350 hWndIcon = hIcon;
2351 else
2352 if (windowClass && windowClass->getIconSm())
2353 hWndIcon = windowClass->getIconSm();
2354 else
2355 if (windowClass && windowClass->getIcon())
2356 hWndIcon = windowClass->getIcon();
2357 else
2358 if (!(dwStyle & DS_MODALFRAME))
2359 {//SvL: load it as shared or else we'll leak icons
2360 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2361 }
2362 else hWndIcon = 0;
2363 }
2364
2365 return hWndIcon;
2366}
2367//******************************************************************************
2368//******************************************************************************
2369BOOL Win32BaseWindow::ShowWindow(ULONG nCmdShow)
2370{
2371 ULONG swp = 0;
2372 HWND hWinAfter;
2373 BOOL rc,wasVisible,showFlag;
2374 RECT newPos = {0, 0, 0, 0};
2375
2376 dprintf(("ShowWindow %x %x", getWindowHandle(), nCmdShow));
2377 wasVisible = (getStyle() & WS_VISIBLE) != 0;
2378
2379 dwOldStyle = getStyle();
2380
2381 /*
2382 * SW_SHOWDEFAULT is an reference to the startup info wShowWindow member.
2383 */
2384 if (nCmdShow == SW_SHOWDEFAULT)
2385 {
2386 nCmdShow = GetProcessDword(0, GPD_STARTF_SHOWWINDOW);
2387 dprintf(("ShowWindow: GetProcessDword(0, GPD_STARTF_SHOWWINDOW) -> %x", nCmdShow));
2388 }
2389
2390
2391 switch(nCmdShow)
2392 {
2393 case SW_HIDE:
2394 if (!wasVisible) goto END;
2395
2396 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER;
2397 break;
2398
2399 case SW_SHOWMINNOACTIVE:
2400 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2401 /* fall through */
2402 case SW_SHOWMINIMIZED:
2403 swp |= SWP_SHOWWINDOW;
2404 /* fall through */
2405 case SW_MINIMIZE:
2406 swp |= SWP_FRAMECHANGED;
2407 if( !(getStyle() & WS_MINIMIZE) ) {
2408 swp |= MinMaximize(SW_MINIMIZE, &newPos );
2409 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2410 }
2411 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2412 break;
2413
2414 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
2415 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2416 if( !(getStyle() & WS_MAXIMIZE) ) {
2417 swp |= MinMaximize(SW_MAXIMIZE, &newPos );
2418 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2419 }
2420 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2421 break;
2422
2423 case SW_SHOWNA:
2424 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2425 /* fall through */
2426 case SW_SHOW:
2427 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2428
2429 /*
2430 * ShowWindow has a little peculiar behavior that if the
2431 * window is already the topmost window, it will not
2432 * activate it.
2433 */
2434 if (::GetTopWindow((HWND)0)==getWindowHandle() && (wasVisible || GetActiveWindow() == getWindowHandle()))
2435 swp |= SWP_NOACTIVATE;
2436
2437 break;
2438
2439 case SW_SHOWNOACTIVATE:
2440 swp |= SWP_NOZORDER;
2441 if (GetActiveWindow())
2442 swp |= SWP_NOACTIVATE;
2443 /* fall through */
2444 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
2445 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2446 case SW_RESTORE:
2447 dprintf(("ShowWindow:restoring window"));
2448
2449 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2450 if( getStyle() & (WS_MINIMIZE | WS_MAXIMIZE) ) {
2451 swp |= MinMaximize(SW_RESTORE, &newPos );
2452 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2453 }
2454 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2455 break;
2456 }
2457
2458 showFlag = (nCmdShow != SW_HIDE);
2459 if (showFlag != wasVisible)
2460 {
2461 SendMessageA(getWindowHandle(),WM_SHOWWINDOW, showFlag, 0 );
2462 if (!::IsWindow( getWindowHandle() )) goto END;
2463 }
2464
2465 /* We can't activate a child window */
2466 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_MDICHILD))
2467 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2468
2469 if (!(getStyle() & WS_MINIMIZE)) {
2470 SetWindowPos(HWND_TOP, newPos.left, newPos.top, newPos.right, newPos.bottom, LOWORD(swp), TRUE);
2471 }
2472 else OSLibWinMinimizeWindow(getOS2FrameWindowHandle());
2473
2474 if(!(swp & SWP_NOACTIVATE) && (!(getStyle() & WS_MINIMIZE))) {
2475 OSLibWinSetActiveWindow(OS2HwndFrame);
2476 }
2477
2478 if (flags & WIN_NEED_SIZE)
2479 {
2480 /* should happen only in CreateWindowEx() */
2481 int wParam = SIZE_RESTORED;
2482
2483 flags &= ~WIN_NEED_SIZE;
2484 if (dwStyle & WS_MAXIMIZE)
2485 wParam = SIZE_MAXIMIZED;
2486 else
2487 if (dwStyle & WS_MINIMIZE)
2488 wParam = SIZE_MINIMIZED;
2489
2490 SendMessageA(getWindowHandle(),WM_SIZE, wParam,
2491 MAKELONG(rectClient.right-rectClient.left,
2492 rectClient.bottom-rectClient.top));
2493 SendMessageA(getWindowHandle(),WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
2494 }
2495//testestest
2496 //temporary workaround for file dialogs with template dialog child
2497 //they don't redraw when switching directories
2498 //For some reason the new child's (syslistview32) update rectangle stays
2499 //empty after its parent is made visible with ShowWindow
2500 //TODO: find real cause
2501 if(!wasVisible) {
2502 InvalidateRect(getWindowHandle(), NULL, TRUE);
2503 }
2504//testestest
2505
2506END:
2507 fMinMaxChange = FALSE;
2508 return wasVisible;
2509}
2510//******************************************************************************
2511//******************************************************************************
2512BOOL Win32BaseWindow::SetWindowPos(HWND hwndInsertAfter, int x, int y, int cx,
2513 int cy, UINT fuFlags, BOOL fShowWindow)
2514{
2515 BOOL rc = FALSE;
2516 Win32BaseWindow *window;
2517 HWND hParent = 0;
2518 RECT oldClientRect = rectClient;
2519
2520 if (fuFlags &
2521 ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
2522 SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
2523 SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
2524 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_DEFERERASE |
2525 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS))
2526 {
2527 dprintf(("ERROR: SetWindowPos; UNKNOWN flag"));
2528 return FALSE;
2529 }
2530
2531 if( fuFlags & (SWP_DEFERERASE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS)) {
2532 dprintf(("WARNING: SetWindowPos; unsupported flag"));
2533 }
2534
2535 if(IsWindowDestroyed()) {
2536 //changing the position of a window that's being destroyed can cause crashes in PMMERGE
2537 dprintf(("SetWindowPos; window already destroyed"));
2538 return TRUE;
2539 }
2540
2541 if(state >= STATE_CREATED) {
2542 /* Fix redundant flags */
2543 if(getStyle() & WS_VISIBLE) {
2544 fuFlags &= ~SWP_SHOWWINDOW;
2545 }
2546 else
2547 {
2548 if (!(fuFlags & SWP_SHOWWINDOW))
2549 fuFlags |= SWP_NOREDRAW;
2550 fuFlags &= ~SWP_HIDEWINDOW;
2551 }
2552
2553 if((rectWindow.right - rectWindow.left == cx) && (rectWindow.bottom - rectWindow.top == cy)) {
2554 fuFlags |= SWP_NOSIZE; /* Already the right size */
2555 }
2556
2557 if((rectWindow.left == x) && (rectWindow.top == y)) {
2558 fuFlags |= SWP_NOMOVE; /* Already the right position */
2559 }
2560
2561 if(getWindowHandle() == GetActiveWindow()) {
2562 fuFlags |= SWP_NOACTIVATE; /* Already active */
2563 }
2564 else
2565 if((getStyle() & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2566 {
2567 if(!(fuFlags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2568 {
2569 fuFlags &= ~SWP_NOZORDER;
2570 hwndInsertAfter = HWND_TOP;
2571 }
2572 }
2573 }
2574 /* TODO: Check hwndInsertAfter */
2575
2576 //Note: Solitaire crashes when receiving WM_SIZE messages before WM_CREATE
2577 if(state < STATE_POST_WMNCCREATE)
2578 {//don't change size; modify internal structures only
2579 //TODO: not 100% correct yet (activate)
2580 dprintf2(("state < STATE_POST_WMNCCREATE"));
2581 if(!(fuFlags & SWP_NOZORDER)) {
2582 hwndLinkAfter = hwndInsertAfter;
2583 }
2584 if(!(fuFlags & SWP_NOMOVE)) {
2585 rectWindow.bottom = (rectWindow.bottom - rectWindow.top) + y;
2586 rectWindow.top = y;
2587 rectWindow.right = (rectWindow.right - rectWindow.left) + x;
2588 rectWindow.left = x;
2589 }
2590 if(!(fuFlags & SWP_NOSIZE)) {
2591 rectWindow.bottom = rectWindow.top + cy;
2592 rectWindow.right = rectWindow.left + cx;
2593 }
2594 return TRUE;
2595 }
2596
2597 WINDOWPOS wpos;
2598 SWP swp, swpOld;
2599 wpos.flags = fuFlags;
2600 wpos.cy = cy;
2601 wpos.cx = cx;
2602 wpos.x = x;
2603 wpos.y = y;
2604 wpos.hwndInsertAfter = hwndInsertAfter;
2605 wpos.hwnd = getWindowHandle();
2606
2607 if(~fuFlags & (SWP_NOMOVE | SWP_NOSIZE))
2608 {
2609 if (isChild())
2610 {
2611 if(!getParent()) {
2612 dprintf(("WARNING: Win32BaseWindow::SetWindowPos window %x is child but has no parent!!", getWindowHandle()));
2613 }
2614 }
2615 OSLibWinQueryWindowPos(OS2HwndFrame, &swpOld);
2616 }
2617 if((dwOldStyle & WS_MINIMIZE) && (getStyle() & WS_MINIMIZE))
2618 {//don't allow size changes if the window is minimized
2619 //we will update the restore position at the end of this method
2620 if(!(wpos.flags & SWP_NOSIZE)) {
2621 //TODO: updating the window rectangle doesn't look right
2622 wpos.flags |= SWP_NOSIZE;
2623 rectWindow.right = rectWindow.left + wpos.cx;
2624 rectWindow.bottom = rectWindow.top + wpos.cy;
2625 dprintf(("WARNING: Don't allow size change for minimized window; only save new restore position"));
2626 dprintf(("new window rectangle (%d,%d)(%d,%d)", rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2627 }
2628 }
2629
2630 if(getParent()) {
2631 OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, getParent()->getClientHeight(),
2632 OS2HwndFrame);
2633 }
2634 else OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, OSLibQueryScreenHeight(), OS2HwndFrame);
2635
2636 if (swp.fl == 0) {
2637 dprintf2(("swp.fl == 0"));
2638 if(fuFlags & SWP_FRAMECHANGED)
2639 {
2640 NotifyFrameChanged(&wpos, &oldClientRect);
2641 }
2642 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)) && !(fuFlags & (SWP_NOSIZE | SWP_NOMOVE)))
2643 {
2644 //Restore position always changes when the window position is changed
2645 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2646 windowpos.rcNormalPosition = rectWindow;
2647 }
2648 return TRUE;
2649 }
2650
2651// if ((swp.fl & SWPOS_ZORDER) && (swp.hwndInsertBehind > HWNDOS_BOTTOM))
2652 if ((swp.hwndInsertBehind > HWNDOS_BOTTOM))
2653 {
2654 Win32BaseWindow *wndBehind = Win32BaseWindow::GetWindowFromHandle(swp.hwndInsertBehind);
2655 if(wndBehind) {
2656 swp.hwndInsertBehind = wndBehind->getOS2FrameWindowHandle();
2657 RELEASE_WNDOBJ(wndBehind);
2658 }
2659 else {
2660 dprintf(("ERROR: SetWindowPos: hwndInsertBehind %x invalid!",swp.hwndInsertBehind));
2661 swp.hwndInsertBehind = 0;
2662 }
2663 }
2664 swp.hwnd = OS2HwndFrame;
2665
2666 //SvL: Must also deactivate the window when hiding it or else focus won't
2667 // change. (NOTE: make sure this doesn't cause regressions (01-02-2003)
2668 if((swp.fl & (SWPOS_HIDE|SWPOS_DEACTIVATE)) == (SWPOS_HIDE|SWPOS_DEACTIVATE))
2669 {
2670 //we must make sure the owner is not disabled or else the focus will
2671 //be switched to the wrong window
2672 Win32BaseWindow *topOwner;
2673
2674 if(getOwner() == NULL) {
2675 windowDesktop->addRef();
2676 topOwner = windowDesktop;
2677 }
2678 else topOwner = GetWindowFromHandle(getOwner()->GetTopParent());
2679
2680 if(topOwner != NULL) {
2681 DWORD dwStyle = topOwner->GetWindowLong(GWL_STYLE, FALSE);
2682 if(dwStyle & WS_DISABLED) {
2683 swp.fl &= ~SWPOS_DEACTIVATE;
2684 }
2685 }
2686 else DebugInt3();
2687 }
2688
2689 if(fuFlags & SWP_SHOWWINDOW && !IsWindowVisible(getWindowHandle())) {
2690 setStyle(getStyle() | WS_VISIBLE);
2691 if(hTaskList) {
2692 dprintf(("Adding window %x to tasklist", getWindowHandle()));
2693 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 1);
2694 }
2695 }
2696 else
2697 if((fuFlags & SWP_HIDEWINDOW) && IsWindowVisible(getWindowHandle())) {
2698 setStyle(getStyle() & ~WS_VISIBLE);
2699 if(hTaskList && !(getStyle() & WS_MINIMIZE)) {
2700 dprintf(("Removing window %x from tasklist", getWindowHandle()));
2701 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 0);
2702 }
2703 }
2704 dprintf (("WinSetWindowPos %x %x (%d,%d)(%d,%d) %x", swp.hwnd, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, swp.fl));
2705
2706 rc = OSLibWinSetMultWindowPos(&swp, 1);
2707 if(rc == FALSE)
2708 {
2709 dprintf(("OSLibWinSetMultWindowPos failed! Error %x",OSLibWinGetLastError()));
2710 return 0;
2711 }
2712
2713 if((fuFlags & SWP_FRAMECHANGED) && (fuFlags & (SWP_NOMOVE | SWP_NOSIZE) == (SWP_NOMOVE | SWP_NOSIZE)))
2714 {
2715 NotifyFrameChanged(&wpos, &oldClientRect);
2716 }
2717 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)))
2718 {
2719 //Restore position always changes when the window position is changed
2720 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2721 windowpos.rcNormalPosition = rectWindow;
2722 }
2723 //MSDN says the entire client area will be invalidated when SWP_NOCOPYBITS
2724 //is specified (fixes repaint issues when window is made smaller)
2725 if((fuFlags & (SWP_NOCOPYBITS|SWP_NOREDRAW)) == SWP_NOCOPYBITS) {
2726 InvalidateRect(getWindowHandle(), NULL, TRUE);
2727 }
2728 return (rc);
2729}
2730//******************************************************************************
2731//Called by ScrollWindowEx (dc.cpp) to notify child window that it has moved
2732//******************************************************************************
2733BOOL Win32BaseWindow::ScrollWindow(int dx, int dy)
2734{
2735 rectWindow.left += dx;
2736 rectWindow.right += dx;
2737 rectWindow.top += dy;
2738 rectWindow.bottom += dy;
2739 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left, rectClient.top));
2740 return TRUE;
2741}
2742//******************************************************************************
2743//******************************************************************************
2744void Win32BaseWindow::NotifyFrameChanged(WINDOWPOS *wpos, RECT *oldClientRect)
2745{
2746 HRGN hrgn, hrgnClient;
2747 RECT rect;
2748
2749 MsgFormatFrame(NULL);
2750
2751 if(RECT_WIDTH(rectClient) != RECT_WIDTH(*oldClientRect) ||
2752 RECT_HEIGHT(rectClient) != RECT_HEIGHT(*oldClientRect))
2753 {
2754 wpos->flags &= ~(SWP_NOSIZE|SWP_NOCLIENTSIZE);
2755 wpos->cx = RECT_WIDTH(rectWindow);
2756 wpos->cy = RECT_HEIGHT(rectWindow);
2757 }
2758
2759 if(rectClient.left != oldClientRect->left ||
2760 rectClient.top != oldClientRect->top)
2761 {
2762 wpos->flags &= ~(SWP_NOMOVE|SWP_NOCLIENTMOVE);
2763 wpos->x = rectWindow.left;
2764 wpos->y = rectWindow.top;
2765 }
2766
2767 WINDOWPOS wpOld = *wpos;
2768 if(!(wpos->flags & SWP_NOSENDCHANGING))
2769 SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, (LPARAM)wpos);
2770
2771 if ((wpos->hwndInsertAfter != wpOld.hwndInsertAfter) ||
2772 (wpos->x != wpOld.x) || (wpos->y != wpOld.y) || (wpos->cx != wpOld.cx) || (wpos->cy != wpOld.cy) || (wpos->flags != wpOld.flags))
2773 {
2774 dprintf(("WARNING, NotifyFrameChanged: TODO -> adjust flags!!!!"));
2775 SetWindowPos(wpos->hwndInsertAfter, wpos->x, wpos->y, wpos->cx, wpos->cy, wpos->flags | SWP_NOSENDCHANGING);
2776 }
2777 else SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, (LPARAM)wpos);
2778
2779 //Calculate invalid areas
2780 rect = rectWindow;
2781 OffsetRect(&rect, -rectWindow.left, -rectWindow.top);
2782 hrgn = CreateRectRgnIndirect(&rect);
2783 if (!hrgn) {
2784 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2785 return;
2786 }
2787 rect = rectClient;
2788 hrgnClient = CreateRectRgnIndirect(&rect);
2789 if (!hrgn) {
2790 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2791 return;
2792 }
2793 CombineRgn(hrgn, hrgn, hrgnClient, RGN_DIFF);
2794 DeleteObject(hrgnClient);
2795
2796 if(!EqualRect(oldClientRect, &rectClient)) {
2797 UnionRect(oldClientRect, oldClientRect, &rectClient);
2798 hrgnClient = CreateRectRgnIndirect(oldClientRect);
2799 if (!hrgn) {
2800 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2801 return;
2802 }
2803 CombineRgn(hrgn, hrgn, hrgnClient, RGN_OR);
2804 DeleteObject(hrgnClient);
2805 }
2806 RedrawWindow(getWindowHandle(), NULL, hrgn, RDW_ALLCHILDREN |
2807 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
2808 DeleteObject(hrgn);
2809}
2810//******************************************************************************
2811//TODO: Check how this api really works in NT
2812//******************************************************************************
2813BOOL Win32BaseWindow::SetWindowPlacement(WINDOWPLACEMENT *wndpl)
2814{
2815 dprintf(("SetWindowPlacement %x min (%d,%d)", getWindowHandle(), wndpl->ptMinPosition.x, wndpl->ptMinPosition.y));
2816 dprintf(("SetWindowPlacement %x max (%d,%d)", getWindowHandle(), wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y));
2817 dprintf(("SetWindowPlacement %x norm (%d,%d)(%d,%d)", getWindowHandle(), wndpl->rcNormalPosition.left, wndpl->rcNormalPosition.top, wndpl->rcNormalPosition.right, wndpl->rcNormalPosition.bottom));
2818 windowpos.ptMinPosition = wndpl->ptMinPosition;
2819 windowpos.ptMaxPosition = wndpl->ptMaxPosition;
2820 windowpos.rcNormalPosition = wndpl->rcNormalPosition;
2821
2822 if(getStyle() & WS_MINIMIZE )
2823 {
2824 //TODO: Why can't this be (0,0)?
2825 if(wndpl->flags & WPF_SETMINPOSITION && !(!windowpos.ptMinPosition.x && !windowpos.ptMinPosition.y)) {
2826 SetWindowPos(0, windowpos.ptMinPosition.x, windowpos.ptMinPosition.y,
2827 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2828 }
2829 }
2830 else
2831 if(getStyle() & WS_MAXIMIZE )
2832 {
2833 //TODO: Why can't this be (0,0)?
2834 if(windowpos.ptMaxPosition.x != 0 || windowpos.ptMaxPosition.y != 0 )
2835 SetWindowPos(0, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
2836 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2837 }
2838 else {
2839 SetWindowPos(0, windowpos.rcNormalPosition.left, windowpos.rcNormalPosition.top,
2840 windowpos.rcNormalPosition.right - windowpos.rcNormalPosition.left,
2841 windowpos.rcNormalPosition.bottom - windowpos.rcNormalPosition.top,
2842 SWP_NOZORDER | SWP_NOACTIVATE );
2843 }
2844 ShowWindow(wndpl->showCmd);
2845 if( ::IsWindow(getWindowHandle()) && getStyle() & WS_MINIMIZE )
2846 {
2847 /* SDK: ...valid only the next time... */
2848 if(wndpl->flags & WPF_RESTORETOMAXIMIZED)
2849 setFlags(getFlags() | WIN_RESTORE_MAX);
2850 }
2851 return TRUE;
2852}
2853//******************************************************************************
2854//******************************************************************************
2855BOOL Win32BaseWindow::GetWindowPlacement(LPWINDOWPLACEMENT wndpl)
2856{
2857 wndpl->length = sizeof(*wndpl);
2858 if(getStyle() & WS_MINIMIZE )
2859 wndpl->showCmd = SW_SHOWMINIMIZED;
2860 else wndpl->showCmd = (getStyle() & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
2861
2862 //TODO: Verify if this is correct -> SDK docs claim this flag must always be set to 0
2863 if(getFlags() & WIN_RESTORE_MAX )
2864 wndpl->flags = WPF_RESTORETOMAXIMIZED;
2865 else wndpl->flags = 0;
2866
2867 wndpl->ptMinPosition = windowpos.ptMinPosition;
2868 wndpl->ptMaxPosition = windowpos.ptMaxPosition;
2869 //Must be in parent coordinates (or screen if no parent); verified in NT4, SP6
2870 wndpl->rcNormalPosition = windowpos.rcNormalPosition;
2871
2872 return TRUE;
2873}
2874//******************************************************************************
2875//Also destroys all the child windows (destroy children first, parent last)
2876//TODO: Don't rely on PM to do the right thing. Send WM_(NC)DESTROY &
2877// destroy children ourselves (see Wine)
2878//******************************************************************************
2879BOOL Win32BaseWindow::DestroyWindow()
2880{
2881 HWND hwnd = getWindowHandle();
2882
2883 dprintf(("DestroyWindow %x", hwnd));
2884
2885#if 0
2886 /* Look whether the focus is within the tree of windows we will
2887 * be destroying.
2888 */
2889 HWND hwndFocus = GetFocus();
2890 if (hwndFocus == hwnd || ::IsChild( hwnd, hwndFocus ))
2891 {
2892 HWND parent = GetAncestor( hwnd, GA_PARENT );
2893 if (parent == GetDesktopWindow()) parent = 0;
2894 SetFocus( parent );
2895 }
2896#endif
2897 /* Call hooks */
2898 if(HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, getWindowHandle(), 0L))
2899 {
2900 return FALSE;
2901 }
2902
2903 if(!(getStyle() & WS_CHILD) && getOwner() == NULL)
2904 {
2905 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWDESTROYED, getWindowHandle(), 0L);
2906 /* FIXME: clean up palette - see "Internals" p.352 */
2907 }
2908
2909 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
2910 {
2911 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
2912 {
2913 /* Notify the parent window only */
2914 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
2915 if(!::IsWindow(hwnd) )
2916 {
2917 return TRUE;
2918 }
2919 }
2920//// else DebugInt3();
2921 }
2922 /* Hide the window */
2923 if(IsWindowVisible(getWindowHandle()))
2924 {
2925 SetWindowPos(0, 0, 0, 0, 0, SWP_HIDEWINDOW |
2926 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2927 if(!::IsWindow(hwnd))
2928 {
2929 return TRUE;
2930 }
2931 }
2932 dprintf(("DestroyWindow %x -> HIDDEN", hwnd));
2933
2934 // check the handle for the last active popup window
2935 Win32BaseWindow* owner = getOwner();
2936 if (NULL != owner)
2937 {
2938 if (owner->getLastActive() == hwnd)
2939 owner->setLastActive( owner->getWindowHandle() );
2940
2941 //SvL: Not sure this is correct, but it solves the problem of reassigning
2942 // activation. A disabled window will never be activated ->
2943 // possible that the wrong window is chosen by PM.
2944 // PM chooses another window to be activated before WM_DESTROY is
2945 // sent. VPC enables the owner when it receives that message,
2946 // but by then it's too late.
2947 // (MFC created modeless dialog)
2948 //TODO: This might be the wrong place to do it. EndDialog is called,
2949 // so perhaps it should be done there. (although Wine only
2950 // enables the owner if the dialog is modal)
2951 ::EnableWindow(owner->getWindowHandle(), 1);
2952 }
2953
2954 fDestroyWindowCalled = TRUE;
2955
2956//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2957// handler; must postpone it
2958 if(fChildDestructionInProgress) {
2959 dprintf(("Postponing parent destruction because of dying child"));
2960 OSLibPostMessageDirect(OS2HwndFrame, WIN32APP_POSTPONEDESTROY, 0, 0);
2961 return TRUE;
2962 }
2963
2964 BOOL fOldChildDestructionInProgress = FALSE;
2965 if(GetParent()) {
2966 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2967 if(window) {
2968 fOldChildDestructionInProgress = window->IsChildDestructionInProgress();
2969 window->SetChildDestructionInProgress(TRUE);
2970 RELEASE_WNDOBJ(window);
2971 }
2972 }
2973//hack end
2974
2975 BOOL ret = OSLibWinDestroyWindow(OS2HwndFrame);
2976
2977//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2978// handler; must postpone it
2979 if(GetParent()) {
2980 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2981 if(window) {
2982 window->SetChildDestructionInProgress(fOldChildDestructionInProgress);
2983 RELEASE_WNDOBJ(window);
2984 }
2985 }
2986//hack end
2987 return ret;
2988}
2989//******************************************************************************
2990//******************************************************************************
2991Win32BaseWindow *Win32BaseWindow::getParent()
2992{
2993 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2994 //experiment
2995#if 0
2996 return ((ULONG)wndparent == (ULONG)windowDesktop) ? NULL : wndparent;
2997#else
2998 return wndparent;
2999#endif
3000}
3001//******************************************************************************
3002//Note: does not set last error if no parent (verified in NT4, SP6)
3003//******************************************************************************
3004HWND Win32BaseWindow::GetParent()
3005{
3006 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3007
3008 if(getStyle() & WS_CHILD)
3009 {
3010 if(wndparent) {
3011 return wndparent->getWindowHandle();
3012 }
3013 dprintf(("WARNING: GetParent: WS_CHILD but no parent!!"));
3014 DebugInt3();
3015 return 0;
3016 }
3017 else
3018 if(getStyle() & WS_POPUP)
3019 return (getOwner()) ? getOwner()->getWindowHandle() : 0;
3020 else return 0;
3021}
3022//******************************************************************************
3023//******************************************************************************
3024HWND Win32BaseWindow::SetParent(HWND hwndNewParent)
3025{
3026 HWND oldhwnd;
3027 Win32BaseWindow *newparent;
3028 Win32BaseWindow *oldparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3029 BOOL fShow = FALSE;
3030
3031 if(oldparent) {
3032 oldhwnd = oldparent->getWindowHandle();
3033 oldparent->removeChild(this);
3034 }
3035 else oldhwnd = 0;
3036
3037 /* Windows hides the window first, then shows it again
3038 * including the WM_SHOWWINDOW messages and all */
3039 if(IsWindowCreated() && (getStyle() & WS_VISIBLE)) {
3040 ShowWindow(SW_HIDE);
3041 fShow = TRUE;
3042 }
3043 if(oldparent) {
3044 //release parent here (increased refcount during creation)
3045 RELEASE_WNDOBJ(oldparent);
3046 }
3047 newparent = GetWindowFromHandle(hwndNewParent);
3048 if(newparent && !newparent->isDesktopWindow())
3049 {
3050 setParent(newparent);
3051 getParent()->addChild(this);
3052 fParentChange = TRUE;
3053 // in case we haven't finished creating the window whose parent we're
3054 // setting here, the OS/2 HWND might not exist yet and we call the PM
3055 // API with a NULLHANDLE - no problem
3056 // when we create the OS/2 window lateron, we will create it with the
3057 // right parent anyway.
3058 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
3059 if(!(getStyle() & WS_CHILD))
3060 {
3061 if(getWindowId())
3062 {
3063 DestroyMenu( (HMENU) getWindowId() );
3064 setWindowId(0);
3065 }
3066 }
3067 //SvL: Even though the win32 coordinates might not change, the PM
3068 // coordinates can. We must make sure the control stays at the
3069 // same position (y) relative to the (new) parent.
3070 // TODO: shouldn't we check the state of the window and not do it in INIT state?
3071 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
3072 SWP_NOACTIVATE|SWP_NOSIZE);
3073 fParentChange = FALSE;
3074 }
3075 else {
3076 if(newparent) RELEASE_WNDOBJ(newparent);
3077
3078 setParent(windowDesktop);
3079 windowDesktop->addRef();
3080 windowDesktop->addChild(this);
3081 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
3082
3083 //Do not change the window id!
3084//// setWindowId(0);
3085 }
3086 /* SetParent additionally needs to make hwndChild the topmost window
3087 in the x-order and send the expected WM_WINDOWPOSCHANGING and
3088 WM_WINDOWPOSCHANGED notification messages.
3089 */
3090 if(state >= STATE_PRE_WMNCCREATE) {
3091 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
3092 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
3093
3094 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
3095 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
3096 }
3097 return oldhwnd;
3098}
3099//******************************************************************************
3100//******************************************************************************
3101BOOL Win32BaseWindow::IsChild(HWND hwndParent)
3102{
3103 // PH: Optimizer won't unroll calls to getParent() even
3104 // in release build.
3105 Win32BaseWindow *_parent = getParent();
3106
3107 if(_parent)
3108 {
3109 if(_parent->getWindowHandle() == hwndParent)
3110 return TRUE;
3111
3112 return _parent->IsChild(hwndParent);
3113 }
3114 else
3115 return 0;
3116}
3117//******************************************************************************
3118//******************************************************************************
3119HWND Win32BaseWindow::GetTopWindow()
3120{
3121 HWND hwndTop;
3122 Win32BaseWindow *topwindow;
3123
3124 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3125 if(!isDesktopWindow())
3126 {
3127 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3128 //Note: GetTopWindow can't return a window that hasn't processed
3129 // WM_NCCREATE yet (verified in NT4, SP6)
3130 if(topwindow) {
3131 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3132 hwndTop = topwindow->getWindowHandle();
3133 }
3134 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3135 RELEASE_WNDOBJ(topwindow);
3136 return hwndTop;
3137 }
3138 if(topwindow) RELEASE_WNDOBJ(topwindow);
3139 return 0;
3140 }
3141 while(hwndTop) {
3142 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3143 //Note: GetTopWindow can't return a window that hasn't processed
3144 // WM_NCCREATE yet (verified in NT4, SP6)
3145 if(topwindow) {
3146 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3147 hwndTop = topwindow->getWindowHandle();
3148 }
3149 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3150 RELEASE_WNDOBJ(topwindow);
3151 return hwndTop;
3152 }
3153 if(topwindow) RELEASE_WNDOBJ(topwindow);
3154 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
3155 }
3156
3157 return 0;
3158}
3159//******************************************************************************
3160// Get the top-level parent for a child window.
3161//******************************************************************************
3162HWND Win32BaseWindow::GetTopParent()
3163{
3164 Win32BaseWindow *window = this;
3165 HWND hwndTopParent = 0;
3166
3167 lock();
3168 while(window && (window->getStyle() & WS_CHILD))
3169 {
3170 window = window->getParent();
3171 }
3172 if(window) {
3173 hwndTopParent = window->getWindowHandle();
3174 }
3175 unlock();
3176 return hwndTopParent;
3177}
3178//******************************************************************************
3179//TODO: Should not enumerate children that are created during the enumeration!
3180//TODO: Do this more efficiently
3181//******************************************************************************
3182BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
3183{
3184 BOOL rc = TRUE;
3185 HWND hwnd;
3186 Win32BaseWindow *prevchild = 0, *child = 0;
3187
3188 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
3189 lock();
3190 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
3191 {
3192 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
3193 hwnd = child->getWindowHandle();
3194 if(child->IsWindowDestroyed() || child->getOwner()) {
3195 continue; //shouldn't have an owner (Wine)
3196 }
3197 child->addRef();
3198 unlock();
3199 if(lpfn(hwnd, lParam) == FALSE)
3200 {
3201 child->release();
3202 return FALSE;
3203 }
3204 child->release();
3205 lock();
3206 //check if the window still exists
3207 if(!::IsWindow(hwnd))
3208 {
3209 child = prevchild;
3210 if(child == NULL) break;
3211 continue;
3212 }
3213 if(child->getFirstChild() != NULL)
3214 {
3215 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
3216 child->addRef();
3217 unlock();
3218 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
3219 {
3220 child->release();
3221 return FALSE;
3222 }
3223 child->release();
3224 lock();
3225 }
3226 prevchild = child;
3227 }
3228 unlock();
3229 return rc;
3230}
3231//******************************************************************************
3232//Enumerate first-level children only and check thread id
3233//NOTE: NT4 returns first-level children in Z-order!
3234//******************************************************************************
3235BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
3236{
3237 Win32BaseWindow *wnd = NULL;
3238 HWND henum, hwnd, hwndWin32;
3239 ULONG tid, pid;
3240 BOOL rc;
3241
3242 //Enumerate all top-level windows and check the process and thread ids
3243 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3244 hwnd = OSLibWinGetNextWindow(henum);
3245
3246 while(hwnd)
3247 {
3248 wnd = GetWindowFromOS2FrameHandle(hwnd);
3249 if(wnd == NULL) {
3250 hwnd = OSLibWinQueryClientWindow(hwnd);
3251 if(hwnd) wnd = GetWindowFromOS2Handle(hwnd);
3252 }
3253 if(wnd) {
3254 hwndWin32 = wnd->getWindowHandle();
3255 }
3256 else hwndWin32 = 0;
3257
3258 if(wnd) RELEASE_WNDOBJ(wnd);
3259
3260 if(hwndWin32) {
3261 OSLibWinQueryWindowProcess(hwnd, &pid, &tid);
3262
3263 if(dwThreadId == tid) {
3264 dprintf(("EnumThreadWindows: Found Window %x", hwndWin32));
3265 if((rc = lpfn(hwndWin32, lParam)) == FALSE) {
3266 break;
3267 }
3268 }
3269 }
3270 hwnd = OSLibWinGetNextWindow(henum);
3271 }
3272 OSLibWinEndEnumWindows(henum);
3273 return TRUE;
3274}
3275//******************************************************************************
3276//Enumerate first-level children only
3277//******************************************************************************
3278BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
3279{
3280 Win32BaseWindow *window;
3281 BOOL rc;
3282 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
3283 DWORD dwStyle;
3284
3285 dprintf(("EnumWindows %x %x", lpfn, lParam));
3286
3287 for(int i=0;i<MAX_WINDOW_HANDLES;i++)
3288 {
3289 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3290 if(window) {
3291 if(window->getWindowHandle() != hwnd) {
3292 dprintf(("CORRUPT WINDOW %x %x", window, hwnd));
3293 }
3294 RELEASE_WNDOBJ(window);
3295 dwStyle = ::GetWindowLongA(hwnd, GWL_STYLE);
3296 if ((dwStyle & WS_POPUP) || ((dwStyle & WS_CAPTION) == WS_CAPTION))
3297 {
3298 dprintf2(("EnumWindows: Found Window %x", hwnd));
3299 if((rc = lpfn(hwnd, lParam)) == FALSE) {
3300 break;
3301 }
3302 }
3303 }
3304 hwnd++;
3305 }
3306 return TRUE;
3307}
3308//******************************************************************************
3309//******************************************************************************
3310HWND Win32BaseWindow::FindWindowById(int id)
3311{
3312 HWND hwnd;
3313
3314 lock();
3315 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3316 {
3317 if (child->getWindowId() == id)
3318 {
3319 hwnd = child->getWindowHandle();
3320 unlock();
3321 return hwnd;
3322 }
3323 }
3324 unlock();
3325 return 0;
3326}
3327//******************************************************************************
3328//TODO:
3329//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3330//the current process owns them.
3331//******************************************************************************
3332HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3333{
3334 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3335 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3336 Win32BaseWindow *firstchild = child;
3337
3338 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3339 if((hwndParent != 0 && !parent) ||
3340 (hwndChildAfter != 0 && !child) ||
3341 (hwndParent == 0 && hwndChildAfter != 0))
3342 {
3343 if(parent) RELEASE_WNDOBJ(parent);
3344 if(firstchild) RELEASE_WNDOBJ(firstchild);
3345 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3346 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3347 return 0;
3348 }
3349 SetLastError(0);
3350 if(hwndParent != 0)
3351 {//if the current process owns the window, just do a quick search
3352 lock(&critsect);
3353 child = (Win32BaseWindow *)parent->getFirstChild();
3354 if(hwndChildAfter != 0)
3355 {
3356 while(child)
3357 {
3358 if(child->getWindowHandle() == hwndChildAfter)
3359 {
3360 child = (Win32BaseWindow *)child->getNextChild();
3361 break;
3362 }
3363 child = (Win32BaseWindow *)child->getNextChild();
3364 }
3365 }
3366 while(child)
3367 {
3368 //According to Wine, the class doesn't need to be specified
3369 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3370 (!lpszWindow || child->hasWindowName(lpszWindow)))
3371 {
3372 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3373 HWND hwndChild = child->getWindowHandle();
3374 unlock(&critsect);
3375 if(parent) RELEASE_WNDOBJ(parent);
3376 if(firstchild) RELEASE_WNDOBJ(firstchild);
3377 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3378 return hwndChild;
3379 }
3380 child = (Win32BaseWindow *)child->getNextChild();
3381 }
3382 unlock(&critsect);
3383 if(parent) RELEASE_WNDOBJ(parent);
3384 if(firstchild) RELEASE_WNDOBJ(firstchild);
3385 }
3386 else {
3387 Win32BaseWindow *wnd;
3388 HWND henum, hwnd;
3389
3390 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3391 hwnd = OSLibWinGetNextWindow(henum);
3392
3393 while(hwnd)
3394 {
3395 wnd = GetWindowFromOS2FrameHandle(hwnd);
3396 if(wnd == NULL) {
3397 hwnd = OSLibWinQueryClientWindow(hwnd);
3398 if(hwnd) wnd = GetWindowFromOS2Handle(hwnd);
3399 }
3400
3401 if(wnd) {
3402 //According to Wine, the class doesn't need to be specified
3403 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3404 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3405 {
3406 OSLibWinEndEnumWindows(henum);
3407 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3408 HWND hwndret = wnd->getWindowHandle();
3409 RELEASE_WNDOBJ(wnd);
3410 return hwndret;
3411 }
3412 RELEASE_WNDOBJ(wnd);
3413 }
3414 hwnd = OSLibWinGetNextWindow(henum);
3415 }
3416 OSLibWinEndEnumWindows(henum);
3417 if(parent) RELEASE_WNDOBJ(parent);
3418 if(firstchild) RELEASE_WNDOBJ(firstchild);
3419 }
3420 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3421 return 0;
3422}
3423//******************************************************************************
3424//******************************************************************************
3425HWND Win32BaseWindow::GetWindow(UINT uCmd)
3426{
3427 HWND hwndRelated = 0;
3428 Win32BaseWindow *window;
3429
3430 switch(uCmd)
3431 {
3432 case GW_HWNDFIRST:
3433 window = (Win32BaseWindow *)getParent();
3434 if(window)
3435 {
3436 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3437 window = GetWindowFromOS2FrameHandle(hwndRelated);
3438 if(window) {
3439 hwndRelated = window->getWindowHandle();
3440 RELEASE_WNDOBJ(window);
3441 }
3442 else hwndRelated = 0;
3443 }
3444 else {
3445 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3446 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3447 }
3448 break;
3449
3450 case GW_HWNDLAST:
3451 window = (Win32BaseWindow *)getParent();
3452 if(window) {
3453 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3454 dprintf(("os2 handle %x", hwndRelated));
3455 window = GetWindowFromOS2FrameHandle(hwndRelated);
3456 if(window) {
3457 hwndRelated = window->getWindowHandle();
3458 RELEASE_WNDOBJ(window);
3459 }
3460 else hwndRelated = 0;
3461 }
3462 else {
3463 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3464 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3465 }
3466 break;
3467
3468 case GW_HWNDNEXT:
3469 if(getParent()) {
3470 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3471 window = GetWindowFromOS2FrameHandle(hwndRelated);
3472 if(window) {
3473 hwndRelated = window->getWindowHandle();
3474 RELEASE_WNDOBJ(window);
3475 }
3476 else hwndRelated = 0;
3477 }
3478 else {
3479 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3480 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3481 }
3482 break;
3483
3484 case GW_HWNDPREV:
3485 if(getParent()) {
3486 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3487 window = GetWindowFromOS2FrameHandle(hwndRelated);
3488 if(window) {
3489 hwndRelated = window->getWindowHandle();
3490 RELEASE_WNDOBJ(window);
3491 }
3492 else hwndRelated = 0;
3493 }
3494 else {
3495 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3496 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3497 }
3498 break;
3499
3500 case GW_OWNER:
3501 {
3502 Win32BaseWindow *owner = getOwner();
3503 if(owner) {
3504 hwndRelated = owner->getWindowHandle();
3505 }
3506 break;
3507 }
3508
3509 case GW_CHILD:
3510 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3511 window = GetWindowFromOS2FrameHandle(hwndRelated);
3512
3513 //Before a window has processed WM_NCCREATE:
3514 //- GetWindow(parent, GW_CHILD) can't return that window handle
3515 //(verified in NT4, SP6)
3516 if(window) {
3517 if(window->state >= STATE_POST_WMNCCREATE) {
3518 hwndRelated = window->getWindowHandle();
3519 RELEASE_WNDOBJ(window);
3520 }
3521 else {
3522 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3523 RELEASE_WNDOBJ(window);
3524 }
3525 }
3526 else hwndRelated = 0;
3527
3528 break;
3529
3530 //for internal use only
3531 case GW_HWNDNEXTCHILD:
3532 lock();
3533 window = (Win32BaseWindow *)getNextChild();
3534 if(window) {
3535 hwndRelated = window->getWindowHandle();
3536 }
3537 else hwndRelated = 0;
3538 unlock();
3539 break;
3540
3541 case GW_HWNDPREVCHILD:
3542 DebugInt3();
3543 break;
3544
3545 case GW_HWNDFIRSTCHILD:
3546 lock();
3547 window = (Win32BaseWindow *)getFirstChild();
3548 if(window) {
3549 hwndRelated = window->getWindowHandle();
3550 }
3551 else hwndRelated = 0;
3552 unlock();
3553 break;
3554
3555 case GW_HWNDLASTCHILD:
3556 lock();
3557 window = (Win32BaseWindow *)getFirstChild();
3558 if(window) {
3559 while (window->getNextChild())
3560 {
3561 window = (Win32BaseWindow *)window->getNextChild();
3562 }
3563 hwndRelated = window->getWindowHandle();
3564 }
3565 else hwndRelated = 0;
3566 unlock();
3567 break;
3568 }
3569end:
3570 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3571 return hwndRelated;
3572}
3573//******************************************************************************
3574//******************************************************************************
3575PRECT Win32BaseWindow::getWindowRect()
3576{
3577 return &rectWindow;
3578}
3579//******************************************************************************
3580//******************************************************************************
3581HWND Win32BaseWindow::SetActiveWindow()
3582{
3583 HWND hwndActive;
3584
3585 dprintf(("SetActiveWindow %x", getWindowHandle()));
3586 if(getStyle() & WS_CHILD) {
3587// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3588 dprintf(("WARNING: Window is a child or disabled"));
3589 return 0;
3590 }
3591
3592 if(GetActiveWindow() == getWindowHandle()) {
3593 dprintf(("Window already active"));
3594 return getWindowHandle();
3595 }
3596 if (HOOK_IsHooked( WH_CBT ))
3597 {
3598 CBTACTIVATESTRUCT cbta;
3599 LRESULT ret;
3600
3601 cbta.fMouse = FALSE;
3602 cbta.hWndActive = GetActiveWindow();
3603 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3604 if(ret)
3605 {
3606 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3607 return cbta.hWndActive;
3608 }
3609 }
3610 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3611
3612// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3613// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3614// }
3615 hwndActive = GetActiveWindow();
3616 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3617}
3618//******************************************************************************
3619//Used to change active status of an mdi window
3620//******************************************************************************
3621BOOL Win32BaseWindow::DeactivateChildWindow()
3622{
3623 /* child windows get a WM_CHILDACTIVATE message */
3624 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3625 {
3626 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3627 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3628 return TRUE;
3629 }
3630 DebugInt3(); //should not be called for non-child window
3631 return FALSE;
3632}
3633//******************************************************************************
3634//WM_ENABLE is sent to hwnd, but not to its children (as it should be)
3635//******************************************************************************
3636BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3637{
3638 BOOL rc;
3639
3640 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3641 //return true if previous state was disabled, else false (sdk docs)
3642 rc = (getStyle() & WS_DISABLED) != 0;
3643 if(rc && !fEnable) {
3644 SendMessageA(getWindowHandle(), WM_CANCELMODE, 0, 0);
3645 }
3646 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3647 if(fEnable == FALSE) {
3648 //SvL: No need to clear focus as PM already does this
3649 if(getWindowHandle() == GetCapture()) {
3650 ReleaseCapture(); /* A disabled window can't capture the mouse */
3651 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3652 }
3653 }
3654 return rc;
3655}
3656//******************************************************************************
3657//******************************************************************************
3658BOOL Win32BaseWindow::CloseWindow()
3659{
3660 if (::GetWindowLongW( getWindowHandle() , GWL_STYLE ) & WS_CHILD) return FALSE;
3661 ShowWindow( SW_MINIMIZE );
3662 return TRUE;
3663}
3664//******************************************************************************
3665//TODO: Not be 100% correct; should return active window of current thread
3666// or NULL when there is none -> WinQueryActiveWindow just returns
3667// the current active window
3668//******************************************************************************
3669HWND Win32BaseWindow::GetActiveWindow()
3670{
3671 HWND hwndActive;
3672
3673 hwndActive = OSLibWinQueryActiveWindow();
3674 return OS2ToWin32Handle(hwndActive);
3675}
3676//******************************************************************************
3677//******************************************************************************
3678BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3679{
3680 INT len = GetWindowTextLength(fUnicode);
3681 BOOL res;
3682
3683 if (wndname == NULL)
3684 return (len == 0);
3685
3686 len++;
3687 if (fUnicode)
3688 {
3689 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3690
3691 GetWindowTextW(text,len);
3692 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3693 free(text);
3694 }
3695 else
3696 {
3697 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3698
3699 GetWindowTextA(text,len);
3700 res = (strcmp(text,wndname) == 0);
3701 free(text);
3702 }
3703
3704 return res;
3705}
3706//******************************************************************************
3707//******************************************************************************
3708CHAR *Win32BaseWindow::getWindowNamePtrA()
3709{
3710 INT len = GetWindowTextLength(FALSE);
3711 CHAR *text;
3712
3713 if (len == 0) return NULL;
3714 len++;
3715 text = (CHAR*)malloc(len*sizeof(CHAR));
3716 GetWindowTextA(text,len);
3717
3718 return text;
3719}
3720//******************************************************************************
3721//******************************************************************************
3722WCHAR *Win32BaseWindow::getWindowNamePtrW()
3723{
3724 INT len = GetWindowTextLength(TRUE);
3725 WCHAR *text;
3726
3727 if (len == 0) return NULL;
3728 len++;
3729 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3730 GetWindowTextW(text,len);
3731
3732 return text;
3733}
3734//******************************************************************************
3735//******************************************************************************
3736VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3737{
3738 if (namePtr) free(namePtr);
3739}
3740//******************************************************************************
3741//When using this API for a window that was created by a different process, NT
3742//does NOT send WM_GETTEXTLENGTH.
3743//******************************************************************************
3744int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3745{
3746 //if the destination window is created by this process, send message
3747 if(dwProcessId == currentProcessId)
3748 {
3749 if(fUnicode) {
3750 return SendMessageW(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3751 }
3752 else return SendMessageA(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3753 }
3754 //else get data directory from window structure
3755 //TODO: must lock window structure.... (TODO)
3756 return windowNameLength;
3757}
3758//******************************************************************************
3759//When using this API for a window that was created by a different process, NT
3760//does NOT send WM_GETTEXT.
3761//******************************************************************************
3762int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3763{
3764 //if the destination window is created by this process, send message
3765 if(dwProcessId == currentProcessId) {
3766 return SendMessageA(getWindowHandle(),WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3767 }
3768
3769 //else get data directory from window structure
3770 if (!lpsz || !cch) return 0;
3771 if (!windowNameA) lpsz[0] = 0;
3772 else memcpy(lpsz, windowNameA, min(windowNameLength + 1, cch) );
3773 return min(windowNameLength, cch);
3774}
3775//******************************************************************************
3776//When using this API for a window that was created by a different process, NT
3777//does NOT send WM_GETTEXT.
3778//******************************************************************************
3779int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3780{
3781 //if the destination window is created by this process, send message
3782 if(dwProcessId == currentProcessId) {
3783 return ::SendMessageW(getWindowHandle(), WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3784 }
3785 //else get data directory from window structure
3786 if (!lpsz || !cch)
3787 return 0;
3788 if (!windowNameW)
3789 lpsz[0] = 0;
3790 else
3791 memcpy(lpsz, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), cch));
3792
3793 return min(windowNameLength, cch);
3794}
3795//******************************************************************************
3796//TODO: How does this work when the target window belongs to a different process???
3797//******************************************************************************
3798BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3799{
3800 return SendMessageA(getWindowHandle(),WM_SETTEXT,0,(LPARAM)lpsz);
3801}
3802//******************************************************************************
3803//******************************************************************************
3804BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3805{
3806 return SendMessageW(getWindowHandle(), WM_SETTEXT,0,(LPARAM)lpsz);
3807}
3808//******************************************************************************
3809//******************************************************************************
3810LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3811{
3812 LONG oldval;
3813
3814 switch(index) {
3815 case GWL_EXSTYLE:
3816 {
3817 STYLESTRUCT ss;
3818
3819 if(dwExStyle == value) {
3820 oldval = value;
3821 break;
3822 }
3823 ss.styleOld = dwExStyle;
3824 ss.styleNew = value;
3825 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3826 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3827 setExStyle(ss.styleNew);
3828 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3829
3830 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3831 getStyle(), getExStyle(),ss.styleOld);
3832
3833 oldval = ss.styleOld;
3834 break;
3835 }
3836 case GWL_STYLE:
3837 {
3838 STYLESTRUCT ss;
3839
3840 //SvL: TODO: Can you change minimize or maximize status here too?
3841
3842 if(dwStyle == value) {
3843 oldval = value;
3844 break;
3845 }
3846 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3847
3848 //Changing WS_CHILD style is allowed
3849 ss.styleOld = getStyle();
3850 ss.styleNew = value;
3851 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3852 setStyle(ss.styleNew);
3853 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3854
3855 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3856 getStyle(), getExStyle(),ss.styleOld);
3857
3858 //TODO: Might not be correct to use ShowWindow here
3859 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3860 if(ss.styleNew & WS_VISIBLE)
3861 ShowWindow(SW_SHOWNOACTIVATE);
3862 else ShowWindow(SW_HIDE);
3863 }
3864
3865#ifdef DEBUG
3866 PrintWindowStyle(ss.styleNew, 0);
3867#endif
3868 oldval = ss.styleOld;
3869 break;
3870 }
3871 case GWL_WNDPROC:
3872 {
3873 //Note: Type of SetWindowLong determines new window proc type
3874 // UNLESS the new window proc has already been registered
3875 // (use the old type in that case)
3876 // (VERIFIED in NT 4, SP6)
3877 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3878 if(type == WIN_PROC_INVALID) {
3879 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3880 }
3881 oldval = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3882 dprintf(("SetWindowLong%c GWL_WNDPROC %x old %x new wndproc %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), oldval, value));
3883 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3884 break;
3885 }
3886 case GWL_HINSTANCE:
3887 oldval = hInstance;
3888 hInstance = value;
3889 break;
3890
3891 case GWL_HWNDPARENT:
3892 dprintf(("GWL_ID GWL_HWNDPARENT %x, new %x", GetParent(), value));
3893 oldval = SetParent((HWND)value);
3894 break;
3895
3896 case GWL_ID:
3897 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3898 oldval = getWindowId();
3899 setWindowId(value);
3900 break;
3901
3902 case GWL_USERDATA:
3903 oldval = userData;
3904 userData = value;
3905 break;
3906
3907 default:
3908 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3909 {
3910 oldval = *(ULONG *)(userWindowBytes + index);
3911 *(ULONG *)(userWindowBytes + index) = value;
3912 break;
3913 }
3914 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3915 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3916 return 0;
3917 }
3918 //Note: NT4, SP6 does not set the last error to 0
3919 SetLastError(ERROR_SUCCESS);
3920 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3921 return oldval;
3922}
3923//******************************************************************************
3924//******************************************************************************
3925ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3926{
3927 ULONG value;
3928
3929 switch(index) {
3930 case GWL_EXSTYLE:
3931 value = dwExStyle;
3932 break;
3933 case GWL_STYLE:
3934 value = dwStyle;
3935 break;
3936 case GWL_WNDPROC:
3937 value = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3938 break;
3939 case GWL_HINSTANCE:
3940 value = hInstance;
3941 break;
3942 case GWL_HWNDPARENT:
3943 value = GetParent();
3944 break;
3945 case GWL_ID:
3946 value = getWindowId();
3947 break;
3948 case GWL_USERDATA:
3949 value = userData;
3950 break;
3951 default:
3952 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3953 {
3954 value = *(ULONG *)(userWindowBytes + index);
3955 break;
3956 }
3957 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3958 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3959 return 0;
3960 }
3961 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3962 //Note: NT4, SP6 does not set the last error to 0
3963 SetLastError(ERROR_SUCCESS);
3964 return value;
3965}
3966//******************************************************************************
3967//******************************************************************************
3968WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3969{
3970 WORD oldval;
3971
3972 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3973 {
3974 oldval = *(WORD *)(userWindowBytes + index);
3975 *(WORD *)(userWindowBytes + index) = value;
3976 //Note: NT4, SP6 does not set the last error to 0
3977 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3978 SetLastError(ERROR_SUCCESS);
3979 return oldval;
3980 }
3981 switch(index)
3982 {
3983 case GWW_HINSTANCE:
3984 oldval = hInstance;
3985 hInstance = value;
3986 break;
3987
3988 case GWW_HWNDPARENT:
3989 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3990 break;
3991
3992 case GWW_ID:
3993 oldval = getWindowId();
3994 setWindowId(value);
3995 break;
3996
3997 default:
3998 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3999 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
4000 return 0;
4001 }
4002 //Note: NT4, SP6 does not set the last error to 0
4003 SetLastError(ERROR_SUCCESS);
4004 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
4005 return oldval;
4006}
4007//******************************************************************************
4008//******************************************************************************
4009WORD Win32BaseWindow::GetWindowWord(int index)
4010{
4011 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
4012 {
4013 //Note: NT4, SP6 does not set the last error to 0
4014 SetLastError(ERROR_SUCCESS);
4015 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
4016 return *(WORD *)(userWindowBytes + index);
4017 }
4018 switch(index)
4019 {
4020 case GWW_ID:
4021 if(HIWORD(getWindowId()))
4022 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
4023 return (WORD)getWindowId();
4024
4025 case GWW_HWNDPARENT:
4026 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
4027 return (WORD) GetParent();
4028
4029 case GWW_HINSTANCE:
4030 if (HIWORD(hInstance))
4031 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
4032 return (WORD)hInstance;
4033 }
4034
4035 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
4036 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
4037 return 0;
4038}
4039//******************************************************************************
4040// Win32BaseWindow::setVisibleRgnNotifyProc
4041//
4042// Sets the visible region change notification handler. Called when
4043// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4044//
4045// Parameters:
4046// VISRGN_NOTIFY_PROC lpNotifyProc - notification handler
4047// DWORD dwUserData - caller supplied parameter for handler invocations
4048//
4049// Returns:
4050// TRUE - Success
4051// FALSE - Failure
4052//
4053//******************************************************************************
4054BOOL Win32BaseWindow::setVisibleRgnNotifyProc(VISRGN_NOTIFY_PROC lpNotifyProc, DWORD dwUserData)
4055{
4056 lpVisRgnNotifyProc = lpNotifyProc;
4057 dwVisRgnNotifyParam = dwUserData;
4058 return TRUE;
4059}
4060//******************************************************************************
4061// Win32BaseWindow::callVisibleRgnNotifyProc
4062//
4063// Call the visible region change notification handler. Called when
4064// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4065//
4066// Parameters:
4067// BOOL fDrawingAllowed - drawing is allowed or not
4068//
4069// Returns:
4070// TRUE - Success
4071// FALSE - Failure
4072//
4073//******************************************************************************
4074void Win32BaseWindow::callVisibleRgnNotifyProc(BOOL fDrawingAllowed)
4075{
4076 if(fDrawingAllowed) {
4077 fWindowLocked = TRUE;
4078 }
4079 else {
4080 fWindowLocked = FALSE;
4081 }
4082 if(lpVisRgnNotifyProc) {
4083 lpVisRgnNotifyProc(getWindowHandle(), fDrawingAllowed, dwVisRgnNotifyParam);
4084 }
4085}
4086//******************************************************************************
4087// Win32BaseWindow::queryOpenDCs
4088//
4089// Return the DCs that are currently open for this window
4090//
4091// Parameters:
4092// HDC *phdcWindow - pointer to HDC array (IN)
4093// int chdcWindow - size of HDC array (IN)
4094// int *pnrdcs - number of HDCs returned (OUT)
4095//
4096// Returns:
4097// TRUE - Success
4098// FALSE - Failure
4099//
4100//******************************************************************************
4101BOOL Win32BaseWindow::queryOpenDCs(HDC *phdcWindow, int chdcWindow, int *pnrdcs)
4102{
4103 if(nrOpenDCs == 0) return FALSE;
4104
4105 if(chdcWindow < nrOpenDCs) {
4106 DebugInt3();
4107 return FALSE;
4108 }
4109
4110 lock(&critsect);
4111 int j = 0;
4112 for(int i=0;i<MAX_OPENDCS && j<nrOpenDCs;i++) {
4113 if(hdcWindow[i] != 0) {
4114 phdcWindow[j] = hdcWindow[i];
4115 j++;
4116 }
4117 }
4118 unlock(&critsect);
4119 *pnrdcs = nrOpenDCs;
4120 return TRUE;
4121}
4122//******************************************************************************
4123// Win32BaseWindow::addOpenDC
4124//
4125// Add DC to list of open DCS
4126//
4127// Parameters:
4128// HDC hdc - HDC to be added to our list of open DCs
4129//
4130// Returns:
4131//
4132//******************************************************************************
4133void Win32BaseWindow::addOpenDC(HDC hdc)
4134{
4135 lock(&critsect);
4136 for(int i=0;i<MAX_OPENDCS;i++) {
4137 if(hdcWindow[i] == 0) {
4138 hdcWindow[i] = hdc;
4139 break;
4140 }
4141 }
4142 unlock(&critsect);
4143 if(i == MAX_OPENDCS) {
4144 DebugInt3(); //no room!
4145 return;
4146 }
4147
4148 dprintf2(("Win32BaseWindow::addOpenDC %x %x %d", getWindowHandle(), hdc, nrOpenDCs+1));
4149 nrOpenDCs++;
4150}
4151//******************************************************************************
4152// Win32BaseWindow::removeOpenDC
4153//
4154// Remove DC from list of open DCS
4155//
4156// Parameters:
4157// HDC hdc - HDC to be removed from our list of open DCs
4158//
4159// Returns:
4160//
4161//******************************************************************************
4162void Win32BaseWindow::removeOpenDC(HDC hdc)
4163{
4164 if(nrOpenDCs == 0) {
4165 dprintf(("Win32BaseWindow::removeOpenDC %x hdc %x not found!! (1)", getWindowHandle(), hdc));
4166 DebugInt3();
4167 return;
4168 }
4169 lock(&critsect);
4170 for(int i=0;i<MAX_OPENDCS;i++) {
4171 if(hdcWindow[i] == hdc) {
4172 hdcWindow[i] = 0;
4173 break;
4174 }
4175 }
4176 unlock(&critsect);
4177 if(i == MAX_OPENDCS) {
4178 dprintf(("Win32BaseWindow::removeOpenDC hdc %x not found!!", hdc));
4179 DebugInt3(); //not found
4180 return;
4181 }
4182 dprintf2(("Win32BaseWindow::removeOpenDC %x %x", getWindowHandle(), hdc, nrOpenDCs-1));
4183 nrOpenDCs--;
4184}
4185//******************************************************************************
4186//Locates window in linked list and increases reference count (if found)
4187//Window object must be unreferenced after usage
4188//******************************************************************************
4189Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
4190{
4191 Win32BaseWindow *window;
4192
4193////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
4194//// while browsing
4195//// Not thread safe now!
4196//// lock(&critsect);
4197 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
4198 if(window) {
4199//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
4200 window->addRef();
4201 }
4202//// unlock(&critsect);
4203 return window;
4204 }
4205//// unlock(&critsect);
4206// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
4207 return NULL;
4208}
4209//******************************************************************************
4210//Locates window in linked list and increases reference count (if found)
4211//Window object must be unreferenced after usage
4212//******************************************************************************
4213Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
4214{
4215 DWORD magic;
4216 HWND hwnd;
4217
4218 if(hwndOS2 == OSLIB_HWND_DESKTOP)
4219 {
4220 windowDesktop->addRef();
4221 return windowDesktop;
4222 }
4223
4224 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
4225 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
4226
4227 if(hwnd && CheckMagicDword(magic)) {
4228 return GetWindowFromHandle(hwnd);
4229 }
4230// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
4231
4232 //Now check if it's a fake window
4233 Win32FakeWindow *window = Win32FakeWindow::GetWindowFromOS2Handle(hwndOS2);
4234 if(window) {
4235 return window;
4236 }
4237 return 0;
4238}
4239//******************************************************************************
4240//Locates window in linked list and increases reference count (if found)
4241//Window object must be unreferenced after usage
4242//******************************************************************************
4243Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
4244{
4245 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
4246}
4247//******************************************************************************
4248//******************************************************************************
4249HWND WIN32API Win32ToOS2Handle(HWND hwnd)
4250{
4251 HWND hwndOS2;
4252
4253 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4254
4255 if(window) {
4256 hwndOS2 = window->getOS2WindowHandle();
4257 RELEASE_WNDOBJ(window);
4258 return hwndOS2;
4259 }
4260// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4261 return hwnd;
4262}
4263//******************************************************************************
4264//******************************************************************************
4265HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
4266{
4267 HWND hwndOS2;
4268
4269 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4270
4271 if(window) {
4272 hwndOS2 = window->getOS2FrameWindowHandle();
4273 RELEASE_WNDOBJ(window);
4274 return hwndOS2;
4275 }
4276// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4277 return hwnd;
4278}
4279//******************************************************************************
4280//******************************************************************************
4281HWND WIN32API OS2ToWin32Handle(HWND hwnd)
4282{
4283 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
4284 HWND hwndWin32;
4285
4286 if(window) {
4287 hwndWin32 = window->getWindowHandle();
4288 RELEASE_WNDOBJ(window);
4289 return hwndWin32;
4290 }
4291 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
4292 if(window) {
4293 hwndWin32 = window->getWindowHandle();
4294 RELEASE_WNDOBJ(window);
4295 return hwndWin32;
4296 }
4297
4298// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
4299 return 0;
4300// else return hwnd; //OS/2 window handle
4301}
4302#ifdef DEBUG
4303LONG Win32BaseWindow::addRef()
4304{
4305// dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
4306 return GenericObject::addRef();
4307}
4308//******************************************************************************
4309//******************************************************************************
4310LONG Win32BaseWindow::release(char *function, int line)
4311{
4312// dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
4313 return GenericObject::release();
4314}
4315#endif
4316//******************************************************************************
4317//******************************************************************************
4318GenericObject *Win32BaseWindow::windows = NULL;
4319CRITICAL_SECTION Win32BaseWindow::critsect = {0};
4320
4321//******************************************************************************
4322//******************************************************************************
4323#ifdef DEBUG
4324void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
4325{
4326 char style[256] = "";
4327 char exstyle[256] = "";
4328
4329 /* Window styles */
4330 if(dwStyle & WS_CHILD)
4331 strcat(style, "WS_CHILD ");
4332 if(dwStyle & WS_POPUP)
4333 strcat(style, "WS_POPUP ");
4334 if(dwStyle & WS_VISIBLE)
4335 strcat(style, "WS_VISIBLE ");
4336 if(dwStyle & WS_DISABLED)
4337 strcat(style, "WS_DISABLED ");
4338 if(dwStyle & WS_CLIPSIBLINGS)
4339 strcat(style, "WS_CLIPSIBLINGS ");
4340 if(dwStyle & WS_CLIPCHILDREN)
4341 strcat(style, "WS_CLIPCHILDREN ");
4342 if(dwStyle & WS_MAXIMIZE)
4343 strcat(style, "WS_MAXIMIZE ");
4344 if(dwStyle & WS_MINIMIZE)
4345 strcat(style, "WS_MINIMIZE ");
4346 if(dwStyle & WS_GROUP)
4347 strcat(style, "WS_GROUP ");
4348 if(dwStyle & WS_TABSTOP)
4349 strcat(style, "WS_TABSTOP ");
4350
4351 if((dwStyle & WS_CAPTION) == WS_CAPTION)
4352 strcat(style, "WS_CAPTION ");
4353 if(dwStyle & WS_DLGFRAME)
4354 strcat(style, "WS_DLGFRAME ");
4355 if(dwStyle & WS_BORDER)
4356 strcat(style, "WS_BORDER ");
4357
4358 if(dwStyle & WS_VSCROLL)
4359 strcat(style, "WS_VSCROLL ");
4360 if(dwStyle & WS_HSCROLL)
4361 strcat(style, "WS_HSCROLL ");
4362 if(dwStyle & WS_SYSMENU)
4363 strcat(style, "WS_SYSMENU ");
4364 if(dwStyle & WS_THICKFRAME)
4365 strcat(style, "WS_THICKFRAME ");
4366 if(dwStyle & WS_MINIMIZEBOX)
4367 strcat(style, "WS_MINIMIZEBOX ");
4368 if(dwStyle & WS_MAXIMIZEBOX)
4369 strcat(style, "WS_MAXIMIZEBOX ");
4370
4371 if(dwExStyle & WS_EX_DLGMODALFRAME)
4372 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
4373 if(dwExStyle & WS_EX_ACCEPTFILES)
4374 strcat(exstyle, "WS_EX_ACCEPTFILES ");
4375 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
4376 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
4377 if(dwExStyle & WS_EX_TOPMOST)
4378 strcat(exstyle, "WS_EX_TOPMOST ");
4379 if(dwExStyle & WS_EX_TRANSPARENT)
4380 strcat(exstyle, "WS_EX_TRANSPARENT ");
4381
4382 if(dwExStyle & WS_EX_MDICHILD)
4383 strcat(exstyle, "WS_EX_MDICHILD ");
4384 if(dwExStyle & WS_EX_TOOLWINDOW)
4385 strcat(exstyle, "WS_EX_TOOLWINDOW ");
4386 if(dwExStyle & WS_EX_WINDOWEDGE)
4387 strcat(exstyle, "WS_EX_WINDOWEDGE ");
4388 if(dwExStyle & WS_EX_CLIENTEDGE)
4389 strcat(exstyle, "WS_EX_CLIENTEDGE ");
4390 if(dwExStyle & WS_EX_CONTEXTHELP)
4391 strcat(exstyle, "WS_EX_CONTEXTHELP ");
4392 if(dwExStyle & WS_EX_RIGHT)
4393 strcat(exstyle, "WS_EX_RIGHT ");
4394 if(dwExStyle & WS_EX_LEFT)
4395 strcat(exstyle, "WS_EX_LEFT ");
4396 if(dwExStyle & WS_EX_RTLREADING)
4397 strcat(exstyle, "WS_EX_RTLREADING ");
4398 if(dwExStyle & WS_EX_LTRREADING)
4399 strcat(exstyle, "WS_EX_LTRREADING ");
4400 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
4401 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
4402 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
4403 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
4404 if(dwExStyle & WS_EX_CONTROLPARENT)
4405 strcat(exstyle, "WS_EX_CONTROLPARENT ");
4406 if(dwExStyle & WS_EX_STATICEDGE)
4407 strcat(exstyle, "WS_EX_STATICEDGE ");
4408 if(dwExStyle & WS_EX_APPWINDOW)
4409 strcat(exstyle, "WS_EX_APPWINDOW ");
4410
4411 dprintf(("Window style: %x %s", dwStyle, style));
4412 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
4413}
4414#endif
4415//******************************************************************************
4416//******************************************************************************
Note: See TracBrowser for help on using the repository browser.