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

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

adding documentation

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