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

Last change on this file since 7763 was 7762, checked in by sandervl, 24 years ago

CreateFakeWindowEx change

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