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

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

WS_CHILD style change in SetWindowLong (GWL_STYLE) *is* allowed

File size: 135.1 KB
Line 
1/* $Id: win32wbase.cpp,v 1.328 2002-06-09 19:53:32 sandervl Exp $ */
2/*
3 * Win32 Window Base Class for OS/2
4 *
5 * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 * Copyright 1999-2000 Christoph Bratschi (cbratschi@datacomm.ch)
8 *
9 * Parts based on Wine Windows code (windows\win.c)
10 * Corel version: corel20000212
11 *
12 * Copyright 1993, 1994, 1996 Alexandre Julliard
13 * 1995 Alex Korobka
14 *
15 * TODO: Not thread/process safe
16 *
17 * NOTE: To access a window object, you must call GetWindowFromOS2Handle or
18 * GetWindowFromHandle. Both these methods increase the reference count
19 * of the object. When you're done with the object, you MUST call
20 * the release method!
21 * This mechanism prevents premature destruction of objects when there
22 * are still clients using it.
23 *
24 * NOTE: Client rectangle always relative to frame window
25 * Window rectangle in parent coordinates (relative to parent's client window)
26 * (screen coord. if no parent)
27 *
28 * NOTE: Status of window:
29 * Before a window has processed WM_NCCREATE:
30 * - GetTopWindow can't return that window handle
31 * - GetWindow(parent, GW_CHILD) can't return that window handle
32 * - IsChild works
33 * TODO: Does this affect more functions?? (other GetWindow ops)
34 * (verified in NT4, SP6)
35 *
36 * Project Odin Software License can be found in LICENSE.TXT
37 *
38 */
39#include <os2win.h>
40#include <win.h>
41#include <stdlib.h>
42#include <string.h>
43#include <stdarg.h>
44#include <assert.h>
45#include <misc.h>
46#include <heapstring.h>
47#include <winuser32.h>
48#include <custombuild.h>
49#include "win32wbase.h"
50#include "wndmsg.h"
51#include "oslibwin.h"
52#include "oslibmsg.h"
53#include "oslibutil.h"
54#include "oslibgdi.h"
55#include "oslibres.h"
56#include "oslibdos.h"
57#include "syscolor.h"
58#include "win32wndhandle.h"
59#include "dc.h"
60#include "win32wdesktop.h"
61#include "pmwindow.h"
62#include "controls.h"
63#include <wprocess.h>
64#include <win\hook.h>
65#include <menu.h>
66#define INCL_TIMERWIN32
67#include "timer.h"
68
69#define DBG_LOCALLOG DBG_win32wbase
70#include "dbglocal.h"
71
72/* bits in the dwKeyData */
73#define KEYDATA_ALT 0x2000
74#define KEYDATA_PREVSTATE 0x4000
75
76void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle);
77
78static fDestroyAll = FALSE;
79//For quick lookup of current process id
80static ULONG currentProcessId = -1;
81static int iF10Key = 0;
82static int iMenuSysKey = 0;
83
84//******************************************************************************
85//******************************************************************************
86Win32BaseWindow::Win32BaseWindow()
87 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
88{
89 Init();
90}
91//******************************************************************************
92//******************************************************************************
93Win32BaseWindow::Win32BaseWindow(HWND hwndOS2, ATOM classAtom)
94 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
95{
96 Init();
97 OS2Hwnd = OS2HwndFrame = hwndOS2;
98
99 /* Find the window class */
100 windowClass = Win32WndClass::FindClass(NULL, (LPSTR)classAtom);
101 if (!windowClass)
102 {
103 char buffer[32];
104 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
105 dprintf(("Bad class '%s'", buffer ));
106 DebugInt3();
107 }
108
109 //Allocate window words
110 nrUserWindowBytes = windowClass->getExtraWndBytes();
111 if(nrUserWindowBytes) {
112 userWindowBytes = (char *)_smalloc(nrUserWindowBytes);
113 memset(userWindowBytes, 0, nrUserWindowBytes);
114 }
115
116 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, windowClass->getWindowProc(), WINPROC_GetProcType(windowClass->getWindowProc()), WIN_PROC_WINDOW);
117 hInstance = NULL;
118 dwStyle = WS_VISIBLE;
119 dwOldStyle = dwStyle;
120 dwExStyle = 0;
121
122 //We pretend this window has no parent and won't change size
123 //(dangerous assumption!!)
124 OSLibWinQueryWindowClientRect(OS2Hwnd, &rectClient);
125 OSLibQueryWindowRectAbsolute (OS2Hwnd, &rectWindow);
126
127 fFakeWindow = TRUE;
128}
129//******************************************************************************
130//******************************************************************************
131Win32BaseWindow::Win32BaseWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
132 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
133{
134 Init();
135 this->isUnicode = isUnicode;
136 CreateWindowExA(lpCreateStructA, classAtom);
137}
138//******************************************************************************
139//******************************************************************************
140void Win32BaseWindow::Init()
141{
142 isUnicode = FALSE;
143 fFirstShow = TRUE;
144 fIsDialog = FALSE;
145 fIsModalDialogOwner = FALSE;
146 OS2HwndModalDialog = 0;
147 fParentChange = FALSE;
148 fDestroyWindowCalled = FALSE;
149 fTaskList = FALSE;
150 fParentDC = FALSE;
151 fComingToTop = FALSE;
152 fMinMaxChange = FALSE;
153 fVisibleRegionChanged = FALSE;
154 fEraseBkgndFlag = TRUE;
155 fFakeWindow = FALSE;
156 fIsDragDropActive= FALSE;
157
158 state = STATE_INIT;
159 windowNameA = NULL;
160 windowNameW = NULL;
161 windowNameLength = 0;
162
163 userWindowBytes = NULL;;
164 nrUserWindowBytes= 0;
165
166 OS2Hwnd = 0;
167 OS2HwndFrame = 0;
168 hSysMenu = 0;
169 Win32Hwnd = 0;
170
171 if(HwAllocateWindowHandle(&Win32Hwnd, (ULONG)this) == FALSE)
172 {
173 dprintf(("Win32BaseWindow::Init HwAllocateWindowHandle failed!!"));
174 DebugInt3();
175 }
176
177 posx = posy = 0;
178 width = height = 0;
179
180 dwExStyle = 0;
181 dwStyle = 0;
182 dwOldStyle = 0;
183 win32wndproc = 0;
184 hInstance = 0;
185 dwIDMenu = 0; //0xFFFFFFFF; //default -1
186 userData = 0;
187 contextHelpId = 0;
188 hotkey = 0;
189
190 hwndLinkAfter = HWND_BOTTOM;
191 flags = 0;
192 lastHitTestVal = HTCLIENT;
193 owner = NULL;
194 windowClass = 0;
195
196 hIcon = 0;
197 hIconSm = 0;
198
199 horzScrollInfo = NULL;
200 vertScrollInfo = NULL;
201
202 propertyList = NULL;
203
204 cbExtra = 0;
205 pExtra = NULL;
206
207 ownDC = 0;
208 hWindowRegion = 0;
209 hClipRegion = 0;
210
211 hTaskList = 0;
212
213 if(currentProcessId == -1)
214 {
215 currentProcessId = GetCurrentProcessId();
216 }
217 dwThreadId = GetCurrentThreadId();
218 dwProcessId = currentProcessId;
219
220 memset(&windowpos, 0, sizeof(windowpos));
221 //min and max position are initially -1 (verified in NT4, SP6)
222 windowpos.ptMinPosition.x = -1;
223 windowpos.ptMinPosition.y = -1;
224 windowpos.ptMaxPosition.x = -1;
225 windowpos.ptMaxPosition.y = -1;
226
227 lpVisRgnNotifyProc = NULL;
228 dwVisRgnNotifyParam = NULL;
229}
230//******************************************************************************
231//todo get rid of resources (menu, icon etc)
232//******************************************************************************
233Win32BaseWindow::~Win32BaseWindow()
234{
235 if(getRefCount() < 0) {
236 DebugInt3();
237 }
238
239 if(hTaskList) {
240 OSLibWinRemoveFromTasklist(hTaskList);
241 }
242
243 OSLibWinSetVisibleRegionNotify(OS2Hwnd, FALSE);
244 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, 0);
245 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, 0);
246
247 if(fDestroyAll) {
248 dprintf(("Destroying window %x %s", getWindowHandle(), windowNameA));
249 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
250 }
251 else
252 if(getParent() && getParent()->getFirstChild() == this && getNextChild() == NULL)
253 {
254 //if we're the last child that's being destroyed and our
255 //parent window was also destroyed, then we
256 if(getParent()->IsWindowDestroyed())
257 {
258 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
259 RELEASE_WNDOBJ(wndparent);
260 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
261 }
262 }
263 else
264 {
265 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
266 if(wndparent && !fDestroyAll) {
267 RELEASE_WNDOBJ(wndparent);
268 }
269 }
270 if(owner && !fDestroyAll) {
271 RELEASE_WNDOBJ(owner);
272 }
273
274 /* Decrement class window counter */
275 if(windowClass) {
276 RELEASE_CLASSOBJ(windowClass);
277 }
278
279 if(isOwnDC())
280 releaseOwnDC(ownDC);
281
282 if(Win32Hwnd)
283 HwFreeWindowHandle(Win32Hwnd);
284
285 if(userWindowBytes)
286 free(userWindowBytes);
287
288 if(windowNameA) {
289 free(windowNameA);
290 windowNameA = NULL;
291 }
292 if(windowNameW) {
293 free(windowNameW);
294 windowNameW = NULL;
295 }
296 if(vertScrollInfo) {
297 free(vertScrollInfo);
298 vertScrollInfo = NULL;
299 }
300 if(horzScrollInfo) {
301 free(horzScrollInfo);
302 horzScrollInfo = NULL;
303 }
304 if(propertyList) {
305 removeWindowProps();
306 }
307}
308//******************************************************************************
309//******************************************************************************
310void Win32BaseWindow::DestroyAll()
311{
312 fDestroyAll = TRUE;
313 GenericObject::DestroyAll(windows);
314}
315//******************************************************************************
316//******************************************************************************
317BOOL Win32BaseWindow::isChild()
318{
319 return ((dwStyle & WS_CHILD) != 0);
320}
321//******************************************************************************
322//******************************************************************************
323BOOL Win32BaseWindow::IsWindowUnicode()
324{
325 dprintf2(("IsWindowUnicode %x %d", getWindowHandle(), WINPROC_GetProcType(getWindowProc()) == WIN_PROC_32W));
326 return (WINPROC_GetProcType(getWindowProc()) == WIN_PROC_32W);
327}
328//******************************************************************************
329//******************************************************************************
330BOOL Win32BaseWindow::CreateWindowExA(CREATESTRUCTA *cs, ATOM classAtom)
331{
332 char buffer[256];
333
334#ifdef DEBUG
335 PrintWindowStyle(cs->style, cs->dwExStyle);
336#endif
337
338 //If window has no owner/parent window, then it will be added to the tasklist
339 //(depending on visibility state)
340 if (!cs->hwndParent) fTaskList = TRUE;
341
342 sw = SW_SHOW;
343 SetLastError(0);
344
345 /* Find the parent window */
346 if (cs->hwndParent)
347 {
348 Win32BaseWindow *window = GetWindowFromHandle(cs->hwndParent);
349 if(!window) {
350 dprintf(("Bad parent %04x\n", cs->hwndParent ));
351 SetLastError(ERROR_INVALID_PARAMETER);
352 return FALSE;
353 }
354 /* Make sure parent is valid */
355 if (!window->IsWindow() )
356 {
357 RELEASE_WNDOBJ(window);
358 dprintf(("Bad parent %04x\n", cs->hwndParent ));
359 SetLastError(ERROR_INVALID_PARAMETER);
360 return FALSE;
361 }
362 RELEASE_WNDOBJ(window);
363 /* Windows does this for overlapped windows
364 * (I don't know about other styles.) */
365 if (cs->hwndParent == GetDesktopWindow() && (!(cs->style & WS_CHILD) || (cs->style & WS_POPUP)))
366 {
367 cs->hwndParent = 0;
368 }
369 }
370 else
371 if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
372 dprintf(("No parent for child window" ));
373 SetLastError(ERROR_INVALID_PARAMETER);
374 return FALSE; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
375 }
376
377 /* Find the window class */
378 windowClass = Win32WndClass::FindClass(cs->hInstance, (LPSTR)classAtom);
379 if (!windowClass)
380 {
381 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
382 dprintf(("Bad class '%s'", buffer ));
383 SetLastError(ERROR_INVALID_PARAMETER);
384 return 0;
385 }
386
387#ifdef DEBUG
388 if(HIWORD(cs->lpszClass))
389 {
390 if(isUnicode) dprintf(("Window class %ls", cs->lpszClass));
391 else dprintf(("Window class %s", cs->lpszClass));
392 }
393 else dprintf(("Window class %x", cs->lpszClass));
394#endif
395
396 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
397 * with an atom as the class name, put some programs expect to have a *REAL* string in
398 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
399 */
400 if (!HIWORD(cs->lpszClass) ) {
401 if (isUnicode) {
402 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
403 }
404 else {
405 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
406 }
407 cs->lpszClass = buffer;
408 }
409
410 /* Fix the coordinates */
411 fXDefault = FALSE;
412 fCXDefault = FALSE;
413 if ((cs->x == CW_USEDEFAULT) || (cs->x == CW_USEDEFAULT16))
414 {
415 /* Never believe Microsoft's documentation... CreateWindowEx doc says
416 * that if an overlapped window is created with WS_VISIBLE style bit
417 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
418 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
419 * reveals that
420 *
421 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
422 * 2) it does not ignore the y parameter as the docs claim; instead, it
423 * uses it as second parameter to ShowWindow() unless y is either
424 * CW_USEDEFAULT or CW_USEDEFAULT16.
425 *
426 * The fact that we didn't do 2) caused bogus windows pop up when wine
427 * was running apps that were using this obscure feature. Example -
428 * calc.exe that comes with Win98 (only Win98, it's different from
429 * the one that comes with Win95 and NT)
430 */
431 if ((cs->y != CW_USEDEFAULT) && (cs->y != CW_USEDEFAULT16)) sw = cs->y;
432
433 /* We have saved cs->y, now we can trash it */
434 cs->x = 0;
435 cs->y = 0;
436 fXDefault = TRUE;
437 }
438 if ((cs->cx == CW_USEDEFAULT) || (cs->cx == CW_USEDEFAULT16))
439 {
440 cs->cx = 600; /* FIXME */
441 cs->cy = 400;
442 fCXDefault = TRUE;
443 }
444 if (cs->style & (WS_POPUP | WS_CHILD))
445 {
446 fXDefault = FALSE;
447 if (fCXDefault)
448 {
449 fCXDefault = FALSE;
450 cs->cx = cs->cy = 0;
451 }
452 }
453 if (fXDefault && !fCXDefault) fXDefault = FALSE; //CB: only x positioning doesn't work (calc.exe,cdrlabel.exe)
454
455
456 /* Correct the window style - stage 1
457 *
458 * These are patches that appear to affect both the style loaded into the
459 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
460 *
461 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
462 * why does the user get to set it?
463 */
464
465 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
466 * tested for WS_POPUP
467 */
468 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
469 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
470 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
471 cs->dwExStyle |= WS_EX_WINDOWEDGE;
472 else
473 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
474
475 //Allocate window words
476 nrUserWindowBytes = windowClass->getExtraWndBytes();
477 if(nrUserWindowBytes) {
478 userWindowBytes = (char *)_smalloc(nrUserWindowBytes);
479 memset(userWindowBytes, 0, nrUserWindowBytes);
480 }
481
482 if ((cs->style & WS_CHILD) && cs->hwndParent)
483 {
484 SetParent(cs->hwndParent);
485 owner = 0;
486 //SvL: Shell positioning shouldn't be done for child windows! (breaks Notes)
487 fXDefault = fCXDefault = FALSE;
488 }
489 else
490 {
491 SetParent(0);
492 if (!cs->hwndParent || (cs->hwndParent == windowDesktop->getWindowHandle())) {
493 owner = NULL;
494 }
495 else
496 {
497 Win32BaseWindow *wndparent = GetWindowFromHandle(cs->hwndParent);
498 if(wndparent) {
499 owner = GetWindowFromHandle(wndparent->GetTopParent());
500 RELEASE_WNDOBJ(wndparent);
501 }
502 else owner = NULL;
503
504 if(owner == NULL)
505 {
506 dprintf(("HwGetWindowHandleData couldn't find owner window %x!!!", cs->hwndParent));
507 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
508 return FALSE;
509 }
510 }
511 }
512
513 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, windowClass->getWindowProc(), WINPROC_GetProcType(windowClass->getWindowProc()), WIN_PROC_WINDOW);
514 hInstance = cs->hInstance;
515 dwStyle = cs->style & ~WS_VISIBLE;
516 dwOldStyle = dwStyle;
517 dwExStyle = cs->dwExStyle;
518
519 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
520
521 /* Correct the window style phase 2 */
522 if (!(cs->style & WS_CHILD))
523 {
524 dwStyle |= WS_CLIPSIBLINGS;
525 if (!(cs->style & WS_POPUP))
526 {
527 dwStyle |= WS_CAPTION;
528 flags |= WIN_NEED_SIZE;
529 }
530 }
531 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) dwStyle &= ~WS_THICKFRAME;
532
533 //WinZip 8.0 crashes when a dialog created after opening a zipfile receives
534 //the WM_SIZE message (before WM_INITDIALOG)
535 //Opera doesn't like this either.
536 if(IsDialog()) {
537 flags |= WIN_NEED_SIZE;
538 }
539
540 //copy pointer of CREATESTRUCT for usage in MsgCreate method
541 tmpcs = cs;
542
543 //Store our window object pointer in thread local memory, so PMWINDOW.CPP can retrieve it
544 TEB *teb = GetThreadTEB();
545 if(teb == NULL) {
546 dprintf(("Window creation failed - teb == NULL")); //this is VERY bad
547 ExitProcess(666);
548 return FALSE;
549 }
550
551 teb->o.odin.newWindow = (ULONG)this;
552
553 DWORD dwOSWinStyle, dwOSFrameStyle;
554
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 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
2766 if(!(getStyle() & WS_CHILD))
2767 {
2768 if(getWindowId())
2769 {
2770 DestroyMenu( (HMENU) getWindowId() );
2771 setWindowId(0);
2772 }
2773 }
2774 //SvL: Even though the win32 coordinates might not change, the PM
2775 // coordinates can. We must make sure the control stays at the
2776 // same position (y) relative to the (new) parent.
2777 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
2778 SWP_NOACTIVATE|SWP_NOSIZE);
2779 fParentChange = FALSE;
2780 }
2781 else {
2782 if(newparent) RELEASE_WNDOBJ(newparent);
2783
2784 setParent(windowDesktop);
2785 windowDesktop->addRef();
2786 windowDesktop->addChild(this);
2787 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
2788
2789 setWindowId(0);
2790 }
2791 /* SetParent additionally needs to make hwndChild the topmost window
2792 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2793 WM_WINDOWPOSCHANGED notification messages.
2794 */
2795 if(state >= STATE_PRE_WMNCCREATE) {
2796 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
2797 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
2798
2799 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2800 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2801 }
2802 return oldhwnd;
2803}
2804//******************************************************************************
2805//******************************************************************************
2806BOOL Win32BaseWindow::IsChild(HWND hwndParent)
2807{
2808 // PH: Optimizer won't unroll calls to getParent() even
2809 // in release build.
2810 Win32BaseWindow *_parent = getParent();
2811
2812 if(_parent)
2813 {
2814 if(_parent->getWindowHandle() == hwndParent)
2815 return TRUE;
2816
2817 return _parent->IsChild(hwndParent);
2818 }
2819 else
2820 return 0;
2821}
2822//******************************************************************************
2823//******************************************************************************
2824HWND Win32BaseWindow::GetTopWindow()
2825{
2826 HWND hwndTop;
2827 Win32BaseWindow *topwindow;
2828
2829 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
2830 if(!isDesktopWindow())
2831 {
2832 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
2833 //Note: GetTopWindow can't return a window that hasn't processed
2834 // WM_NCCREATE yet (verified in NT4, SP6)
2835 if(topwindow) {
2836 if(topwindow->state >= STATE_POST_WMNCCREATE) {
2837 hwndTop = topwindow->getWindowHandle();
2838 }
2839 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
2840 RELEASE_WNDOBJ(topwindow);
2841 return hwndTop;
2842 }
2843 if(topwindow) RELEASE_WNDOBJ(topwindow);
2844 return 0;
2845 }
2846 while(hwndTop) {
2847 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
2848 //Note: GetTopWindow can't return a window that hasn't processed
2849 // WM_NCCREATE yet (verified in NT4, SP6)
2850 if(topwindow) {
2851 if(topwindow->state >= STATE_POST_WMNCCREATE) {
2852 hwndTop = topwindow->getWindowHandle();
2853 }
2854 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
2855 RELEASE_WNDOBJ(topwindow);
2856 return hwndTop;
2857 }
2858 if(topwindow) RELEASE_WNDOBJ(topwindow);
2859 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
2860 }
2861
2862 return 0;
2863}
2864//******************************************************************************
2865// Get the top-level parent for a child window.
2866//******************************************************************************
2867HWND Win32BaseWindow::GetTopParent()
2868{
2869 Win32BaseWindow *window = this;
2870 HWND hwndTopParent = 0;
2871
2872 lock();
2873 while(window && (window->getStyle() & WS_CHILD))
2874 {
2875 window = window->getParent();
2876 }
2877 if(window) {
2878 hwndTopParent = window->getWindowHandle();
2879 }
2880 unlock();
2881 return hwndTopParent;
2882}
2883//******************************************************************************
2884//TODO: Should not enumerate children that are created during the enumeration!
2885//TODO: Do this more efficiently
2886//******************************************************************************
2887BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
2888{
2889 BOOL rc = TRUE;
2890 HWND hwnd;
2891 Win32BaseWindow *prevchild = 0, *child = 0;
2892
2893 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
2894 lock();
2895 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
2896 {
2897 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
2898 hwnd = child->getWindowHandle();
2899 if(child->IsWindowDestroyed() || child->getOwner()) {
2900 continue; //shouldn't have an owner (Wine)
2901 }
2902 child->addRef();
2903 unlock();
2904 if(lpfn(hwnd, lParam) == FALSE)
2905 {
2906 child->release();
2907 return FALSE;
2908 }
2909 child->release();
2910 lock();
2911 //check if the window still exists
2912 if(!::IsWindow(hwnd))
2913 {
2914 child = prevchild;
2915 if(child == NULL) break;
2916 continue;
2917 }
2918 if(child->getFirstChild() != NULL)
2919 {
2920 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
2921 child->addRef();
2922 unlock();
2923 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
2924 {
2925 child->release();
2926 return FALSE;
2927 }
2928 child->release();
2929 lock();
2930 }
2931 prevchild = child;
2932 }
2933 unlock();
2934 return rc;
2935}
2936//******************************************************************************
2937//Enumerate first-level children only and check thread id
2938//******************************************************************************
2939BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
2940{
2941 Win32BaseWindow *child = 0;
2942 ULONG tid, pid;
2943 BOOL rc;
2944 HWND hwnd;
2945
2946 dprintf(("EnumThreadWindows %x %x %x", dwThreadId, lpfn, lParam));
2947
2948 for (child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
2949 {
2950 OSLibWinQueryWindowProcess(child->getOS2WindowHandle(), &pid, &tid);
2951
2952 if(dwThreadId == tid) {
2953 dprintf2(("EnumThreadWindows: Found Window %x", child->getWindowHandle()));
2954 if((rc = lpfn(child->getWindowHandle(), lParam)) == FALSE) {
2955 break;
2956 }
2957 }
2958 }
2959 return TRUE;
2960}
2961//******************************************************************************
2962//Enumerate first-level children only
2963//******************************************************************************
2964BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
2965{
2966 Win32BaseWindow *window;
2967 BOOL rc;
2968 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
2969 DWORD dwStyle;
2970
2971 dprintf(("EnumWindows %x %x", lpfn, lParam));
2972
2973 for(int i=0;i<MAX_WINDOW_HANDLES;i++)
2974 {
2975 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
2976 if(window) {
2977 if(window->getWindowHandle() != hwnd) {
2978 dprintf(("CORRUPT WINDOW %x %x", window, hwnd));
2979 }
2980 RELEASE_WNDOBJ(window);
2981 dwStyle = ::GetWindowLongA(hwnd, GWL_STYLE);
2982 if ((dwStyle & WS_POPUP) || ((dwStyle & WS_CAPTION) == WS_CAPTION))
2983 {
2984 dprintf2(("EnumWindows: Found Window %x", hwnd));
2985 if((rc = lpfn(hwnd, lParam)) == FALSE) {
2986 break;
2987 }
2988 }
2989 }
2990 hwnd++;
2991 }
2992 return TRUE;
2993}
2994//******************************************************************************
2995//******************************************************************************
2996HWND Win32BaseWindow::FindWindowById(int id)
2997{
2998 HWND hwnd;
2999
3000 lock();
3001 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3002 {
3003 if (child->getWindowId() == id)
3004 {
3005 hwnd = child->getWindowHandle();
3006 unlock();
3007 return hwnd;
3008 }
3009 }
3010 unlock();
3011 return 0;
3012}
3013//******************************************************************************
3014//TODO:
3015//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3016//the current process owns them.
3017//******************************************************************************
3018HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3019{
3020 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3021 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3022 Win32BaseWindow *firstchild = child;
3023
3024 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3025 if((hwndParent != 0 && !parent) ||
3026 (hwndChildAfter != 0 && !child) ||
3027 (hwndParent == 0 && hwndChildAfter != 0))
3028 {
3029 if(parent) RELEASE_WNDOBJ(parent);
3030 if(firstchild) RELEASE_WNDOBJ(firstchild);
3031 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3032 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3033 return 0;
3034 }
3035 SetLastError(0);
3036 if(hwndParent != 0)
3037 {//if the current process owns the window, just do a quick search
3038 lock(&critsect);
3039 child = (Win32BaseWindow *)parent->getFirstChild();
3040 if(hwndChildAfter != 0)
3041 {
3042 while(child)
3043 {
3044 if(child->getWindowHandle() == hwndChildAfter)
3045 {
3046 child = (Win32BaseWindow *)child->getNextChild();
3047 break;
3048 }
3049 child = (Win32BaseWindow *)child->getNextChild();
3050 }
3051 }
3052 while(child)
3053 {
3054 //According to Wine, the class doesn't need to be specified
3055 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3056 (!lpszWindow || child->hasWindowName(lpszWindow)))
3057 {
3058 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3059 HWND hwndChild = child->getWindowHandle();
3060 unlock(&critsect);
3061 if(parent) RELEASE_WNDOBJ(parent);
3062 if(firstchild) RELEASE_WNDOBJ(firstchild);
3063 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3064 return hwndChild;
3065 }
3066 child = (Win32BaseWindow *)child->getNextChild();
3067 }
3068 unlock(&critsect);
3069 if(parent) RELEASE_WNDOBJ(parent);
3070 if(firstchild) RELEASE_WNDOBJ(firstchild);
3071 }
3072 else {
3073 Win32BaseWindow *wnd;
3074 HWND henum, hwnd;
3075
3076 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3077 hwnd = OSLibWinGetNextWindow(henum);
3078
3079 while(hwnd)
3080 {
3081 wnd = GetWindowFromOS2FrameHandle(hwnd);
3082 if(wnd == NULL) {
3083 hwnd = OSLibWinQueryClientWindow(hwnd);
3084 if(hwnd) wnd = GetWindowFromOS2Handle(hwnd);
3085 }
3086
3087 if(wnd) {
3088 //According to Wine, the class doesn't need to be specified
3089 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3090 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3091 {
3092 OSLibWinEndEnumWindows(henum);
3093 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3094 HWND hwndret = wnd->getWindowHandle();
3095 RELEASE_WNDOBJ(wnd);
3096 return hwndret;
3097 }
3098 RELEASE_WNDOBJ(wnd);
3099 }
3100 hwnd = OSLibWinGetNextWindow(henum);
3101 }
3102 OSLibWinEndEnumWindows(henum);
3103 if(parent) RELEASE_WNDOBJ(parent);
3104 if(firstchild) RELEASE_WNDOBJ(firstchild);
3105 }
3106 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3107 return 0;
3108}
3109//******************************************************************************
3110//******************************************************************************
3111HWND Win32BaseWindow::GetWindow(UINT uCmd)
3112{
3113 HWND hwndRelated = 0;
3114 Win32BaseWindow *window;
3115
3116 switch(uCmd)
3117 {
3118 case GW_HWNDFIRST:
3119 window = (Win32BaseWindow *)getParent();
3120 if(window)
3121 {
3122 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3123 window = GetWindowFromOS2FrameHandle(hwndRelated);
3124 if(window) {
3125 hwndRelated = window->getWindowHandle();
3126 RELEASE_WNDOBJ(window);
3127 }
3128 else hwndRelated = 0;
3129 }
3130 else {
3131 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3132 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3133 }
3134 break;
3135
3136 case GW_HWNDLAST:
3137 window = (Win32BaseWindow *)getParent();
3138 if(window) {
3139 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3140 dprintf(("os2 handle %x", hwndRelated));
3141 window = GetWindowFromOS2FrameHandle(hwndRelated);
3142 if(window) {
3143 hwndRelated = window->getWindowHandle();
3144 RELEASE_WNDOBJ(window);
3145 }
3146 else hwndRelated = 0;
3147 }
3148 else {
3149 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3150 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3151 }
3152 break;
3153
3154 case GW_HWNDNEXT:
3155 if(getParent()) {
3156 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3157 window = GetWindowFromOS2FrameHandle(hwndRelated);
3158 if(window) {
3159 hwndRelated = window->getWindowHandle();
3160 RELEASE_WNDOBJ(window);
3161 }
3162 else hwndRelated = 0;
3163 }
3164 else {
3165 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3166 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3167 }
3168 break;
3169
3170 case GW_HWNDPREV:
3171 if(getParent()) {
3172 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3173 window = GetWindowFromOS2FrameHandle(hwndRelated);
3174 if(window) {
3175 hwndRelated = window->getWindowHandle();
3176 RELEASE_WNDOBJ(window);
3177 }
3178 else hwndRelated = 0;
3179 }
3180 else {
3181 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3182 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3183 }
3184 break;
3185
3186 case GW_OWNER:
3187 {
3188 Win32BaseWindow *owner = getOwner();
3189 if(owner) {
3190 hwndRelated = owner->getWindowHandle();
3191 }
3192 break;
3193 }
3194
3195 case GW_CHILD:
3196 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3197 window = GetWindowFromOS2FrameHandle(hwndRelated);
3198
3199 //Before a window has processed WM_NCCREATE:
3200 //- GetWindow(parent, GW_CHILD) can't return that window handle
3201 //(verified in NT4, SP6)
3202 if(window) {
3203 if(window->state >= STATE_POST_WMNCCREATE) {
3204 hwndRelated = window->getWindowHandle();
3205 RELEASE_WNDOBJ(window);
3206 }
3207 else {
3208 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3209 RELEASE_WNDOBJ(window);
3210 }
3211 }
3212 else hwndRelated = 0;
3213
3214 break;
3215
3216 //for internal use only
3217 case GW_HWNDNEXTCHILD:
3218 lock();
3219 window = (Win32BaseWindow *)getNextChild();
3220 if(window) {
3221 hwndRelated = window->getWindowHandle();
3222 }
3223 else hwndRelated = 0;
3224 unlock();
3225 break;
3226
3227 case GW_HWNDPREVCHILD:
3228 DebugInt3();
3229 break;
3230
3231 case GW_HWNDFIRSTCHILD:
3232 lock();
3233 window = (Win32BaseWindow *)getFirstChild();
3234 if(window) {
3235 hwndRelated = window->getWindowHandle();
3236 }
3237 else hwndRelated = 0;
3238 unlock();
3239 break;
3240
3241 case GW_HWNDLASTCHILD:
3242 lock();
3243 window = (Win32BaseWindow *)getFirstChild();
3244 if(window) {
3245 while (window->getNextChild())
3246 {
3247 window = (Win32BaseWindow *)window->getNextChild();
3248 }
3249 hwndRelated = window->getWindowHandle();
3250 }
3251 else hwndRelated = 0;
3252 unlock();
3253 break;
3254 }
3255end:
3256 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3257 return hwndRelated;
3258}
3259//******************************************************************************
3260//******************************************************************************
3261HWND Win32BaseWindow::SetActiveWindow()
3262{
3263 HWND hwndActive;
3264
3265 dprintf(("SetActiveWindow %x", getWindowHandle()));
3266 if(getStyle() & WS_CHILD) {
3267// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3268 dprintf(("WARNING: Window is a child or disabled"));
3269 return 0;
3270 }
3271
3272 if(GetActiveWindow() == getWindowHandle()) {
3273 dprintf(("Window already active"));
3274 return getWindowHandle();
3275 }
3276 if (HOOK_IsHooked( WH_CBT ))
3277 {
3278 CBTACTIVATESTRUCT cbta;
3279 LRESULT ret;
3280
3281 cbta.fMouse = FALSE;
3282 cbta.hWndActive = GetActiveWindow();
3283 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3284 if(ret)
3285 {
3286 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3287 return cbta.hWndActive;
3288 }
3289 }
3290 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3291
3292// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3293// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3294// }
3295 hwndActive = GetActiveWindow();
3296 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3297}
3298//******************************************************************************
3299//Used to change active status of an mdi window
3300//******************************************************************************
3301BOOL Win32BaseWindow::DeactivateChildWindow()
3302{
3303 /* child windows get a WM_CHILDACTIVATE message */
3304 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3305 {
3306 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3307 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3308 return TRUE;
3309 }
3310 DebugInt3(); //should not be called for non-child window
3311 return FALSE;
3312}
3313//******************************************************************************
3314//WM_ENABLE is sent to hwnd, but not to it's children (as it should be)
3315//******************************************************************************
3316BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3317{
3318 BOOL rc;
3319
3320 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3321 //return true if previous state was disabled, else false (sdk docs)
3322 rc = (getStyle() & WS_DISABLED) != 0;
3323 if(rc && !fEnable) {
3324 SendMessageA(getWindowHandle(), WM_CANCELMODE, 0, 0);
3325 }
3326 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3327 if(fEnable == FALSE) {
3328 //SvL: No need to clear focus as PM already does this
3329 if(getWindowHandle() == GetCapture()) {
3330 ReleaseCapture(); /* A disabled window can't capture the mouse */
3331 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3332 }
3333 }
3334 return rc;
3335}
3336//******************************************************************************
3337//******************************************************************************
3338BOOL Win32BaseWindow::CloseWindow()
3339{
3340 if (::GetWindowLongW( getWindowHandle() , GWL_STYLE ) & WS_CHILD) return FALSE;
3341 ShowWindow( SW_MINIMIZE );
3342 return TRUE;
3343}
3344//******************************************************************************
3345//TODO: Not be 100% correct; should return active window of current thread
3346// or NULL when there is none -> WinQueryActiveWindow just returns
3347// the current active window
3348//******************************************************************************
3349HWND Win32BaseWindow::GetActiveWindow()
3350{
3351 HWND hwndActive;
3352
3353 hwndActive = OSLibWinQueryActiveWindow();
3354 return OS2ToWin32Handle(hwndActive);
3355}
3356//******************************************************************************
3357//******************************************************************************
3358BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3359{
3360 INT len = GetWindowTextLength(fUnicode);
3361 BOOL res;
3362
3363 if (wndname == NULL)
3364 return (len == 0);
3365
3366 len++;
3367 if (fUnicode)
3368 {
3369 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3370
3371 GetWindowTextW(text,len);
3372 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3373 free(text);
3374 }
3375 else
3376 {
3377 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3378
3379 GetWindowTextA(text,len);
3380 res = (strcmp(text,wndname) == 0);
3381 free(text);
3382 }
3383
3384 return res;
3385}
3386//******************************************************************************
3387//******************************************************************************
3388CHAR *Win32BaseWindow::getWindowNamePtrA()
3389{
3390 INT len = GetWindowTextLength(FALSE);
3391 CHAR *text;
3392
3393 if (len == 0) return NULL;
3394 len++;
3395 text = (CHAR*)malloc(len*sizeof(CHAR));
3396 GetWindowTextA(text,len);
3397
3398 return text;
3399}
3400//******************************************************************************
3401//******************************************************************************
3402WCHAR *Win32BaseWindow::getWindowNamePtrW()
3403{
3404 INT len = GetWindowTextLength(TRUE);
3405 WCHAR *text;
3406
3407 if (len == 0) return NULL;
3408 len++;
3409 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3410 GetWindowTextW(text,len);
3411
3412 return text;
3413}
3414//******************************************************************************
3415//******************************************************************************
3416VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3417{
3418 if (namePtr) free(namePtr);
3419}
3420//******************************************************************************
3421//When using this API for a window that was created by a different process, NT
3422//does NOT send WM_GETTEXTLENGTH.
3423//******************************************************************************
3424int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3425{
3426 //if the destination window is created by this process, send message
3427 if(dwProcessId == currentProcessId)
3428 {
3429 if(fUnicode) {
3430 return SendMessageW(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3431 }
3432 else return SendMessageA(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3433 }
3434 //else get data directory from window structure
3435 //TODO: must lock window structure.... (TODO)
3436 return windowNameLength;
3437}
3438//******************************************************************************
3439//When using this API for a window that was created by a different process, NT
3440//does NOT send WM_GETTEXT.
3441//******************************************************************************
3442int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3443{
3444 //if the destination window is created by this process, send message
3445 if(dwProcessId == currentProcessId) {
3446 return SendMessageA(getWindowHandle(),WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3447 }
3448
3449 //else get data directory from window structure
3450 if (!lpsz || !cch) return 0;
3451 if (!windowNameA) lpsz[0] = 0;
3452 else memcpy(lpsz, windowNameA, min(windowNameLength + 1, cch) );
3453 return min(windowNameLength, cch);
3454}
3455//******************************************************************************
3456//When using this API for a window that was created by a different process, NT
3457//does NOT send WM_GETTEXT.
3458//******************************************************************************
3459int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3460{
3461 //if the destination window is created by this process, send message
3462 if(dwProcessId == currentProcessId) {
3463 return ::SendMessageW(getWindowHandle(), WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3464 }
3465 //else get data directory from window structure
3466 if (!lpsz || !cch)
3467 return 0;
3468 if (!windowNameW)
3469 lpsz[0] = 0;
3470 else
3471 memcpy(lpsz, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), cch));
3472
3473 return min(windowNameLength, cch);
3474}
3475//******************************************************************************
3476//TODO: How does this work when the target window belongs to a different process???
3477//******************************************************************************
3478BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3479{
3480 return SendMessageA(getWindowHandle(),WM_SETTEXT,0,(LPARAM)lpsz);
3481}
3482//******************************************************************************
3483//******************************************************************************
3484BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3485{
3486 return SendMessageW(getWindowHandle(), WM_SETTEXT,0,(LPARAM)lpsz);
3487}
3488//******************************************************************************
3489//******************************************************************************
3490LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3491{
3492 LONG oldval;
3493
3494 switch(index) {
3495 case GWL_EXSTYLE:
3496 {
3497 STYLESTRUCT ss;
3498
3499 if(dwExStyle == value) {
3500 oldval = value;
3501 break;
3502 }
3503 ss.styleOld = dwExStyle;
3504 ss.styleNew = value;
3505 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3506 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3507 setExStyle(ss.styleNew);
3508 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3509 oldval = ss.styleOld;
3510 break;
3511 }
3512 case GWL_STYLE:
3513 {
3514 STYLESTRUCT ss;
3515
3516 //SvL: TODO: Can you change minimize or maximize status here too?
3517
3518 if(dwStyle == value) {
3519 oldval = value;
3520 break;
3521 }
3522 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3523
3524 //Changing WS_CHILD style is allowed
3525 ss.styleOld = getStyle();
3526 ss.styleNew = value;
3527 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3528 setStyle(ss.styleNew);
3529 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3530 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
3531
3532 //TODO: Might not be correct to use ShowWindow here
3533 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3534 if(ss.styleNew & WS_VISIBLE)
3535 ShowWindow(SW_SHOWNOACTIVATE);
3536 else ShowWindow(SW_HIDE);
3537 }
3538#ifdef DEBUG
3539 PrintWindowStyle(ss.styleNew, 0);
3540#endif
3541 oldval = ss.styleOld;
3542 break;
3543 }
3544 case GWL_WNDPROC:
3545 {
3546 //Note: Type of SetWindowLong determines new window proc type
3547 // UNLESS the new window proc has already been registered
3548 // (use the old type in that case)
3549 // (VERIFIED in NT 4, SP6)
3550 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3551 if(type == WIN_PROC_INVALID) {
3552 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3553 }
3554 oldval = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3555 dprintf(("SetWindowLong%c GWL_WNDPROC %x old %x new wndproc %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), oldval, value));
3556 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3557 break;
3558 }
3559 case GWL_HINSTANCE:
3560 oldval = hInstance;
3561 hInstance = value;
3562 break;
3563
3564 case GWL_HWNDPARENT:
3565 oldval = SetParent((HWND)value);
3566 break;
3567
3568 case GWL_ID:
3569 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3570 oldval = getWindowId();
3571 setWindowId(value);
3572 break;
3573
3574 case GWL_USERDATA:
3575 oldval = userData;
3576 userData = value;
3577 break;
3578
3579 default:
3580 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3581 {
3582 oldval = *(ULONG *)(userWindowBytes + index);
3583 *(ULONG *)(userWindowBytes + index) = value;
3584 break;
3585 }
3586 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3587 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3588 return 0;
3589 }
3590 //Note: NT4, SP6 does not set the last error to 0
3591 SetLastError(ERROR_SUCCESS);
3592 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3593 return oldval;
3594}
3595//******************************************************************************
3596//******************************************************************************
3597ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3598{
3599 ULONG value;
3600
3601 switch(index) {
3602 case GWL_EXSTYLE:
3603 value = dwExStyle;
3604 break;
3605 case GWL_STYLE:
3606 value = dwStyle;
3607 break;
3608 case GWL_WNDPROC:
3609 value = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3610 break;
3611 case GWL_HINSTANCE:
3612 value = hInstance;
3613 break;
3614 case GWL_HWNDPARENT:
3615 value = GetParent();
3616 break;
3617 case GWL_ID:
3618 value = getWindowId();
3619 break;
3620 case GWL_USERDATA:
3621 value = userData;
3622 break;
3623 default:
3624 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3625 {
3626 value = *(ULONG *)(userWindowBytes + index);
3627 break;
3628 }
3629 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3630 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3631 return 0;
3632 }
3633 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3634 //Note: NT4, SP6 does not set the last error to 0
3635 SetLastError(ERROR_SUCCESS);
3636 return value;
3637}
3638//******************************************************************************
3639//******************************************************************************
3640WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3641{
3642 WORD oldval;
3643
3644 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3645 {
3646 oldval = *(WORD *)(userWindowBytes + index);
3647 *(WORD *)(userWindowBytes + index) = value;
3648 //Note: NT4, SP6 does not set the last error to 0
3649 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3650 SetLastError(ERROR_SUCCESS);
3651 return oldval;
3652 }
3653 switch(index)
3654 {
3655 case GWW_HINSTANCE:
3656 oldval = hInstance;
3657 hInstance = value;
3658 break;
3659
3660 case GWW_HWNDPARENT:
3661 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3662 break;
3663
3664 case GWW_ID:
3665 oldval = getWindowId();
3666 setWindowId(value);
3667 break;
3668
3669 default:
3670 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3671 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3672 return 0;
3673 }
3674 //Note: NT4, SP6 does not set the last error to 0
3675 SetLastError(ERROR_SUCCESS);
3676 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3677 return oldval;
3678}
3679//******************************************************************************
3680//******************************************************************************
3681WORD Win32BaseWindow::GetWindowWord(int index)
3682{
3683 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3684 {
3685 //Note: NT4, SP6 does not set the last error to 0
3686 SetLastError(ERROR_SUCCESS);
3687 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
3688 return *(WORD *)(userWindowBytes + index);
3689 }
3690 switch(index)
3691 {
3692 case GWW_ID:
3693 if(HIWORD(getWindowId()))
3694 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
3695 return (WORD)getWindowId();
3696
3697 case GWW_HWNDPARENT:
3698 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
3699 return (WORD) GetParent();
3700
3701 case GWW_HINSTANCE:
3702 if (HIWORD(hInstance))
3703 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
3704 return (WORD)hInstance;
3705 }
3706
3707 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
3708 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3709 return 0;
3710}
3711//******************************************************************************
3712//Locates window in linked list and increases reference count (if found)
3713//Window object must be unreferenced after usage
3714//******************************************************************************
3715Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
3716{
3717 Win32BaseWindow *window;
3718
3719////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
3720//// while browsing
3721//// Not thread safe now!
3722//// lock(&critsect);
3723 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
3724 if(window) {
3725//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
3726 window->addRef();
3727 }
3728//// unlock(&critsect);
3729 return window;
3730 }
3731//// unlock(&critsect);
3732// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
3733 return NULL;
3734}
3735//******************************************************************************
3736//Locates window in linked list and increases reference count (if found)
3737//Window object must be unreferenced after usage
3738//******************************************************************************
3739Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
3740{
3741 DWORD magic;
3742 HWND hwnd;
3743
3744 if(hwndOS2 == OSLIB_HWND_DESKTOP)
3745 {
3746 windowDesktop->addRef();
3747 return windowDesktop;
3748 }
3749
3750 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
3751 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
3752
3753 if(hwnd && CheckMagicDword(magic)) {
3754 return GetWindowFromHandle(hwnd);
3755 }
3756// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
3757 return 0;
3758}
3759//******************************************************************************
3760//Locates window in linked list and increases reference count (if found)
3761//Window object must be unreferenced after usage
3762//******************************************************************************
3763Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
3764{
3765 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
3766}
3767//******************************************************************************
3768//******************************************************************************
3769HWND WIN32API Win32ToOS2Handle(HWND hwnd)
3770{
3771 HWND hwndOS2;
3772
3773 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3774
3775 if(window) {
3776 hwndOS2 = window->getOS2WindowHandle();
3777 RELEASE_WNDOBJ(window);
3778 return hwndOS2;
3779 }
3780// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3781 return hwnd;
3782}
3783//******************************************************************************
3784//******************************************************************************
3785HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
3786{
3787 HWND hwndOS2;
3788
3789 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3790
3791 if(window) {
3792 hwndOS2 = window->getOS2FrameWindowHandle();
3793 RELEASE_WNDOBJ(window);
3794 return hwndOS2;
3795 }
3796// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3797 return hwnd;
3798}
3799//******************************************************************************
3800//******************************************************************************
3801HWND WIN32API OS2ToWin32Handle(HWND hwnd)
3802{
3803 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
3804 HWND hwndWin32;
3805
3806 if(window) {
3807 hwndWin32 = window->getWindowHandle();
3808 RELEASE_WNDOBJ(window);
3809 return hwndWin32;
3810 }
3811 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
3812 if(window) {
3813 hwndWin32 = window->getWindowHandle();
3814 RELEASE_WNDOBJ(window);
3815 return hwndWin32;
3816 }
3817
3818// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
3819 return 0;
3820// else return hwnd; //OS/2 window handle
3821}
3822#ifdef DEBUG
3823LONG Win32BaseWindow::addRef()
3824{
3825// dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
3826 return GenericObject::addRef();
3827}
3828//******************************************************************************
3829//******************************************************************************
3830LONG Win32BaseWindow::release(char *function, int line)
3831{
3832// dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
3833 return GenericObject::release();
3834}
3835#endif
3836//******************************************************************************
3837//******************************************************************************
3838GenericObject *Win32BaseWindow::windows = NULL;
3839CRITICAL_SECTION Win32BaseWindow::critsect = {0};
3840
3841//******************************************************************************
3842//******************************************************************************
3843#ifdef DEBUG
3844void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
3845{
3846 char style[256] = "";
3847 char exstyle[256] = "";
3848
3849 /* Window styles */
3850 if(dwStyle & WS_CHILD)
3851 strcat(style, "WS_CHILD ");
3852 if(dwStyle & WS_POPUP)
3853 strcat(style, "WS_POPUP ");
3854 if(dwStyle & WS_VISIBLE)
3855 strcat(style, "WS_VISIBLE ");
3856 if(dwStyle & WS_DISABLED)
3857 strcat(style, "WS_DISABLED ");
3858 if(dwStyle & WS_CLIPSIBLINGS)
3859 strcat(style, "WS_CLIPSIBLINGS ");
3860 if(dwStyle & WS_CLIPCHILDREN)
3861 strcat(style, "WS_CLIPCHILDREN ");
3862 if(dwStyle & WS_MAXIMIZE)
3863 strcat(style, "WS_MAXIMIZE ");
3864 if(dwStyle & WS_MINIMIZE)
3865 strcat(style, "WS_MINIMIZE ");
3866 if(dwStyle & WS_GROUP)
3867 strcat(style, "WS_GROUP ");
3868 if(dwStyle & WS_TABSTOP)
3869 strcat(style, "WS_TABSTOP ");
3870
3871 if((dwStyle & WS_CAPTION) == WS_CAPTION)
3872 strcat(style, "WS_CAPTION ");
3873 if(dwStyle & WS_DLGFRAME)
3874 strcat(style, "WS_DLGFRAME ");
3875 if(dwStyle & WS_BORDER)
3876 strcat(style, "WS_BORDER ");
3877
3878 if(dwStyle & WS_VSCROLL)
3879 strcat(style, "WS_VSCROLL ");
3880 if(dwStyle & WS_HSCROLL)
3881 strcat(style, "WS_HSCROLL ");
3882 if(dwStyle & WS_SYSMENU)
3883 strcat(style, "WS_SYSMENU ");
3884 if(dwStyle & WS_THICKFRAME)
3885 strcat(style, "WS_THICKFRAME ");
3886 if(dwStyle & WS_MINIMIZEBOX)
3887 strcat(style, "WS_MINIMIZEBOX ");
3888 if(dwStyle & WS_MAXIMIZEBOX)
3889 strcat(style, "WS_MAXIMIZEBOX ");
3890
3891 if(dwExStyle & WS_EX_DLGMODALFRAME)
3892 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
3893 if(dwExStyle & WS_EX_ACCEPTFILES)
3894 strcat(exstyle, "WS_EX_ACCEPTFILES ");
3895 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
3896 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
3897 if(dwExStyle & WS_EX_TOPMOST)
3898 strcat(exstyle, "WS_EX_TOPMOST ");
3899 if(dwExStyle & WS_EX_TRANSPARENT)
3900 strcat(exstyle, "WS_EX_TRANSPARENT ");
3901
3902 if(dwExStyle & WS_EX_MDICHILD)
3903 strcat(exstyle, "WS_EX_MDICHILD ");
3904 if(dwExStyle & WS_EX_TOOLWINDOW)
3905 strcat(exstyle, "WS_EX_TOOLWINDOW ");
3906 if(dwExStyle & WS_EX_WINDOWEDGE)
3907 strcat(exstyle, "WS_EX_WINDOWEDGE ");
3908 if(dwExStyle & WS_EX_CLIENTEDGE)
3909 strcat(exstyle, "WS_EX_CLIENTEDGE ");
3910 if(dwExStyle & WS_EX_CONTEXTHELP)
3911 strcat(exstyle, "WS_EX_CONTEXTHELP ");
3912 if(dwExStyle & WS_EX_RIGHT)
3913 strcat(exstyle, "WS_EX_RIGHT ");
3914 if(dwExStyle & WS_EX_LEFT)
3915 strcat(exstyle, "WS_EX_LEFT ");
3916 if(dwExStyle & WS_EX_RTLREADING)
3917 strcat(exstyle, "WS_EX_RTLREADING ");
3918 if(dwExStyle & WS_EX_LTRREADING)
3919 strcat(exstyle, "WS_EX_LTRREADING ");
3920 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
3921 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
3922 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
3923 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
3924 if(dwExStyle & WS_EX_CONTROLPARENT)
3925 strcat(exstyle, "WS_EX_CONTROLPARENT ");
3926 if(dwExStyle & WS_EX_STATICEDGE)
3927 strcat(exstyle, "WS_EX_STATICEDGE ");
3928 if(dwExStyle & WS_EX_APPWINDOW)
3929 strcat(exstyle, "WS_EX_APPWINDOW ");
3930
3931 dprintf(("Window style: %x %s", dwStyle, style));
3932 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
3933}
3934#endif
3935//******************************************************************************
3936//******************************************************************************
Note: See TracBrowser for help on using the repository browser.