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

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

Enable owner of window destroyed by DestroyWindow. Disabled owners will never be activated by PM

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