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

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

YD: Resync WM_RBUTTONUP & WM_CONTEXTMENU default window handlers

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