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

Last change on this file since 7890 was 7890, checked in by sandervl, 24 years ago

Fixed reference count leaks

File size: 135.1 KB
Line 
1/* $Id: win32wbase.cpp,v 1.314 2002-02-12 18:07:20 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 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2279
2280 if( getStyle() & (WS_MINIMIZE | WS_MAXIMIZE) ) {
2281 swp |= MinMaximize(SW_RESTORE, &newPos );
2282 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2283 }
2284 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2285 break;
2286 }
2287
2288 showFlag = (nCmdShow != SW_HIDE);
2289 if (showFlag != wasVisible)
2290 {
2291 SendMessageA(getWindowHandle(),WM_SHOWWINDOW, showFlag, 0 );
2292 if (!::IsWindow( getWindowHandle() )) goto END;
2293 }
2294
2295 /* We can't activate a child window */
2296 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_MDICHILD))
2297 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2298
2299 SetWindowPos(HWND_TOP, newPos.left, newPos.top, newPos.right, newPos.bottom, LOWORD(swp));
2300
2301 if(!(swp & SWP_NOACTIVATE)) {
2302 OSLibWinSetActiveWindow(OS2HwndFrame);
2303 }
2304
2305 if (flags & WIN_NEED_SIZE)
2306 {
2307 /* should happen only in CreateWindowEx() */
2308 int wParam = SIZE_RESTORED;
2309
2310 flags &= ~WIN_NEED_SIZE;
2311 if (dwStyle & WS_MAXIMIZE)
2312 wParam = SIZE_MAXIMIZED;
2313 else
2314 if (dwStyle & WS_MINIMIZE)
2315 wParam = SIZE_MINIMIZED;
2316
2317 SendMessageA(getWindowHandle(),WM_SIZE, wParam,
2318 MAKELONG(rectClient.right-rectClient.left,
2319 rectClient.bottom-rectClient.top));
2320 SendMessageA(getWindowHandle(),WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
2321 }
2322//testestest
2323 //temporary workaround for file dialogs with template dialog child
2324 //they don't redraw when switching directories
2325 //For some reason the new child's (syslistview32) update rectangle stays
2326 //empty after its parent is made visible with ShowWindow
2327 //TODO: find real cause
2328 if(!wasVisible) {
2329 InvalidateRect(getWindowHandle(), NULL, TRUE);
2330 }
2331//testestest
2332END:
2333 fMinMaxChange = FALSE;
2334 return wasVisible;
2335}
2336//******************************************************************************
2337//******************************************************************************
2338BOOL Win32BaseWindow::SetWindowPos(HWND hwndInsertAfter, int x, int y, int cx, int cy, UINT fuFlags)
2339{
2340 BOOL rc = FALSE;
2341 Win32BaseWindow *window;
2342 HWND hParent = 0;
2343 RECT oldClientRect = rectClient;
2344
2345 if (fuFlags &
2346 ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
2347 SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
2348 SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
2349 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_DEFERERASE |
2350 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE))
2351 {
2352 dprintf(("ERROR: SetWindowPos; UNKNOWN flag"));
2353 return FALSE;
2354 }
2355
2356 if( fuFlags & (SWP_DEFERERASE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)) {
2357 dprintf(("WARNING: SetWindowPos; unsupported flag"));
2358 }
2359
2360 if(IsWindowDestroyed()) {
2361 //changing the position of a window that's being destroyed can cause crashes in PMMERGE
2362 dprintf(("SetWindowPos; window already destroyed"));
2363 return TRUE;
2364 }
2365
2366#if 0
2367 /* Fix redundant flags */
2368 if(getStyle() & WS_VISIBLE) {
2369 fuFlags &= ~SWP_SHOWWINDOW;
2370 }
2371 else
2372 {
2373 if (!(fuFlags & SWP_SHOWWINDOW))
2374 fuFlags |= SWP_NOREDRAW;
2375 fuFlags &= ~SWP_HIDEWINDOW;
2376 }
2377
2378//// if(cx < 0) cx = 0;
2379//// if(cy < 0) cy = 0;
2380
2381 if((rectWindow.right - rectWindow.left == cx) && (rectWindow.bottom - rectWindow.top == cy)) {
2382 fuFlags |= SWP_NOSIZE; /* Already the right size */
2383 }
2384
2385 if((rectWindow.left == x) && (rectWindow.top == y)) {
2386 fuFlags |= SWP_NOMOVE; /* Already the right position */
2387 }
2388
2389 if(getWindowHandle() == GetActiveWindow()) {
2390 fuFlags |= SWP_NOACTIVATE; /* Already active */
2391 }
2392 else
2393 if((getStyle() & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2394 {
2395 if(!(fuFlags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2396 {
2397 fuFlags &= ~SWP_NOZORDER;
2398 hwndInsertAfter = HWND_TOP;
2399 }
2400 }
2401 /* TODO: Check hwndInsertAfter */
2402
2403#endif
2404
2405 //Note: Solitaire crashes when receiving WM_SIZE messages before WM_CREATE
2406 if(state < STATE_POST_WMNCCREATE)
2407 {//don't change size; modify internal structures only
2408 //TODO: not 100% correct yet (activate)
2409 dprintf2(("state < STATE_POST_WMNCCREATE"));
2410 if(!(fuFlags & SWP_NOZORDER)) {
2411 hwndLinkAfter = hwndInsertAfter;
2412 }
2413 if(!(fuFlags & SWP_NOMOVE)) {
2414 rectWindow.bottom = (rectWindow.bottom - rectWindow.top) + y;
2415 rectWindow.top = y;
2416 rectWindow.right = (rectWindow.right - rectWindow.left) + x;
2417 rectWindow.left = x;
2418 }
2419 if(!(fuFlags & SWP_NOSIZE)) {
2420 rectWindow.bottom = rectWindow.top + cy;
2421 rectWindow.right = rectWindow.left + cx;
2422 }
2423 return TRUE;
2424 }
2425
2426 WINDOWPOS wpos;
2427 SWP swp, swpOld;
2428 wpos.flags = fuFlags;
2429 wpos.cy = cy;
2430 wpos.cx = cx;
2431 wpos.x = x;
2432 wpos.y = y;
2433 wpos.hwndInsertAfter = hwndInsertAfter;
2434 wpos.hwnd = getWindowHandle();
2435
2436 if(~fuFlags & (SWP_NOMOVE | SWP_NOSIZE))
2437 {
2438 if (isChild())
2439 {
2440 if(!getParent()) {
2441 dprintf(("WARNING: Win32BaseWindow::SetWindowPos window %x is child but has no parent!!", getWindowHandle()));
2442 }
2443 }
2444 OSLibWinQueryWindowPos(OS2HwndFrame, &swpOld);
2445 }
2446
2447 if(getParent()) {
2448 OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, getParent()->getClientHeight(),
2449 OS2HwndFrame);
2450 }
2451 else OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, OSLibQueryScreenHeight(), OS2HwndFrame);
2452
2453 if (swp.fl == 0) {
2454 dprintf2(("swp.fl == 0"));
2455 if(fuFlags & SWP_FRAMECHANGED)
2456 {
2457 NotifyFrameChanged(&wpos, &oldClientRect);
2458 }
2459 return TRUE;
2460 }
2461
2462// if ((swp.fl & SWPOS_ZORDER) && (swp.hwndInsertBehind > HWNDOS_BOTTOM))
2463 if ((swp.hwndInsertBehind > HWNDOS_BOTTOM))
2464 {
2465 Win32BaseWindow *wndBehind = Win32BaseWindow::GetWindowFromHandle(swp.hwndInsertBehind);
2466 if(wndBehind) {
2467 swp.hwndInsertBehind = wndBehind->getOS2FrameWindowHandle();
2468 RELEASE_WNDOBJ(wndBehind);
2469 }
2470 else {
2471 dprintf(("ERROR: SetWindowPos: hwndInsertBehind %x invalid!",swp.hwndInsertBehind));
2472 swp.hwndInsertBehind = 0;
2473 }
2474 }
2475 swp.hwnd = OS2HwndFrame;
2476
2477 if(fuFlags & SWP_SHOWWINDOW && !IsWindowVisible(getWindowHandle())) {
2478 setStyle(getStyle() | WS_VISIBLE);
2479 if(hTaskList) {
2480 dprintf(("Adding window %x to tasklist", getWindowHandle()));
2481 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 1);
2482 }
2483 }
2484 else
2485 if((fuFlags & SWP_HIDEWINDOW) && IsWindowVisible(getWindowHandle())) {
2486 setStyle(getStyle() & ~WS_VISIBLE);
2487 if(hTaskList && !(getStyle() & WS_MINIMIZE)) {
2488 dprintf(("Removing window %x from tasklist", getWindowHandle()));
2489 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 0);
2490 }
2491 }
2492 dprintf (("WinSetWindowPos %x %x (%d,%d)(%d,%d) %x", swp.hwnd, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, swp.fl));
2493 rc = OSLibWinSetMultWindowPos(&swp, 1);
2494
2495 if(rc == FALSE)
2496 {
2497 dprintf(("OSLibWinSetMultWindowPos failed! Error %x",OSLibWinGetLastError()));
2498 return 0;
2499 }
2500
2501 if((fuFlags & SWP_FRAMECHANGED) && (fuFlags & (SWP_NOMOVE | SWP_NOSIZE) == (SWP_NOMOVE | SWP_NOSIZE)))
2502 {
2503 NotifyFrameChanged(&wpos, &oldClientRect);
2504 }
2505 if(!(getStyle() & (WS_MAXIMIZE|WS_MINIMIZE))) {
2506 //Restore position always changes when the window position is changed
2507 dprintf(("Save new restore position (%d,%d)(%d,%d)", rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2508 windowpos.rcNormalPosition = rectWindow;
2509 }
2510 return (rc);
2511}
2512//******************************************************************************
2513//Called by ScrollWindowEx (dc.cpp) to notify child window that it has moved
2514//******************************************************************************
2515BOOL Win32BaseWindow::ScrollWindow(int dx, int dy)
2516{
2517 rectWindow.left += dx;
2518 rectWindow.right += dx;
2519 rectWindow.top += dy;
2520 rectWindow.bottom += dy;
2521 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left, rectClient.top));
2522 return TRUE;
2523}
2524//******************************************************************************
2525//******************************************************************************
2526void Win32BaseWindow::NotifyFrameChanged(WINDOWPOS *wpos, RECT *oldClientRect)
2527{
2528 HRGN hrgn, hrgnClient;
2529 RECT rect;
2530
2531 MsgFormatFrame(NULL);
2532
2533 if(RECT_WIDTH(rectClient) != RECT_WIDTH(*oldClientRect) ||
2534 RECT_HEIGHT(rectClient) != RECT_HEIGHT(*oldClientRect))
2535 {
2536 wpos->flags &= ~(SWP_NOSIZE|SWP_NOCLIENTSIZE);
2537 wpos->cx = RECT_WIDTH(rectWindow);
2538 wpos->cy = RECT_HEIGHT(rectWindow);
2539 }
2540
2541 if(rectClient.left != oldClientRect->left ||
2542 rectClient.top != oldClientRect->top)
2543 {
2544 wpos->flags &= ~(SWP_NOMOVE|SWP_NOCLIENTMOVE);
2545 wpos->x = rectWindow.left;
2546 wpos->y = rectWindow.top;
2547 }
2548
2549 WINDOWPOS wpOld = *wpos;
2550 if(!(wpos->flags & SWP_NOSENDCHANGING))
2551 SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, (LPARAM)wpos);
2552
2553 if ((wpos->hwndInsertAfter != wpOld.hwndInsertAfter) ||
2554 (wpos->x != wpOld.x) || (wpos->y != wpOld.y) || (wpos->cx != wpOld.cx) || (wpos->cy != wpOld.cy) || (wpos->flags != wpOld.flags))
2555 {
2556 dprintf(("WARNING, NotifyFrameChanged: TODO -> adjust flags!!!!"));
2557 SetWindowPos(wpos->hwndInsertAfter, wpos->x, wpos->y, wpos->cx, wpos->cy, wpos->flags | SWP_NOSENDCHANGING);
2558 }
2559 else SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, (LPARAM)wpos);
2560
2561 //Calculate invalid areas
2562 rect = rectWindow;
2563 OffsetRect(&rect, -rectWindow.left, -rectWindow.top);
2564 hrgn = CreateRectRgnIndirect(&rect);
2565 if (!hrgn) {
2566 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2567 return;
2568 }
2569 rect = rectClient;
2570 hrgnClient = CreateRectRgnIndirect(&rect);
2571 if (!hrgn) {
2572 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2573 return;
2574 }
2575 CombineRgn(hrgn, hrgn, hrgnClient, RGN_DIFF);
2576 DeleteObject(hrgnClient);
2577
2578 if(!EqualRect(oldClientRect, &rectClient)) {
2579 UnionRect(oldClientRect, oldClientRect, &rectClient);
2580 hrgnClient = CreateRectRgnIndirect(oldClientRect);
2581 if (!hrgn) {
2582 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2583 return;
2584 }
2585 CombineRgn(hrgn, hrgn, hrgnClient, RGN_OR);
2586 DeleteObject(hrgnClient);
2587 }
2588 RedrawWindow(getWindowHandle(), NULL, hrgn, RDW_ALLCHILDREN |
2589 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
2590 DeleteObject(hrgn);
2591}
2592//******************************************************************************
2593//TODO: Check how this api really works in NT
2594//******************************************************************************
2595BOOL Win32BaseWindow::SetWindowPlacement(WINDOWPLACEMENT *wndpl)
2596{
2597 dprintf(("SetWindowPlacement %x min (%d,%d)", getWindowHandle(), wndpl->ptMinPosition.x, wndpl->ptMinPosition.y));
2598 dprintf(("SetWindowPlacement %x max (%d,%d)", getWindowHandle(), wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y));
2599 dprintf(("SetWindowPlacement %x norm (%d,%d)(%d,%d)", getWindowHandle(), wndpl->rcNormalPosition.left, wndpl->rcNormalPosition.top, wndpl->rcNormalPosition.right, wndpl->rcNormalPosition.bottom));
2600 windowpos.ptMinPosition = wndpl->ptMinPosition;
2601 windowpos.ptMaxPosition = wndpl->ptMaxPosition;
2602 windowpos.rcNormalPosition = wndpl->rcNormalPosition;
2603
2604 if(getStyle() & WS_MINIMIZE )
2605 {
2606 //TODO: Why can't this be (0,0)?
2607 if(wndpl->flags & WPF_SETMINPOSITION && !(!windowpos.ptMinPosition.x && !windowpos.ptMinPosition.y)) {
2608 SetWindowPos(0, windowpos.ptMinPosition.x, windowpos.ptMinPosition.y,
2609 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2610 }
2611 }
2612 else
2613 if(getStyle() & WS_MAXIMIZE )
2614 {
2615 //TODO: Why can't this be (0,0)?
2616 if(windowpos.ptMaxPosition.x != 0 || windowpos.ptMaxPosition.y != 0 )
2617 SetWindowPos(0, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
2618 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2619 }
2620 else {
2621 SetWindowPos(0, windowpos.rcNormalPosition.left, windowpos.rcNormalPosition.top,
2622 windowpos.rcNormalPosition.right - windowpos.rcNormalPosition.left,
2623 windowpos.rcNormalPosition.bottom - windowpos.rcNormalPosition.top,
2624 SWP_NOZORDER | SWP_NOACTIVATE );
2625 }
2626 ShowWindow(wndpl->showCmd);
2627 if( ::IsWindow(getWindowHandle()) && getStyle() & WS_MINIMIZE )
2628 {
2629 /* SDK: ...valid only the next time... */
2630 if(wndpl->flags & WPF_RESTORETOMAXIMIZED)
2631 setFlags(getFlags() | WIN_RESTORE_MAX);
2632 }
2633 return TRUE;
2634}
2635//******************************************************************************
2636//******************************************************************************
2637BOOL Win32BaseWindow::GetWindowPlacement(LPWINDOWPLACEMENT wndpl)
2638{
2639 wndpl->length = sizeof(*wndpl);
2640 if(getStyle() & WS_MINIMIZE )
2641 wndpl->showCmd = SW_SHOWMINIMIZED;
2642 else wndpl->showCmd = (getStyle() & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
2643
2644 //TODO: Verify if this is correct -> SDK docs claim this flag must always be set to 0
2645 if(getFlags() & WIN_RESTORE_MAX )
2646 wndpl->flags = WPF_RESTORETOMAXIMIZED;
2647 else wndpl->flags = 0;
2648
2649 wndpl->ptMinPosition = windowpos.ptMinPosition;
2650 wndpl->ptMaxPosition = windowpos.ptMaxPosition;
2651 //Must be in parent coordinates (or screen if no parent); verified in NT4, SP6
2652 wndpl->rcNormalPosition = rectWindow;
2653
2654 return TRUE;
2655}
2656//******************************************************************************
2657//Also destroys all the child windows (destroy children first, parent last)
2658//******************************************************************************
2659BOOL Win32BaseWindow::DestroyWindow()
2660{
2661 HWND hwnd = getWindowHandle();
2662
2663 dprintf(("DestroyWindow %x", hwnd));
2664
2665 /* Call hooks */
2666 if(HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, getWindowHandle(), 0L))
2667 {
2668 return FALSE;
2669 }
2670
2671 if(!(getStyle() & WS_CHILD) && getOwner() == NULL)
2672 {
2673 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWDESTROYED, getWindowHandle(), 0L);
2674 /* FIXME: clean up palette - see "Internals" p.352 */
2675 }
2676
2677 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
2678 {
2679 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
2680 {
2681 /* Notify the parent window only */
2682 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
2683 if(!::IsWindow(hwnd) )
2684 {
2685 return TRUE;
2686 }
2687 }
2688//// else DebugInt3();
2689 }
2690 /* Hide the window */
2691 if(IsWindowVisible(getWindowHandle()))
2692 {
2693 SetWindowPos(0, 0, 0, 0, 0, SWP_HIDEWINDOW |
2694 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2695 if(!::IsWindow(hwnd))
2696 {
2697 return TRUE;
2698 }
2699 }
2700 dprintf(("DestroyWindow %x -> HIDDEN", hwnd));
2701
2702 // check the handle for the last active popup window
2703 Win32BaseWindow* owner = getOwner();
2704 if (NULL != owner)
2705 {
2706 if (owner->getLastActive() == hwnd)
2707 owner->setLastActive( owner->getWindowHandle() );
2708 }
2709
2710 fDestroyWindowCalled = TRUE;
2711 return OSLibWinDestroyWindow(OS2HwndFrame);
2712}
2713//******************************************************************************
2714//******************************************************************************
2715Win32BaseWindow *Win32BaseWindow::getParent()
2716{
2717 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2718 return ((ULONG)wndparent == (ULONG)windowDesktop) ? NULL : wndparent;
2719}
2720//******************************************************************************
2721//Note: does not set last error if no parent (verified in NT4, SP6)
2722//******************************************************************************
2723HWND Win32BaseWindow::GetParent()
2724{
2725 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2726
2727 if(getStyle() & WS_CHILD) {
2728 if(wndparent) {
2729 return wndparent->getWindowHandle();
2730 }
2731 dprintf(("WARNING: GetParent: WS_CHILD but no parent!!"));
2732 DebugInt3();
2733 return 0;
2734 }
2735 else
2736 if(getStyle() & WS_POPUP)
2737 return (getOwner()) ? getOwner()->getWindowHandle() : 0;
2738 else return 0;
2739}
2740//******************************************************************************
2741//******************************************************************************
2742HWND Win32BaseWindow::SetParent(HWND hwndNewParent)
2743{
2744 HWND oldhwnd;
2745 Win32BaseWindow *newparent;
2746 Win32BaseWindow *oldparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2747 BOOL fShow = FALSE;
2748
2749 if(oldparent) {
2750 oldhwnd = oldparent->getWindowHandle();
2751 oldparent->removeChild(this);
2752 }
2753 else oldhwnd = 0;
2754
2755 /* Windows hides the window first, then shows it again
2756 * including the WM_SHOWWINDOW messages and all */
2757 if(IsWindowCreated() && (getStyle() & WS_VISIBLE)) {
2758 ShowWindow(SW_HIDE);
2759 fShow = TRUE;
2760 }
2761 if(oldparent) {
2762 //release parent here (increased refcount during creation)
2763 RELEASE_WNDOBJ(oldparent);
2764 }
2765 newparent = GetWindowFromHandle(hwndNewParent);
2766 if(newparent && !newparent->isDesktopWindow())
2767 {
2768 setParent(newparent);
2769 getParent()->addChild(this);
2770 fParentChange = TRUE;
2771
2772 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
2773 if(!(getStyle() & WS_CHILD))
2774 {
2775 //TODO: Send WM_STYLECHANGED msg?
2776 setStyle(getStyle() | WS_CHILD);
2777 if(getWindowId())
2778 {
2779 DestroyMenu( (HMENU) getWindowId() );
2780 setWindowId(0);
2781 }
2782 }
2783 //SvL: Even though the win32 coordinates might not change, the PM
2784 // coordinates can. We must make sure the control stays at the
2785 // same position (y) relative to the (new) parent.
2786 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
2787 SWP_NOACTIVATE|SWP_NOSIZE);
2788 fParentChange = FALSE;
2789 }
2790 else {
2791 if(newparent) RELEASE_WNDOBJ(newparent);
2792
2793 setParent(windowDesktop);
2794 windowDesktop->addRef();
2795 windowDesktop->addChild(this);
2796 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
2797
2798 //TODO: Send WM_STYLECHANGED msg?
2799 setStyle(getStyle() & ~WS_CHILD);
2800 setWindowId(0);
2801 }
2802 /* SetParent additionally needs to make hwndChild the topmost window
2803 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2804 WM_WINDOWPOSCHANGED notification messages.
2805 */
2806 if(state >= STATE_PRE_WMNCCREATE) {
2807 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
2808 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
2809
2810 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2811 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2812 }
2813 return oldhwnd;
2814}
2815//******************************************************************************
2816//******************************************************************************
2817BOOL Win32BaseWindow::IsChild(HWND hwndParent)
2818{
2819 // PH: Optimizer won't unroll calls to getParent() even
2820 // in release build.
2821 Win32BaseWindow *_parent = getParent();
2822
2823 if(_parent)
2824 {
2825 if(_parent->getWindowHandle() == hwndParent)
2826 return TRUE;
2827
2828 return _parent->IsChild(hwndParent);
2829 }
2830 else
2831 return 0;
2832}
2833//******************************************************************************
2834//******************************************************************************
2835HWND Win32BaseWindow::GetTopWindow()
2836{
2837 HWND hwndTop;
2838 Win32BaseWindow *topwindow;
2839
2840 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
2841 if(!isDesktopWindow())
2842 {
2843 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
2844 //Note: GetTopWindow can't return a window that hasn't processed
2845 // WM_NCCREATE yet (verified in NT4, SP6)
2846 if(topwindow) {
2847 if(topwindow->state >= STATE_POST_WMNCCREATE) {
2848 hwndTop = topwindow->getWindowHandle();
2849 }
2850 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
2851 RELEASE_WNDOBJ(topwindow);
2852 return hwndTop;
2853 }
2854 if(topwindow) RELEASE_WNDOBJ(topwindow);
2855 return 0;
2856 }
2857 while(hwndTop) {
2858 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
2859 //Note: GetTopWindow can't return a window that hasn't processed
2860 // WM_NCCREATE yet (verified in NT4, SP6)
2861 if(topwindow) {
2862 if(topwindow->state >= STATE_POST_WMNCCREATE) {
2863 hwndTop = topwindow->getWindowHandle();
2864 }
2865 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
2866 RELEASE_WNDOBJ(topwindow);
2867 return hwndTop;
2868 }
2869 if(topwindow) RELEASE_WNDOBJ(topwindow);
2870 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
2871 }
2872
2873 return 0;
2874}
2875//******************************************************************************
2876// Get the top-level parent for a child window.
2877//******************************************************************************
2878HWND Win32BaseWindow::GetTopParent()
2879{
2880 Win32BaseWindow *window = this;
2881 HWND hwndTopParent = 0;
2882
2883 lock();
2884 while(window && (window->getStyle() & WS_CHILD))
2885 {
2886 window = window->getParent();
2887 }
2888 if(window) {
2889 hwndTopParent = window->getWindowHandle();
2890 }
2891 unlock();
2892 return hwndTopParent;
2893}
2894//******************************************************************************
2895//TODO: Should not enumerate children that are created during the enumeration!
2896//TODO: Do this more efficiently
2897//******************************************************************************
2898BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
2899{
2900 BOOL rc = TRUE;
2901 HWND hwnd;
2902 Win32BaseWindow *prevchild = 0, *child = 0;
2903
2904 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
2905 lock();
2906 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
2907 {
2908 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
2909 hwnd = child->getWindowHandle();
2910 if(child->IsWindowDestroyed() || child->getOwner()) {
2911 continue; //shouldn't have an owner (Wine)
2912 }
2913 child->addRef();
2914 unlock();
2915 if(lpfn(hwnd, lParam) == FALSE)
2916 {
2917 child->release();
2918 return FALSE;
2919 }
2920 child->release();
2921 lock();
2922 //check if the window still exists
2923 if(!::IsWindow(hwnd))
2924 {
2925 child = prevchild;
2926 if(child == NULL) break;
2927 continue;
2928 }
2929 if(child->getFirstChild() != NULL)
2930 {
2931 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
2932 child->addRef();
2933 unlock();
2934 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
2935 {
2936 child->release();
2937 return FALSE;
2938 }
2939 child->release();
2940 lock();
2941 }
2942 prevchild = child;
2943 }
2944 unlock();
2945 return rc;
2946}
2947//******************************************************************************
2948//Enumerate first-level children only and check thread id
2949//******************************************************************************
2950BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
2951{
2952 Win32BaseWindow *child = 0;
2953 ULONG tid, pid;
2954 BOOL rc;
2955 HWND hwnd;
2956
2957 dprintf(("EnumThreadWindows %x %x %x", dwThreadId, lpfn, lParam));
2958
2959 for (child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
2960 {
2961 OSLibWinQueryWindowProcess(child->getOS2WindowHandle(), &pid, &tid);
2962
2963 if(dwThreadId == tid) {
2964 dprintf2(("EnumThreadWindows: Found Window %x", child->getWindowHandle()));
2965 if((rc = lpfn(child->getWindowHandle(), lParam)) == FALSE) {
2966 break;
2967 }
2968 }
2969 }
2970 return TRUE;
2971}
2972//******************************************************************************
2973//Enumerate first-level children only
2974//******************************************************************************
2975BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
2976{
2977 Win32BaseWindow *window;
2978 BOOL rc;
2979 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
2980
2981 dprintf(("EnumWindows %x %x", lpfn, lParam));
2982
2983 for(int i=0;i<MAX_WINDOW_HANDLES;i++)
2984 {
2985 window = GetWindowFromHandle(hwnd++);
2986 if(window)
2987 {
2988 if ((window->getStyle() & WS_POPUP) || ((window->getStyle() & WS_CAPTION) == WS_CAPTION))
2989 {
2990 dprintf2(("EnumWindows: Found Window %x", window->getWindowHandle()));
2991 if((rc = lpfn(window->getWindowHandle(), lParam)) == FALSE) {
2992 break;
2993 }
2994 }
2995 RELEASE_WNDOBJ(window);
2996 }
2997 }
2998 if(window) RELEASE_WNDOBJ(window);
2999 return TRUE;
3000}
3001//******************************************************************************
3002//******************************************************************************
3003HWND Win32BaseWindow::FindWindowById(int id)
3004{
3005 HWND hwnd;
3006
3007 lock();
3008 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3009 {
3010 if (child->getWindowId() == id)
3011 {
3012 hwnd = child->getWindowHandle();
3013 unlock();
3014 return hwnd;
3015 }
3016 }
3017 unlock();
3018 return 0;
3019}
3020//******************************************************************************
3021//TODO:
3022//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3023//the current process owns them.
3024//******************************************************************************
3025HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3026{
3027 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3028 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3029 Win32BaseWindow *firstchild = child;
3030
3031 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3032 if((hwndParent != 0 && !parent) ||
3033 (hwndChildAfter != 0 && !child) ||
3034 (hwndParent == 0 && hwndChildAfter != 0))
3035 {
3036 if(parent) RELEASE_WNDOBJ(parent);
3037 if(firstchild) RELEASE_WNDOBJ(firstchild);
3038 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3039 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3040 return 0;
3041 }
3042 SetLastError(0);
3043 if(hwndParent != 0)
3044 {//if the current process owns the window, just do a quick search
3045 lock(&critsect);
3046 child = (Win32BaseWindow *)parent->getFirstChild();
3047 if(hwndChildAfter != 0)
3048 {
3049 while(child)
3050 {
3051 if(child->getWindowHandle() == hwndChildAfter)
3052 {
3053 child = (Win32BaseWindow *)child->getNextChild();
3054 break;
3055 }
3056 child = (Win32BaseWindow *)child->getNextChild();
3057 }
3058 }
3059 while(child)
3060 {
3061 //According to Wine, the class doesn't need to be specified
3062 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3063 (!lpszWindow || child->hasWindowName(lpszWindow)))
3064 {
3065 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3066 HWND hwndChild = child->getWindowHandle();
3067 unlock(&critsect);
3068 if(parent) RELEASE_WNDOBJ(parent);
3069 if(firstchild) RELEASE_WNDOBJ(firstchild);
3070 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3071 return hwndChild;
3072 }
3073 child = (Win32BaseWindow *)child->getNextChild();
3074 }
3075 unlock(&critsect);
3076 if(parent) RELEASE_WNDOBJ(parent);
3077 if(firstchild) RELEASE_WNDOBJ(firstchild);
3078 }
3079 else {
3080 Win32BaseWindow *wnd;
3081 HWND henum, hwnd;
3082
3083 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3084 hwnd = OSLibWinGetNextWindow(henum);
3085
3086 while(hwnd)
3087 {
3088 wnd = GetWindowFromOS2FrameHandle(hwnd);
3089 if(wnd == NULL) {
3090 hwnd = OSLibWinQueryClientWindow(hwnd);
3091 if(hwnd) wnd = GetWindowFromOS2Handle(hwnd);
3092 }
3093
3094 if(wnd) {
3095 //According to Wine, the class doesn't need to be specified
3096 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3097 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3098 {
3099 OSLibWinEndEnumWindows(henum);
3100 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3101 HWND hwndret = wnd->getWindowHandle();
3102 RELEASE_WNDOBJ(wnd);
3103 return hwndret;
3104 }
3105 RELEASE_WNDOBJ(wnd);
3106 }
3107 hwnd = OSLibWinGetNextWindow(henum);
3108 }
3109 OSLibWinEndEnumWindows(henum);
3110 if(parent) RELEASE_WNDOBJ(parent);
3111 if(firstchild) RELEASE_WNDOBJ(firstchild);
3112 }
3113 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3114 return 0;
3115}
3116//******************************************************************************
3117//******************************************************************************
3118HWND Win32BaseWindow::GetWindow(UINT uCmd)
3119{
3120 HWND hwndRelated = 0;
3121 Win32BaseWindow *window;
3122
3123 switch(uCmd)
3124 {
3125 case GW_HWNDFIRST:
3126 window = (Win32BaseWindow *)getParent();
3127 if(window)
3128 {
3129 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3130 window = GetWindowFromOS2FrameHandle(hwndRelated);
3131 if(window) {
3132 hwndRelated = window->getWindowHandle();
3133 RELEASE_WNDOBJ(window);
3134 }
3135 else hwndRelated = 0;
3136 }
3137 else {
3138 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3139 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3140 }
3141 break;
3142
3143 case GW_HWNDLAST:
3144 window = (Win32BaseWindow *)getParent();
3145 if(window) {
3146 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3147 dprintf(("os2 handle %x", hwndRelated));
3148 window = GetWindowFromOS2FrameHandle(hwndRelated);
3149 if(window) {
3150 hwndRelated = window->getWindowHandle();
3151 RELEASE_WNDOBJ(window);
3152 }
3153 else hwndRelated = 0;
3154 }
3155 else {
3156 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3157 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3158 }
3159 break;
3160
3161 case GW_HWNDNEXT:
3162 if(getParent()) {
3163 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3164 window = GetWindowFromOS2FrameHandle(hwndRelated);
3165 if(window) {
3166 hwndRelated = window->getWindowHandle();
3167 RELEASE_WNDOBJ(window);
3168 }
3169 else hwndRelated = 0;
3170 }
3171 else {
3172 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3173 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3174 }
3175 break;
3176
3177 case GW_HWNDPREV:
3178 if(getParent()) {
3179 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3180 window = GetWindowFromOS2FrameHandle(hwndRelated);
3181 if(window) {
3182 hwndRelated = window->getWindowHandle();
3183 RELEASE_WNDOBJ(window);
3184 }
3185 else hwndRelated = 0;
3186 }
3187 else {
3188 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3189 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3190 }
3191 break;
3192
3193 case GW_OWNER:
3194 {
3195 Win32BaseWindow *owner = getOwner();
3196 if(owner) {
3197 hwndRelated = owner->getWindowHandle();
3198 }
3199 break;
3200 }
3201
3202 case GW_CHILD:
3203 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3204 window = GetWindowFromOS2FrameHandle(hwndRelated);
3205
3206 //Before a window has processed WM_NCCREATE:
3207 //- GetWindow(parent, GW_CHILD) can't return that window handle
3208 //(verified in NT4, SP6)
3209 if(window) {
3210 if(window->state >= STATE_POST_WMNCCREATE) {
3211 hwndRelated = window->getWindowHandle();
3212 RELEASE_WNDOBJ(window);
3213 }
3214 else {
3215 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3216 RELEASE_WNDOBJ(window);
3217 }
3218 }
3219 else hwndRelated = 0;
3220
3221 break;
3222
3223 //for internal use only
3224 case GW_HWNDNEXTCHILD:
3225 lock();
3226 window = (Win32BaseWindow *)getNextChild();
3227 if(window) {
3228 hwndRelated = window->getWindowHandle();
3229 }
3230 else hwndRelated = 0;
3231 unlock();
3232 break;
3233
3234 case GW_HWNDPREVCHILD:
3235 DebugInt3();
3236 break;
3237
3238 case GW_HWNDFIRSTCHILD:
3239 lock();
3240 window = (Win32BaseWindow *)getFirstChild();
3241 if(window) {
3242 hwndRelated = window->getWindowHandle();
3243 }
3244 else hwndRelated = 0;
3245 unlock();
3246 break;
3247
3248 case GW_HWNDLASTCHILD:
3249 lock();
3250 window = (Win32BaseWindow *)getFirstChild();
3251 if(window) {
3252 while (window->getNextChild())
3253 {
3254 window = (Win32BaseWindow *)window->getNextChild();
3255 }
3256 hwndRelated = window->getWindowHandle();
3257 }
3258 else hwndRelated = 0;
3259 unlock();
3260 break;
3261 }
3262end:
3263 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3264 return hwndRelated;
3265}
3266//******************************************************************************
3267//******************************************************************************
3268HWND Win32BaseWindow::SetActiveWindow()
3269{
3270 HWND hwndActive;
3271
3272 dprintf(("SetActiveWindow %x", getWindowHandle()));
3273 if(getStyle() & WS_CHILD) {
3274// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3275 dprintf(("WARNING: Window is a child or disabled"));
3276 return 0;
3277 }
3278
3279 if(GetActiveWindow() == getWindowHandle()) {
3280 dprintf(("Window already active"));
3281 return getWindowHandle();
3282 }
3283 if (HOOK_IsHooked( WH_CBT ))
3284 {
3285 CBTACTIVATESTRUCT cbta;
3286 LRESULT ret;
3287
3288 cbta.fMouse = FALSE;
3289 cbta.hWndActive = GetActiveWindow();
3290 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3291 if(ret)
3292 {
3293 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3294 return cbta.hWndActive;
3295 }
3296 }
3297 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3298
3299// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3300// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3301// }
3302 hwndActive = GetActiveWindow();
3303 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3304}
3305//******************************************************************************
3306//Used to change active status of an mdi window
3307//******************************************************************************
3308BOOL Win32BaseWindow::DeactivateChildWindow()
3309{
3310 /* child windows get a WM_CHILDACTIVATE message */
3311 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3312 {
3313 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3314 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3315 return TRUE;
3316 }
3317 DebugInt3(); //should not be called for non-child window
3318 return FALSE;
3319}
3320//******************************************************************************
3321//WM_ENABLE is sent to hwnd, but not to it's children (as it should be)
3322//******************************************************************************
3323BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3324{
3325 BOOL rc;
3326
3327 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3328 //return true if previous state was disabled, else false (sdk docs)
3329 rc = (getStyle() & WS_DISABLED) != 0;
3330 if(rc && !fEnable) {
3331 SendMessageA(getWindowHandle(), WM_CANCELMODE, 0, 0);
3332 }
3333 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3334 if(fEnable == FALSE) {
3335 //SvL: No need to clear focus as PM already does this
3336 if(getWindowHandle() == GetCapture()) {
3337 ReleaseCapture(); /* A disabled window can't capture the mouse */
3338 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3339 }
3340 }
3341 return rc;
3342}
3343//******************************************************************************
3344//******************************************************************************
3345BOOL Win32BaseWindow::CloseWindow()
3346{
3347 return OSLibWinMinimizeWindow(OS2Hwnd);
3348}
3349//******************************************************************************
3350//TODO: Not be 100% correct; should return active window of current thread
3351// or NULL when there is none -> WinQueryActiveWindow just returns
3352// the current active window
3353//******************************************************************************
3354HWND Win32BaseWindow::GetActiveWindow()
3355{
3356 HWND hwndActive;
3357
3358 hwndActive = OSLibWinQueryActiveWindow();
3359 return OS2ToWin32Handle(hwndActive);
3360}
3361//******************************************************************************
3362//******************************************************************************
3363BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3364{
3365 INT len = GetWindowTextLength(fUnicode);
3366 BOOL res;
3367
3368 if (wndname == NULL)
3369 return (len == 0);
3370
3371 len++;
3372 if (fUnicode)
3373 {
3374 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3375
3376 GetWindowTextW(text,len);
3377 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3378 free(text);
3379 }
3380 else
3381 {
3382 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3383
3384 GetWindowTextA(text,len);
3385 res = (strcmp(text,wndname) == 0);
3386 free(text);
3387 }
3388
3389 return res;
3390}
3391//******************************************************************************
3392//******************************************************************************
3393CHAR *Win32BaseWindow::getWindowNamePtrA()
3394{
3395 INT len = GetWindowTextLength(FALSE);
3396 CHAR *text;
3397
3398 if (len == 0) return NULL;
3399 len++;
3400 text = (CHAR*)malloc(len*sizeof(CHAR));
3401 GetWindowTextA(text,len);
3402
3403 return text;
3404}
3405//******************************************************************************
3406//******************************************************************************
3407WCHAR *Win32BaseWindow::getWindowNamePtrW()
3408{
3409 INT len = GetWindowTextLength(TRUE);
3410 WCHAR *text;
3411
3412 if (len == 0) return NULL;
3413 len++;
3414 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3415 GetWindowTextW(text,len);
3416
3417 return text;
3418}
3419//******************************************************************************
3420//******************************************************************************
3421VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3422{
3423 if (namePtr) free(namePtr);
3424}
3425//******************************************************************************
3426//When using this API for a window that was created by a different process, NT
3427//does NOT send WM_GETTEXTLENGTH.
3428//******************************************************************************
3429int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3430{
3431 //if the destination window is created by this process, send message
3432 if(dwProcessId == currentProcessId)
3433 {
3434 if(fUnicode) {
3435 return SendMessageW(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3436 }
3437 else return SendMessageA(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3438 }
3439 //else get data directory from window structure
3440 //TODO: must lock window structure.... (TODO)
3441 return windowNameLength;
3442}
3443//******************************************************************************
3444//When using this API for a window that was created by a different process, NT
3445//does NOT send WM_GETTEXT.
3446//******************************************************************************
3447int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3448{
3449 //if the destination window is created by this process, send message
3450 if(dwProcessId == currentProcessId) {
3451 return SendMessageA(getWindowHandle(),WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3452 }
3453
3454 //else get data directory from window structure
3455 if (!lpsz || !cch) return 0;
3456 if (!windowNameA) lpsz[0] = 0;
3457 else memcpy(lpsz, windowNameA, min(windowNameLength + 1, cch) );
3458 return min(windowNameLength, cch);
3459}
3460//******************************************************************************
3461//When using this API for a window that was created by a different process, NT
3462//does NOT send WM_GETTEXT.
3463//******************************************************************************
3464int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3465{
3466 //if the destination window is created by this process, send message
3467 if(dwProcessId == currentProcessId) {
3468 return ::SendMessageW(getWindowHandle(), WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3469 }
3470 //else get data directory from window structure
3471 if (!lpsz || !cch)
3472 return 0;
3473 if (!windowNameW)
3474 lpsz[0] = 0;
3475 else
3476 memcpy(lpsz, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), cch));
3477
3478 return min(windowNameLength, cch);
3479}
3480//******************************************************************************
3481//TODO: How does this work when the target window belongs to a different process???
3482//******************************************************************************
3483BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3484{
3485 return SendMessageA(getWindowHandle(),WM_SETTEXT,0,(LPARAM)lpsz);
3486}
3487//******************************************************************************
3488//******************************************************************************
3489BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3490{
3491 return SendMessageW(getWindowHandle(), WM_SETTEXT,0,(LPARAM)lpsz);
3492}
3493//******************************************************************************
3494//******************************************************************************
3495LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3496{
3497 LONG oldval;
3498
3499 switch(index) {
3500 case GWL_EXSTYLE:
3501 {
3502 STYLESTRUCT ss;
3503
3504 if(dwExStyle == value) {
3505 oldval = value;
3506 break;
3507 }
3508 ss.styleOld = dwExStyle;
3509 ss.styleNew = value;
3510 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3511 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3512 setExStyle(ss.styleNew);
3513 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3514 oldval = ss.styleOld;
3515 break;
3516 }
3517 case GWL_STYLE:
3518 {
3519 STYLESTRUCT ss;
3520
3521 //SvL: TODO: Can you change minimize or maximize status here too?
3522
3523 if(dwStyle == value) {
3524 oldval = value;
3525 break;
3526 }
3527 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3528#ifdef DEBUG
3529// if((value & WS_CHILD) != (dwStyle & WS_CHILD)) {
3530// DebugInt3(); //is this allowed?
3531// }
3532#endif
3533 value &= ~(WS_CHILD);
3534 ss.styleOld = getStyle();
3535 ss.styleNew = value | (ss.styleOld & WS_CHILD);
3536 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3537 setStyle(ss.styleNew);
3538 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3539 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
3540
3541 //TODO: Might not be correct to use ShowWindow here
3542 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3543 if(ss.styleNew & WS_VISIBLE)
3544 ShowWindow(SW_SHOWNOACTIVATE);
3545 else ShowWindow(SW_HIDE);
3546 }
3547#ifdef DEBUG
3548 PrintWindowStyle(ss.styleNew, 0);
3549#endif
3550 oldval = ss.styleOld;
3551 break;
3552 }
3553 case GWL_WNDPROC:
3554 {
3555 //Note: Type of SetWindowLong determines new window proc type
3556 // UNLESS the new window proc has already been registered
3557 // (use the old type in that case)
3558 // (VERIFIED in NT 4, SP6)
3559 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3560 if(type == WIN_PROC_INVALID) {
3561 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3562 }
3563 oldval = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3564 dprintf(("SetWindowLong%c GWL_WNDPROC %x old %x new wndproc %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), oldval, value));
3565 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3566 break;
3567 }
3568 case GWL_HINSTANCE:
3569 oldval = hInstance;
3570 hInstance = value;
3571 break;
3572
3573 case GWL_HWNDPARENT:
3574 oldval = SetParent((HWND)value);
3575 break;
3576
3577 case GWL_ID:
3578 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3579 oldval = getWindowId();
3580 setWindowId(value);
3581 break;
3582
3583 case GWL_USERDATA:
3584 oldval = userData;
3585 userData = value;
3586 break;
3587
3588 default:
3589 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3590 {
3591 oldval = *(ULONG *)(userWindowBytes + index);
3592 *(ULONG *)(userWindowBytes + index) = value;
3593 break;
3594 }
3595 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3596 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3597 return 0;
3598 }
3599 //Note: NT4, SP6 does not set the last error to 0
3600 SetLastError(ERROR_SUCCESS);
3601 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3602 return oldval;
3603}
3604//******************************************************************************
3605//******************************************************************************
3606ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3607{
3608 ULONG value;
3609
3610 switch(index) {
3611 case GWL_EXSTYLE:
3612 value = dwExStyle;
3613 break;
3614 case GWL_STYLE:
3615 value = dwStyle;
3616 break;
3617 case GWL_WNDPROC:
3618 value = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3619 break;
3620 case GWL_HINSTANCE:
3621 value = hInstance;
3622 break;
3623 case GWL_HWNDPARENT:
3624 value = GetParent();
3625 break;
3626 case GWL_ID:
3627 value = getWindowId();
3628 break;
3629 case GWL_USERDATA:
3630 value = userData;
3631 break;
3632 default:
3633 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3634 {
3635 value = *(ULONG *)(userWindowBytes + index);
3636 break;
3637 }
3638 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3639 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3640 return 0;
3641 }
3642 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3643 //Note: NT4, SP6 does not set the last error to 0
3644 SetLastError(ERROR_SUCCESS);
3645 return value;
3646}
3647//******************************************************************************
3648//******************************************************************************
3649WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3650{
3651 WORD oldval;
3652
3653 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3654 {
3655 oldval = *(WORD *)(userWindowBytes + index);
3656 *(WORD *)(userWindowBytes + index) = value;
3657 //Note: NT4, SP6 does not set the last error to 0
3658 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3659 SetLastError(ERROR_SUCCESS);
3660 return oldval;
3661 }
3662 switch(index)
3663 {
3664 case GWW_HINSTANCE:
3665 oldval = hInstance;
3666 hInstance = value;
3667 break;
3668
3669 case GWW_HWNDPARENT:
3670 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3671 break;
3672
3673 case GWW_ID:
3674 oldval = getWindowId();
3675 setWindowId(value);
3676 break;
3677
3678 default:
3679 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3680 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3681 return 0;
3682 }
3683 //Note: NT4, SP6 does not set the last error to 0
3684 SetLastError(ERROR_SUCCESS);
3685 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3686 return oldval;
3687}
3688//******************************************************************************
3689//******************************************************************************
3690WORD Win32BaseWindow::GetWindowWord(int index)
3691{
3692 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3693 {
3694 //Note: NT4, SP6 does not set the last error to 0
3695 SetLastError(ERROR_SUCCESS);
3696 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
3697 return *(WORD *)(userWindowBytes + index);
3698 }
3699 switch(index)
3700 {
3701 case GWW_ID:
3702 if(HIWORD(getWindowId()))
3703 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
3704 return (WORD)getWindowId();
3705
3706 case GWW_HWNDPARENT:
3707 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
3708 return (WORD) GetParent();
3709
3710 case GWW_HINSTANCE:
3711 if (HIWORD(hInstance))
3712 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
3713 return (WORD)hInstance;
3714 }
3715
3716 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
3717 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3718 return 0;
3719}
3720//******************************************************************************
3721//Locates window in linked list and increases reference count (if found)
3722//Window object must be unreferenced after usage
3723//******************************************************************************
3724Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
3725{
3726 Win32BaseWindow *window;
3727
3728////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
3729//// while browsing
3730//// Not thread safe now!
3731//// lock(&critsect);
3732 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
3733 if(window) {
3734//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
3735 window->addRef();
3736 }
3737//// unlock(&critsect);
3738 return window;
3739 }
3740//// unlock(&critsect);
3741// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
3742 return NULL;
3743}
3744//******************************************************************************
3745//Locates window in linked list and increases reference count (if found)
3746//Window object must be unreferenced after usage
3747//******************************************************************************
3748Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
3749{
3750 DWORD magic;
3751 HWND hwnd;
3752
3753 if(hwndOS2 == OSLIB_HWND_DESKTOP)
3754 {
3755 windowDesktop->addRef();
3756 return windowDesktop;
3757 }
3758
3759 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
3760 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
3761
3762 if(hwnd && CheckMagicDword(magic)) {
3763 return GetWindowFromHandle(hwnd);
3764 }
3765// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
3766 return 0;
3767}
3768//******************************************************************************
3769//Locates window in linked list and increases reference count (if found)
3770//Window object must be unreferenced after usage
3771//******************************************************************************
3772Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
3773{
3774 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
3775}
3776//******************************************************************************
3777//******************************************************************************
3778HWND WIN32API Win32ToOS2Handle(HWND hwnd)
3779{
3780 HWND hwndOS2;
3781
3782 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3783
3784 if(window) {
3785 hwndOS2 = window->getOS2WindowHandle();
3786 RELEASE_WNDOBJ(window);
3787 return hwndOS2;
3788 }
3789// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3790 return hwnd;
3791}
3792//******************************************************************************
3793//******************************************************************************
3794HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
3795{
3796 HWND hwndOS2;
3797
3798 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3799
3800 if(window) {
3801 hwndOS2 = window->getOS2FrameWindowHandle();
3802 RELEASE_WNDOBJ(window);
3803 return hwndOS2;
3804 }
3805// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3806 return hwnd;
3807}
3808//******************************************************************************
3809//******************************************************************************
3810HWND WIN32API OS2ToWin32Handle(HWND hwnd)
3811{
3812 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
3813 HWND hwndWin32;
3814
3815 if(window) {
3816 hwndWin32 = window->getWindowHandle();
3817 RELEASE_WNDOBJ(window);
3818 return hwndWin32;
3819 }
3820 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
3821 if(window) {
3822 hwndWin32 = window->getWindowHandle();
3823 RELEASE_WNDOBJ(window);
3824 return hwndWin32;
3825 }
3826
3827// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
3828 return 0;
3829// else return hwnd; //OS/2 window handle
3830}
3831#ifdef DEBUG
3832LONG Win32BaseWindow::addRef()
3833{
3834// dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
3835 return GenericObject::addRef();
3836}
3837//******************************************************************************
3838//******************************************************************************
3839LONG Win32BaseWindow::release(char *function, int line)
3840{
3841// dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
3842 return GenericObject::release();
3843}
3844#endif
3845//******************************************************************************
3846//******************************************************************************
3847GenericObject *Win32BaseWindow::windows = NULL;
3848CRITICAL_SECTION Win32BaseWindow::critsect = {0};
3849
3850//******************************************************************************
3851//******************************************************************************
3852#ifdef DEBUG
3853void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
3854{
3855 char style[256] = "";
3856 char exstyle[256] = "";
3857
3858 /* Window styles */
3859 if(dwStyle & WS_CHILD)
3860 strcat(style, "WS_CHILD ");
3861 if(dwStyle & WS_POPUP)
3862 strcat(style, "WS_POPUP ");
3863 if(dwStyle & WS_VISIBLE)
3864 strcat(style, "WS_VISIBLE ");
3865 if(dwStyle & WS_DISABLED)
3866 strcat(style, "WS_DISABLED ");
3867 if(dwStyle & WS_CLIPSIBLINGS)
3868 strcat(style, "WS_CLIPSIBLINGS ");
3869 if(dwStyle & WS_CLIPCHILDREN)
3870 strcat(style, "WS_CLIPCHILDREN ");
3871 if(dwStyle & WS_MAXIMIZE)
3872 strcat(style, "WS_MAXIMIZE ");
3873 if(dwStyle & WS_MINIMIZE)
3874 strcat(style, "WS_MINIMIZE ");
3875 if(dwStyle & WS_GROUP)
3876 strcat(style, "WS_GROUP ");
3877 if(dwStyle & WS_TABSTOP)
3878 strcat(style, "WS_TABSTOP ");
3879
3880 if((dwStyle & WS_CAPTION) == WS_CAPTION)
3881 strcat(style, "WS_CAPTION ");
3882 if(dwStyle & WS_DLGFRAME)
3883 strcat(style, "WS_DLGFRAME ");
3884 if(dwStyle & WS_BORDER)
3885 strcat(style, "WS_BORDER ");
3886
3887 if(dwStyle & WS_VSCROLL)
3888 strcat(style, "WS_VSCROLL ");
3889 if(dwStyle & WS_HSCROLL)
3890 strcat(style, "WS_HSCROLL ");
3891 if(dwStyle & WS_SYSMENU)
3892 strcat(style, "WS_SYSMENU ");
3893 if(dwStyle & WS_THICKFRAME)
3894 strcat(style, "WS_THICKFRAME ");
3895 if(dwStyle & WS_MINIMIZEBOX)
3896 strcat(style, "WS_MINIMIZEBOX ");
3897 if(dwStyle & WS_MAXIMIZEBOX)
3898 strcat(style, "WS_MAXIMIZEBOX ");
3899
3900 if(dwExStyle & WS_EX_DLGMODALFRAME)
3901 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
3902 if(dwExStyle & WS_EX_ACCEPTFILES)
3903 strcat(exstyle, "WS_EX_ACCEPTFILES ");
3904 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
3905 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
3906 if(dwExStyle & WS_EX_TOPMOST)
3907 strcat(exstyle, "WS_EX_TOPMOST ");
3908 if(dwExStyle & WS_EX_TRANSPARENT)
3909 strcat(exstyle, "WS_EX_TRANSPARENT ");
3910
3911 if(dwExStyle & WS_EX_MDICHILD)
3912 strcat(exstyle, "WS_EX_MDICHILD ");
3913 if(dwExStyle & WS_EX_TOOLWINDOW)
3914 strcat(exstyle, "WS_EX_TOOLWINDOW ");
3915 if(dwExStyle & WS_EX_WINDOWEDGE)
3916 strcat(exstyle, "WS_EX_WINDOWEDGE ");
3917 if(dwExStyle & WS_EX_CLIENTEDGE)
3918 strcat(exstyle, "WS_EX_CLIENTEDGE ");
3919 if(dwExStyle & WS_EX_CONTEXTHELP)
3920 strcat(exstyle, "WS_EX_CONTEXTHELP ");
3921 if(dwExStyle & WS_EX_RIGHT)
3922 strcat(exstyle, "WS_EX_RIGHT ");
3923 if(dwExStyle & WS_EX_LEFT)
3924 strcat(exstyle, "WS_EX_LEFT ");
3925 if(dwExStyle & WS_EX_RTLREADING)
3926 strcat(exstyle, "WS_EX_RTLREADING ");
3927 if(dwExStyle & WS_EX_LTRREADING)
3928 strcat(exstyle, "WS_EX_LTRREADING ");
3929 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
3930 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
3931 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
3932 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
3933 if(dwExStyle & WS_EX_CONTROLPARENT)
3934 strcat(exstyle, "WS_EX_CONTROLPARENT ");
3935 if(dwExStyle & WS_EX_STATICEDGE)
3936 strcat(exstyle, "WS_EX_STATICEDGE ");
3937 if(dwExStyle & WS_EX_APPWINDOW)
3938 strcat(exstyle, "WS_EX_APPWINDOW ");
3939
3940 dprintf(("Window style: %x %s", dwStyle, style));
3941 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
3942}
3943#endif
3944//******************************************************************************
3945//******************************************************************************
Note: See TracBrowser for help on using the repository browser.