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

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

don't send WM_SETCURSOR if mouse is captured

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