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

Last change on this file since 8954 was 8945, checked in by achimha, 23 years ago

adding documentation

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