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

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

Changes & fixes for minimized windows

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