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

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

PF: Fix for restoring window from minimized state

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