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

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

added ole drag and drop (wps -> odin app) support

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