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

Last change on this file since 9107 was 9101, checked in by sandervl, 23 years ago

Ugly hack added to work around crash in PM when child window calls DestroyWindow for parent or owner in WM_DESTROY handler (solution: postpone DestroyWindow for parent/owner)

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