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

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

WM_CTLCOLOR fix for buttonsbutton.cpp

File size: 140.2 KB
Line 
1/* $Id: win32wbase.cpp,v 1.306 2001-12-26 11:35:39 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 SendInternalMessageA(WM_SETCURSOR, Win32Hwnd, MAKELONG(lastHitTestVal, msg->message));
1185
1186 //translated message == WM_(NC)MOUSEMOVE
1187 return SendInternalMessageA(msg->message, msg->wParam, msg->lParam);
1188}
1189//******************************************************************************
1190//******************************************************************************
1191ULONG Win32BaseWindow::MsgChar(MSG *msg)
1192{
1193 return DispatchMsgA(msg);
1194}
1195//******************************************************************************
1196//TODO: Should use update region, not rectangle
1197//******************************************************************************
1198ULONG Win32BaseWindow::MsgNCPaint(PRECT pUpdateRect)
1199{
1200 HRGN hrgn;
1201 ULONG rc;
1202 RECT client = rectClient;
1203
1204 if ((pUpdateRect->left >= client.left) && (pUpdateRect->left < client.right) &&
1205 (pUpdateRect->right >= client.left) && (pUpdateRect->right < client.right) &&
1206 (pUpdateRect->top >= client.top) && (pUpdateRect->top < client.bottom) &&
1207 (pUpdateRect->bottom >= client.top) && (pUpdateRect->bottom < client.bottom))
1208 {
1209 return 0;
1210 }
1211
1212 dprintf(("MsgNCPaint (%d,%d)(%d,%d)", pUpdateRect->left, pUpdateRect->top, pUpdateRect->right, pUpdateRect->bottom));
1213 hrgn = CreateRectRgnIndirect(pUpdateRect);
1214
1215 rc = SendInternalMessageA(WM_NCPAINT, hrgn, 0);
1216
1217 DeleteObject(hrgn);
1218
1219 return rc;
1220}
1221//******************************************************************************
1222//Called when either the frame's size or position has changed (lpWndPos != NULL)
1223//or when the frame layout has changed (i.e. scrollbars added/removed) (lpWndPos == NULL)
1224//******************************************************************************
1225ULONG Win32BaseWindow::MsgFormatFrame(WINDOWPOS *lpWndPos)
1226{
1227 RECT oldWindowRect = rectWindow, client = rectClient, newWindowRect;
1228 RECT newClientRect;
1229 WINDOWPOS wndPos;
1230 ULONG rc;
1231
1232 if(lpWndPos)
1233 {
1234 //set new window rectangle
1235 setWindowRect(lpWndPos->x, lpWndPos->y, lpWndPos->x+lpWndPos->cx,
1236 lpWndPos->y+lpWndPos->cy);
1237 newWindowRect = rectWindow;
1238 }
1239 else {
1240 wndPos.hwnd = getWindowHandle();
1241 wndPos.hwndInsertAfter = 0;
1242 newWindowRect= rectWindow;
1243 wndPos.x = newWindowRect.left;
1244 wndPos.y = newWindowRect.top;
1245 wndPos.cx = newWindowRect.right - newWindowRect.left;
1246 wndPos.cy = newWindowRect.bottom - newWindowRect.top;
1247 wndPos.flags = SWP_FRAMECHANGED;
1248 lpWndPos = &wndPos;
1249 }
1250
1251 newClientRect = rectClient;
1252 rc = SendNCCalcSize(TRUE, &newWindowRect, &oldWindowRect, &client, lpWndPos, &newClientRect);
1253 rectClient = newClientRect; //must update rectClient here
1254
1255 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));
1256 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));
1257
1258 if(!CanReceiveSizeMsgs() || !EqualRect(&client, &rectClient)) {
1259 OSLibWinSetClientPos(getOS2WindowHandle(), rectClient.left, rectClient.top, getClientWidth(), getClientHeight(), getWindowHeight());
1260 }
1261
1262#if 1
1263//this doesn't always work
1264// if(CanReceiveSizeMsgs() && (client.left != rectClient.left || client.top != rectClient.top))
1265 if(CanReceiveSizeMsgs() && ((oldWindowRect.right - oldWindowRect.left < rectClient.left
1266 || oldWindowRect.bottom - oldWindowRect.top < rectClient.top) ||
1267 (EqualRect(&oldWindowRect, &rectWindow) && (client.left != rectClient.left || client.top != rectClient.top))))
1268 {
1269 Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild();
1270
1271 //client rectangle has moved -> inform children
1272 dprintf(("MsgFormatFrame -> client rectangle has changed, move children"));
1273 while(child) {
1274 ::SetWindowPos(child->getWindowHandle(),
1275 HWND_TOP, child->getWindowRect()->left,
1276 child->getWindowRect()->top, 0, 0,
1277 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
1278 child = (Win32BaseWindow *)child->getNextChild();
1279 }
1280 }
1281#endif
1282 if(fOS2Look && ((dwStyle & WS_CAPTION) == WS_CAPTION))
1283 {
1284 RECT rect = {0};
1285 int height = getWindowHeight();
1286 RECTLOS2 rectOS2;
1287
1288 AdjustRectOuter(&rect, FALSE);
1289
1290 rect.left = -rect.left;
1291 rect.top = rect.bottom - rect.top;
1292 rect.right = rectWindow.right - rectWindow.left - rect.right;
1293
1294 rectOS2.xLeft = rect.left;
1295 rectOS2.xRight = rect.right;
1296 rectOS2.yBottom = height - rect.top;
1297 rectOS2.yTop = height - rect.bottom;
1298 OSLibWinPositionFrameControls(getOS2FrameWindowHandle(), &rectOS2, dwStyle, dwExStyle, IconForWindow(ICON_SMALL));
1299 }
1300 return rc;
1301}
1302//******************************************************************************
1303//******************************************************************************
1304ULONG Win32BaseWindow::MsgSetText(LPSTR lpsz, LONG cch)
1305{
1306 return SendInternalMessageA(WM_SETTEXT, 0, (LPARAM)lpsz);
1307}
1308//******************************************************************************
1309//******************************************************************************
1310ULONG Win32BaseWindow::MsgGetTextLength()
1311{
1312 return SendInternalMessageA(WM_GETTEXTLENGTH, 0, 0);
1313}
1314//******************************************************************************
1315//******************************************************************************
1316void Win32BaseWindow::MsgGetText(char *wndtext, ULONG textlength)
1317{
1318 SendInternalMessageA(WM_GETTEXT, textlength, (LPARAM)wndtext);
1319}
1320//******************************************************************************
1321//******************************************************************************
1322BOOL Win32BaseWindow::isMDIClient()
1323{
1324 return FALSE;
1325}
1326//******************************************************************************
1327//******************************************************************************
1328BOOL Win32BaseWindow::isMDIChild()
1329{
1330 return FALSE;
1331}
1332//******************************************************************************
1333//TODO: Not complete
1334//******************************************************************************
1335BOOL Win32BaseWindow::isFrameWindow()
1336{
1337 if(getParent() == NULL)
1338 return TRUE;
1339
1340 return FALSE;
1341}
1342//******************************************************************************
1343//******************************************************************************
1344BOOL Win32BaseWindow::isDesktopWindow()
1345{
1346 return FALSE;
1347}
1348//******************************************************************************
1349//******************************************************************************
1350BOOL Win32BaseWindow::IsWindowIconic()
1351{
1352 return ((getStyle() & WS_MINIMIZE) && windowClass->getIcon());
1353}
1354//******************************************************************************
1355//******************************************************************************
1356SCROLLBAR_INFO *Win32BaseWindow::getScrollInfo(int nBar)
1357{
1358 switch(nBar)
1359 {
1360 case SB_HORZ:
1361 if (!horzScrollInfo)
1362 {
1363 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1364 if (!horzScrollInfo) break;
1365 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
1366 horzScrollInfo->MaxVal = 100;
1367 horzScrollInfo->flags = ESB_ENABLE_BOTH;
1368 }
1369 return horzScrollInfo;
1370
1371 case SB_VERT:
1372 if (!vertScrollInfo)
1373 {
1374 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1375 if (!vertScrollInfo) break;
1376 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
1377 vertScrollInfo->MaxVal = 100;
1378 vertScrollInfo->flags = ESB_ENABLE_BOTH;
1379 }
1380 return vertScrollInfo;
1381 }
1382
1383 return NULL;
1384}
1385//******************************************************************************
1386//******************************************************************************
1387LRESULT Win32BaseWindow::DefWndControlColor(UINT ctlType, HDC hdc)
1388{
1389 //SvL: Set background color to default button color (not window (white))
1390 if(ctlType == CTLCOLOR_BTN)
1391 {
1392 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1393 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1394 return GetSysColorBrush(COLOR_BTNFACE);
1395 }
1396 //SvL: Set background color to default dialog color if window is dialog
1397 if((ctlType == CTLCOLOR_DLG || ctlType == CTLCOLOR_STATIC) && IsDialog()) {
1398 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1399 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1400 return GetSysColorBrush(COLOR_BTNFACE);
1401 }
1402 if( ctlType == CTLCOLOR_SCROLLBAR)
1403 {
1404 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
1405 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
1406 SetTextColor( hdc, GetSysColor(COLOR_3DFACE));
1407 SetBkColor( hdc, bk);
1408
1409 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
1410 * we better use 0x55aa bitmap brush to make scrollbar's background
1411 * look different from the window background.
1412 */
1413 if (bk == GetSysColor(COLOR_WINDOW)) {
1414 return GetPattern55AABrush();
1415 }
1416
1417 UnrealizeObject( hb );
1418 return (LRESULT)hb;
1419 }
1420
1421 SetTextColor( hdc, GetSysColor(COLOR_WINDOWTEXT));
1422
1423 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
1424 {
1425 SetBkColor( hdc, GetSysColor(COLOR_WINDOW) );
1426 }
1427 else
1428 {
1429 SetBkColor( hdc, GetSysColor(COLOR_3DFACE) );
1430 return (LRESULT)GetSysColorBrush(COLOR_3DFACE);
1431 }
1432 return (LRESULT)GetSysColorBrush(COLOR_WINDOW);
1433}
1434//******************************************************************************
1435//******************************************************************************
1436LRESULT Win32BaseWindow::DefWndPrint(HDC hdc,ULONG uFlags)
1437{
1438 /*
1439 * Visibility flag.
1440 */
1441 if ( (uFlags & PRF_CHECKVISIBLE) &&
1442 !IsWindowVisible(getWindowHandle()) )
1443 return 0;
1444
1445 /*
1446 * Unimplemented flags.
1447 */
1448 if ( (uFlags & PRF_CHILDREN) ||
1449 (uFlags & PRF_OWNED) ||
1450 (uFlags & PRF_NONCLIENT) )
1451 {
1452 dprintf(("WM_PRINT message with unsupported flags\n"));
1453 }
1454
1455 /*
1456 * Background
1457 */
1458 if ( uFlags & PRF_ERASEBKGND)
1459 SendInternalMessageA(WM_ERASEBKGND, (WPARAM)hdc, 0);
1460
1461 /*
1462 * Client area
1463 */
1464 if ( uFlags & PRF_CLIENT)
1465 SendInternalMessageA(WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
1466
1467
1468 return 0;
1469}
1470//******************************************************************************
1471//******************************************************************************
1472LRESULT Win32BaseWindow::DefWindowProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
1473{
1474 switch(Msg)
1475 {
1476 case WM_CLOSE:
1477 dprintf(("DefWindowProcA: WM_CLOSE %x", getWindowHandle()));
1478 DestroyWindow();
1479 return 0;
1480
1481 case WM_GETTEXTLENGTH:
1482 return windowNameLength;
1483
1484 case WM_GETTEXT:
1485 if (!lParam || !wParam)
1486 return 0;
1487 if (!windowNameA)
1488 ((LPSTR)lParam)[0] = 0;
1489 else
1490 memcpy((LPSTR)lParam, windowNameA, min(windowNameLength+1, wParam) );
1491 return min(windowNameLength, wParam);
1492
1493 case WM_SETTEXT:
1494 {
1495 LPCSTR lpsz = (LPCSTR)lParam;
1496
1497 // reallocate if new buffer is larger
1498 if (!lParam)
1499 {
1500 free(windowNameA);
1501 free(windowNameW);
1502 windowNameLength = 0;
1503 windowNameA = NULL;
1504 windowNameW = NULL;
1505 }
1506 else
1507 {
1508 // determine length of new text
1509 int iTextLength = strlen(lpsz);
1510
1511 if (windowNameLength < iTextLength)
1512 {
1513 if (windowNameA)
1514 {
1515 free(windowNameA);
1516 windowNameA = NULL;
1517 }
1518
1519 if (windowNameW)
1520 {
1521 free(windowNameW);
1522 windowNameW = NULL;
1523 }
1524 }
1525
1526 windowNameLength = iTextLength;
1527 if(!windowNameA)
1528 windowNameA = (LPSTR)_smalloc(windowNameLength+1);
1529 memcpy(windowNameA, lpsz, windowNameLength+1);
1530 if(!windowNameW)
1531 windowNameW = (LPWSTR)_smalloc((windowNameLength+1)*sizeof(WCHAR));
1532 lstrcpynAtoW(windowNameW, windowNameA, windowNameLength+1);
1533 }
1534
1535 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, lParam));
1536 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1537 {
1538 HandleNCPaint((HRGN)1);
1539 if(hTaskList) {
1540 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
1541 }
1542 if(fOS2Look) {
1543 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
1544 }
1545 }
1546
1547 return TRUE;
1548 }
1549
1550 case WM_SETREDRAW:
1551 {
1552 if (wParam)
1553 {
1554 setStyle(getStyle() | WS_VISIBLE);
1555 dprintf(("Enable window update for %x", getWindowHandle()));
1556 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, TRUE);
1557 }
1558 else
1559 {
1560 if (getStyle() & WS_VISIBLE)
1561 {
1562 setStyle(getStyle() & ~WS_VISIBLE);
1563 dprintf(("Disable window update for %x", getWindowHandle()));
1564 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, FALSE);
1565 }
1566 }
1567 return 0;
1568 }
1569
1570 case WM_CTLCOLORMSGBOX:
1571 case WM_CTLCOLOREDIT:
1572 case WM_CTLCOLORLISTBOX:
1573 case WM_CTLCOLORBTN:
1574 case WM_CTLCOLORDLG:
1575 case WM_CTLCOLORSTATIC:
1576 case WM_CTLCOLORSCROLLBAR:
1577 return DefWndControlColor(Msg - WM_CTLCOLORMSGBOX, (HDC)wParam);
1578
1579 case WM_CTLCOLOR:
1580 return DefWndControlColor(HIWORD(lParam), (HDC)wParam);
1581
1582 case WM_VKEYTOITEM:
1583 case WM_CHARTOITEM:
1584 return -1;
1585
1586 case WM_PARENTNOTIFY:
1587 return 0;
1588
1589 case WM_MOUSEACTIVATE:
1590 {
1591 dprintf(("DefWndProc: WM_MOUSEACTIVATE for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1592 if(getStyle() & WS_CHILD && !(getExStyle() & WS_EX_NOPARENTNOTIFY) )
1593 {
1594 if(getParent()) {
1595 LRESULT rc = getParent()->SendInternalMessageA(WM_MOUSEACTIVATE, wParam, lParam );
1596 if(rc) return rc;
1597 }
1598 }
1599 return (LOWORD(lParam) == HTCAPTION) ? MA_NOACTIVATE : MA_ACTIVATE;
1600 }
1601
1602 case WM_ACTIVATE:
1603 /* The default action in Windows is to set the keyboard focus to
1604 * the window, if it's being activated and not minimized */
1605 if (LOWORD(wParam) != WA_INACTIVE) {
1606 if(!(getStyle() & WS_MINIMIZE))
1607 SetFocus(getWindowHandle());
1608 }
1609 return 0;
1610
1611 case WM_SETCURSOR:
1612 {
1613 dprintf(("DefWndProc: WM_SETCURSOR for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1614 if((getStyle() & WS_CHILD))
1615 {
1616 if(getParent()) {
1617 LRESULT rc = getParent()->SendInternalMessageA(WM_SETCURSOR, wParam, lParam);
1618 if(rc) return rc;
1619 }
1620 }
1621 if (wParam == getWindowHandle())
1622 {
1623 HCURSOR hCursor;
1624
1625 switch(LOWORD(lParam))
1626 {
1627 case HTCLIENT:
1628 hCursor = windowClass ? windowClass->getCursor():LoadCursorA(0,IDC_ARROWA);
1629 break;
1630
1631 case HTLEFT:
1632 case HTRIGHT:
1633 hCursor = LoadCursorA(0,IDC_SIZEWEA);
1634 break;
1635
1636 case HTTOP:
1637 case HTBOTTOM:
1638 hCursor = LoadCursorA(0,IDC_SIZENSA);
1639 break;
1640
1641 case HTTOPLEFT:
1642 case HTBOTTOMRIGHT:
1643 hCursor = LoadCursorA(0,IDC_SIZENWSEA);
1644 break;
1645
1646 case HTTOPRIGHT:
1647 case HTBOTTOMLEFT:
1648 hCursor = LoadCursorA(0,IDC_SIZENESWA);
1649 break;
1650
1651 default:
1652 hCursor = LoadCursorA(0,IDC_ARROWA);
1653 break;
1654 }
1655
1656 if (hCursor)
1657 {
1658 SetCursor(hCursor);
1659 return 1;
1660 }
1661 else return 0;
1662 }
1663 else return 0;
1664 }
1665
1666 case WM_MOUSEMOVE:
1667 return 0;
1668
1669 case WM_WINDOWPOSCHANGED:
1670 {
1671 PWINDOWPOS wpos = (PWINDOWPOS)lParam;
1672 WPARAM wp = SIZE_RESTORED;
1673
1674 if (!(wpos->flags & SWP_NOMOVE) && !(wpos->flags & SWP_NOCLIENTMOVE))
1675 {
1676 SendInternalMessageA(WM_MOVE, 0, MAKELONG(rectClient.left,rectClient.top));
1677 }
1678 if (!(wpos->flags & SWP_NOSIZE) && !(wpos->flags & SWP_NOCLIENTSIZE))
1679 {
1680 if (dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
1681 else
1682 if (dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
1683
1684 SendInternalMessageA(WM_SIZE, wp, MAKELONG(rectClient.right - rectClient.left,
1685 rectClient.bottom - rectClient.top));
1686 }
1687 return 0;
1688 }
1689 case WM_WINDOWPOSCHANGING:
1690 return HandleWindowPosChanging((WINDOWPOS *)lParam);
1691
1692 case WM_ERASEBKGND:
1693 case WM_ICONERASEBKGND:
1694 {
1695 RECT rect;
1696 int rc;
1697
1698 if (!windowClass || !windowClass->getBackgroundBrush()) return 0;
1699
1700 rc = GetClipBox( (HDC)wParam, &rect );
1701 if ((rc == SIMPLEREGION) || (rc == COMPLEXREGION))
1702 {
1703 HBRUSH hBrush = windowClass->getBackgroundBrush();
1704
1705 if (hBrush <= (HBRUSH)(SYSCOLOR_GetLastColor()+1))
1706 hBrush = GetSysColorBrush(hBrush-1);
1707
1708 FillRect( (HDC)wParam, &rect, hBrush);
1709 }
1710 return 1;
1711 }
1712
1713 case WM_PRINT:
1714 return DefWndPrint(wParam,lParam);
1715
1716 case WM_PAINTICON:
1717 case WM_PAINT:
1718 {
1719 PAINTSTRUCT ps;
1720 HDC hdc = BeginPaint(getWindowHandle(), &ps );
1721 if( hdc )
1722 {
1723 if( (getStyle() & WS_MINIMIZE) && (getWindowClass()->getIcon() || hIcon))
1724 {
1725 int x = (rectWindow.right - rectWindow.left - GetSystemMetrics(SM_CXICON))/2;
1726 int y = (rectWindow.bottom - rectWindow.top - GetSystemMetrics(SM_CYICON))/2;
1727 dprintf(("Painting class icon: vis rect=(%i,%i - %i,%i)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom ));
1728 DrawIcon(hdc, x, y, hIcon ? hIcon:getWindowClass()->getIcon() );
1729 }
1730 EndPaint(getWindowHandle(), &ps );
1731 }
1732 return 0;
1733 }
1734
1735 case WM_GETDLGCODE:
1736 return 0;
1737
1738 case WM_NCPAINT:
1739 return HandleNCPaint((HRGN)wParam);
1740
1741 case WM_NCACTIVATE:
1742 return HandleNCActivate(wParam);
1743
1744 case WM_NCCREATE:
1745 return(TRUE);
1746
1747 case WM_NCDESTROY:
1748 return 0;
1749
1750 case WM_NCCALCSIZE:
1751 return HandleNCCalcSize((BOOL)wParam,(RECT*)lParam);
1752
1753 case WM_NCLBUTTONDOWN:
1754 return HandleNCLButtonDown(wParam,lParam);
1755
1756 case WM_LBUTTONDBLCLK:
1757 case WM_NCLBUTTONDBLCLK:
1758 return HandleNCLButtonDblClk(wParam,lParam);
1759
1760 case WM_NCRBUTTONDOWN:
1761 case WM_NCRBUTTONDBLCLK:
1762 case WM_NCMBUTTONDOWN:
1763 case WM_NCMBUTTONDBLCLK:
1764 if (lastHitTestVal == HTERROR) MessageBeep(MB_ICONEXCLAMATION);
1765 return 0;
1766
1767 case WM_NCRBUTTONUP:
1768 return HandleNCRButtonUp(wParam,lParam);
1769
1770 case WM_NCMBUTTONUP:
1771 return 0;
1772
1773 case WM_NCHITTEST:
1774 {
1775 POINT point;
1776 LRESULT retvalue;
1777
1778 point.x = (SHORT)LOWORD(lParam);
1779 point.y = (SHORT)HIWORD(lParam);
1780
1781 retvalue = HandleNCHitTest(point);
1782#if 0 //CB: let the Corel people fix the bugs first
1783 if(retvalue == HTMENU)
1784 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,TRUE);
1785 else
1786 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,FALSE);
1787#endif
1788 return retvalue;
1789 }
1790
1791 case WM_SYSCOMMAND:
1792 {
1793 POINT point;
1794
1795 point.x = LOWORD(lParam);
1796 point.y = HIWORD(lParam);
1797 return HandleSysCommand(wParam,&point);
1798 }
1799
1800 case WM_SYSKEYDOWN:
1801 {
1802 if( HIWORD(lParam) & KEYDATA_ALT )
1803 {
1804 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1805 if( wParam == VK_MENU && !iMenuSysKey )
1806 iMenuSysKey = 1;
1807 else
1808 iMenuSysKey = 0;
1809
1810 iF10Key = 0;
1811
1812 if( wParam == VK_F4 ) /* try to close the window */
1813 {
1814 HWND top = GetTopParent();
1815 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
1816 PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
1817 }
1818 }
1819 else if( wParam == VK_F10 )
1820 iF10Key = 1;
1821 else
1822 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1823 SendMessageW(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
1824
1825 Win32BaseWindow *siblingWindow;
1826 HWND sibling;
1827 char nameBuffer [40], mnemonic;
1828 int nameLength;
1829
1830 GetWindowTextA (nameBuffer, 40);
1831
1832 // search all sibling to see it this key is their mnemonic
1833 sibling = GetWindow (GW_HWNDFIRST);
1834 while (sibling != 0) {
1835 siblingWindow = GetWindowFromHandle (sibling);
1836 nameLength = siblingWindow->GetWindowTextA (nameBuffer, 40);
1837
1838 // find the siblings mnemonic
1839 mnemonic = '\0';
1840 for (int i=0 ; i<nameLength ; i++) {
1841 if (IsDBCSLeadByte(nameBuffer[i])) {
1842 // Skip DBCS
1843 continue;
1844 }
1845 if (nameBuffer [i] == '&') {
1846 mnemonic = nameBuffer [i+1];
1847 if ((mnemonic >= 'a') && (mnemonic <= 'z'))
1848 mnemonic -= 32; // make it uppercase
1849 break; // stop searching
1850 }
1851 }
1852
1853 // key matches siblings mnemonic, send mouseclick
1854 if (mnemonic == (char) wParam) {
1855 siblingWindow->SendInternalMessageA (BM_CLICK, 0, 0);
1856 }
1857 sibling = siblingWindow->GetNextWindow (GW_HWNDNEXT);
1858 RELEASE_WNDOBJ(siblingWindow);
1859 }
1860
1861 return 0;
1862 }
1863
1864 case WM_KEYUP:
1865 case WM_SYSKEYUP:
1866 /* Press and release F10 or ALT */
1867 if (((wParam == VK_MENU) && iMenuSysKey) ||
1868 ((wParam == VK_F10) && iF10Key))
1869 ::SendMessageW( GetTopWindow(), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1870 iMenuSysKey = iF10Key = 0;
1871 break;
1872
1873 case WM_SYSCHAR:
1874 {
1875 iMenuSysKey = 0;
1876 if (wParam == VK_RETURN && (getStyle() & WS_MINIMIZE))
1877 {
1878 PostMessageA(getWindowHandle(), WM_SYSCOMMAND,
1879 (WPARAM)SC_RESTORE, 0L );
1880 break;
1881 }
1882 if((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1883 {
1884 if (wParam == VK_TAB || wParam == VK_ESCAPE || wParam == VK_F4)
1885 break;
1886 if (wParam == VK_SPACE && (getStyle() & WS_CHILD)) {
1887 ::SendMessageW(GetParent(), Msg, wParam, lParam );
1888 }
1889 else SendMessageA(WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
1890 }
1891#if 0
1892 else /* check for Ctrl-Esc */
1893 if (wParam != VK_ESCAPE) MessageBeep(0);
1894 break;
1895#endif
1896 }
1897
1898 case WM_SETHOTKEY:
1899 hotkey = wParam;
1900 return 1; //CB: always successful
1901
1902 case WM_GETHOTKEY:
1903 return hotkey;
1904
1905 case WM_CONTEXTMENU:
1906 if ((dwStyle & WS_CHILD) && getParent())
1907 getParent()->SendInternalMessageA(WM_CONTEXTMENU,wParam,lParam);
1908 return 0;
1909
1910 case WM_SHOWWINDOW:
1911 if (!lParam) return 0; /* sent from ShowWindow */
1912 if (!(dwStyle & WS_POPUP) || !owner) return 0;
1913 if ((dwStyle & WS_VISIBLE) && wParam) return 0;
1914 else if (!(dwStyle & WS_VISIBLE) && !wParam) return 0;
1915 ShowWindow(wParam ? SW_SHOW:SW_HIDE);
1916 return 0;
1917
1918 case WM_CANCELMODE:
1919 if (getParent() == windowDesktop) EndMenu();
1920 if (GetCapture() == Win32Hwnd) ReleaseCapture();
1921 return 0;
1922
1923 case WM_DROPOBJECT:
1924 return DRAG_FILE;
1925
1926 case WM_QUERYDROPOBJECT:
1927 return (dwExStyle & WS_EX_ACCEPTFILES) ? 1:0;
1928
1929 case WM_QUERYDRAGICON:
1930 {
1931 HICON hDragIcon = windowClass->getCursor();
1932 UINT len;
1933
1934 if(hDragIcon) return (LRESULT)hDragIcon;
1935 for(len = 1; len < 64; len++)
1936 {
1937 hDragIcon = LoadIconA(hInstance,MAKEINTRESOURCEA(len));
1938 if(hDragIcon)
1939 return (LRESULT)hDragIcon;
1940 }
1941 return (LRESULT)LoadIconA(0,IDI_APPLICATIONA);
1942 }
1943
1944 case WM_QUERYOPEN:
1945 case WM_QUERYENDSESSION:
1946 return 1;
1947
1948 case WM_NOTIFYFORMAT:
1949 return IsWindowUnicode() ? NFR_UNICODE:NFR_ANSI;
1950
1951 case WM_SETICON:
1952 case WM_GETICON:
1953 {
1954 LRESULT result = 0;
1955
1956 /* Set the appropriate icon members in the window structure. */
1957 if (wParam == ICON_SMALL)
1958 {
1959 result = hIconSm;
1960 if (Msg == WM_SETICON)
1961 hIconSm = (HICON)lParam;
1962 }
1963 else
1964 {
1965 result = hIcon;
1966 if (Msg == WM_SETICON)
1967 {
1968 hIcon = (HICON)lParam;
1969 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1970 OSLibWinSetIcon(OS2HwndFrame,hIcon);
1971 }
1972 }
1973 if ((Msg == WM_SETICON) && ((dwStyle & WS_CAPTION) == WS_CAPTION))
1974 HandleNCPaint((HRGN)1);
1975
1976 return result;
1977 }
1978
1979 case WM_HELP:
1980 if (getParent()) getParent()->SendInternalMessageA(Msg,wParam,lParam);
1981 break;
1982
1983 case WM_NOTIFY:
1984 return 0; //comctl32 controls expect this
1985
1986 default:
1987 return 0;
1988 }
1989 return 0;
1990}
1991//******************************************************************************
1992//******************************************************************************
1993LRESULT Win32BaseWindow::DefWindowProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
1994{
1995 switch(Msg)
1996 {
1997 case WM_GETTEXTLENGTH:
1998 return windowNameLength;
1999
2000 case WM_GETTEXT:
2001 if (!lParam || !wParam)
2002 return 0;
2003 if (!windowNameW)
2004 ((LPWSTR)lParam)[0] = 0;
2005 else
2006 memcpy((LPSTR)lParam, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), wParam) );
2007 return min(windowNameLength, wParam);
2008
2009 case WM_SETTEXT:
2010 {
2011 LPWSTR lpsz = (LPWSTR)lParam;
2012
2013 // reallocate if new buffer is larger
2014 if (!lParam)
2015 {
2016 free(windowNameA);
2017 free(windowNameW);
2018 windowNameLength = 0;
2019 windowNameA = NULL;
2020 windowNameW = NULL;
2021 }
2022 else
2023 {
2024 // determine length of new text
2025 int iTextLength = lstrlenW(lpsz);
2026
2027 if (windowNameLength < iTextLength)
2028 {
2029 if (windowNameA)
2030 {
2031 free(windowNameA);
2032 windowNameA = NULL;
2033 }
2034
2035 if (windowNameW)
2036 {
2037 free(windowNameW);
2038 windowNameW = NULL;
2039 }
2040 }
2041
2042 windowNameLength = iTextLength;
2043 if(!windowNameW)
2044 windowNameW = (LPWSTR)_smalloc((windowNameLength+1)*sizeof(WCHAR));
2045 memcpy(windowNameW, lpsz, (windowNameLength+1) * sizeof(WCHAR));
2046 if(!windowNameA)
2047 windowNameA = (LPSTR)_smalloc(windowNameLength+1);
2048 lstrcpynWtoA(windowNameA, windowNameW, windowNameLength+1);
2049 }
2050
2051 dprintf(("WM_SETTEXT of %x\n",Win32Hwnd));
2052 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2053 {
2054 HandleNCPaint((HRGN)1);
2055 if(hTaskList) {
2056 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
2057 }
2058 if(fOS2Look) {
2059 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
2060 }
2061 }
2062
2063 return TRUE;
2064 }
2065
2066 default:
2067 return DefWindowProcA(Msg, wParam, lParam);
2068 }
2069}
2070//******************************************************************************
2071//******************************************************************************
2072LRESULT Win32BaseWindow::SendMessageA(ULONG Msg, WPARAM wParam, LPARAM lParam)
2073{
2074 //if the destination window is created by this process & thread, call window proc directly
2075 if(dwProcessId == currentProcessId && dwThreadId == GetCurrentThreadId()) {
2076 return SendInternalMessageA(Msg, wParam, lParam);
2077 }
2078 //otherwise use WinSendMsg to send it to the right process/thread
2079 dprintf(("SendMessages (inter-process) %x %x %x %x", getWindowHandle(), Msg, wParam, lParam));
2080 return OSLibSendMessage(getOS2WindowHandle(), Msg, wParam, lParam, FALSE);
2081}
2082//******************************************************************************
2083//******************************************************************************
2084LRESULT Win32BaseWindow::SendMessageW(ULONG Msg, WPARAM wParam, LPARAM lParam)
2085{
2086 //if the destination window is created by this process & thread, call window proc directly
2087 if(dwProcessId == currentProcessId && dwThreadId == GetCurrentThreadId()) {
2088 return SendInternalMessageW(Msg, wParam, lParam);
2089 }
2090 //otherwise use WinSendMsg to send it to the right process/thread
2091 return OSLibSendMessage(getOS2WindowHandle(), Msg, wParam, lParam, TRUE);
2092}
2093//******************************************************************************
2094//Called as a result of an OS/2 message or called from a class method
2095//******************************************************************************
2096LRESULT Win32BaseWindow::SendInternalMessageA(ULONG Msg, WPARAM wParam, LPARAM lParam)
2097{
2098 LRESULT rc;
2099 HWND hwnd = getWindowHandle();
2100 BOOL fInternalMsgBackup = fInternalMsg;
2101
2102 //if the destination window was created by this process & thread, call window proc directly
2103 if(dwProcessId != currentProcessId || dwThreadId != GetCurrentThreadId()) {
2104 dprintf(("SendMessages (inter-process) %x %x %x %x", getWindowHandle(), Msg, wParam, lParam));
2105 return OSLibSendMessage(getOS2WindowHandle(), Msg, wParam, lParam, FALSE);
2106 }
2107
2108 DebugPrintMessage(getWindowHandle(), Msg, wParam, lParam, FALSE, TRUE);
2109
2110 CallWindowHookProc(WH_CALLWNDPROC, Msg, wParam, lParam, FALSE);
2111
2112 fInternalMsg = TRUE;
2113 switch(Msg)
2114 {
2115 case WM_CREATE:
2116 {
2117 if(CallWindowProcA(win32wndproc, getWindowHandle(), WM_CREATE, 0, lParam) == -1) {
2118 dprintf(("WM_CREATE returned -1\n"));
2119 rc = -1; //don't create window
2120 break;
2121 }
2122 rc = 0;
2123 break;
2124 }
2125 case WM_LBUTTONDOWN:
2126 case WM_MBUTTONDOWN:
2127 case WM_RBUTTONDOWN:
2128 {
2129 if (getParent())
2130 {
2131 POINTS pt = MAKEPOINTS(lParam);
2132 POINT point;
2133
2134 point.x = pt.x;
2135 point.y = pt.y;
2136 MapWindowPoints(getWindowHandle(), getParent()->getWindowHandle(), &point, 1);
2137 NotifyParent(Msg,wParam,MAKELPARAM(point.x,point.y));
2138 }
2139 rc = win32wndproc(getWindowHandle(), Msg, wParam, lParam);
2140 break;
2141 }
2142 case WM_NCHITTEST:
2143 rc = lastHitTestVal = win32wndproc(getWindowHandle(), WM_NCHITTEST, wParam, lParam);
2144 break;
2145
2146 case WM_DESTROY:
2147 rc = win32wndproc(getWindowHandle(), WM_DESTROY, 0, 0);
2148 break;
2149
2150 default:
2151 rc = CallWindowProcA(win32wndproc, getWindowHandle(), Msg, wParam, lParam);
2152 break;
2153 }
2154 if(!::IsWindow(hwnd)) {
2155 //window might have been destroyed by now. (this pointer invalid)
2156 //we must return immediately
2157 //(MS Visual C++ install heap corruption)
2158 //TODO: could happen in several places here!!!!
2159 return rc;
2160 }
2161 fInternalMsg = fInternalMsgBackup;
2162 dprintf2(("SendMessageA %x %x %x %x returned %x", getWindowHandle(), Msg, wParam, lParam, rc));
2163 return rc;
2164}
2165//******************************************************************************
2166//Called as a result of an OS/2 message or called from a class method
2167//******************************************************************************
2168LRESULT Win32BaseWindow::SendInternalMessageW(ULONG Msg, WPARAM wParam, LPARAM lParam)
2169{
2170 LRESULT rc;
2171 HWND hwnd = getWindowHandle();
2172 BOOL fInternalMsgBackup = fInternalMsg;
2173
2174 //if the destination window was created by this process & thread, call window proc directly
2175 if(dwProcessId != currentProcessId || dwThreadId != GetCurrentThreadId()) {
2176 dprintf(("SendMessages (inter-process) %x %x %x %x", getWindowHandle(), Msg, wParam, lParam));
2177 return OSLibSendMessage(getOS2WindowHandle(), Msg, wParam, lParam, FALSE);
2178 }
2179
2180 DebugPrintMessage(getWindowHandle(), Msg, wParam, lParam, TRUE, TRUE);
2181
2182 CallWindowHookProc(WH_CALLWNDPROC, Msg, wParam, lParam, TRUE);
2183
2184 fInternalMsg = TRUE;
2185 switch(Msg)
2186 {
2187 case WM_CREATE:
2188 {
2189 if(CallWindowProcW(win32wndproc, getWindowHandle(), WM_CREATE, 0, lParam) == -1) {
2190 dprintf(("WM_CREATE returned -1\n"));
2191 rc = -1; //don't create window
2192 break;
2193 }
2194 rc = 0;
2195 break;
2196 }
2197 case WM_LBUTTONDOWN:
2198 case WM_MBUTTONDOWN:
2199 case WM_RBUTTONDOWN:
2200 NotifyParent(Msg, wParam, lParam);
2201 rc = win32wndproc(getWindowHandle(), Msg, wParam, lParam);
2202 break;
2203
2204 case WM_NCHITTEST:
2205 rc = lastHitTestVal = win32wndproc(getWindowHandle(), WM_NCHITTEST, wParam, lParam);
2206 break;
2207
2208 case WM_DESTROY:
2209 rc = win32wndproc(getWindowHandle(), WM_DESTROY, 0, 0);
2210 break;
2211 default:
2212 rc = CallWindowProcW(win32wndproc, getWindowHandle(), Msg, wParam, lParam);
2213 break;
2214 }
2215 if(!::IsWindow(hwnd)) {
2216 //window might have been destroyed by now. (this pointer invalid)
2217 //we must return immediately
2218 //(MS Visual C++ install heap corruption)
2219 //TODO: could happen in several places here!!!!
2220 return rc;
2221 }
2222 fInternalMsg = fInternalMsgBackup;
2223 dprintf2(("SendMessageW %x %x %x %x returned %x", getWindowHandle(), Msg, wParam, lParam, rc));
2224 return rc;
2225}
2226//******************************************************************************
2227//******************************************************************************
2228void Win32BaseWindow::CallWindowHookProc(ULONG hooktype, ULONG Msg, WPARAM wParam, LPARAM lParam, BOOL fUnicode)
2229{
2230 CWPSTRUCT cwp;
2231
2232 cwp.lParam = lParam;
2233 cwp.wParam = wParam;
2234 cwp.message = Msg;
2235 cwp.hwnd = getWindowHandle();
2236
2237 switch(hooktype) {
2238 case WH_CALLWNDPROC:
2239 if(fUnicode) {
2240 HOOK_CallHooksW(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
2241 }
2242 else HOOK_CallHooksA(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
2243 break;
2244 }
2245}
2246//******************************************************************************
2247//TODO: Do this more efficiently
2248//******************************************************************************
2249LRESULT Win32BaseWindow::BroadcastMessageA(int type, UINT msg, WPARAM wParam, LPARAM lParam)
2250{
2251 Win32BaseWindow *window;
2252 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
2253
2254 dprintf(("BroadCastMessageA %x %x %x %s", msg, wParam, lParam, (type == BROADCAST_SEND) ? "Send" : "Post"));
2255
2256 for(int i=0;i<MAX_WINDOW_HANDLES;i++) {
2257 window = GetWindowFromHandle(hwnd++);
2258 if(window) {
2259 if ((window->getStyle() & WS_POPUP) || ((window->getStyle() & WS_CAPTION) == WS_CAPTION))
2260 {
2261 if(type == BROADCAST_SEND) {
2262 ::SendMessageA(window->getWindowHandle(), msg, wParam, lParam);
2263 }
2264 else PostMessageA(window->getWindowHandle(), msg, wParam, lParam);
2265 }
2266 RELEASE_WNDOBJ(window);
2267 }
2268 }
2269 return 0;
2270}
2271//******************************************************************************
2272//TODO: Do this more efficiently
2273//******************************************************************************
2274LRESULT Win32BaseWindow::BroadcastMessageW(int type, UINT msg, WPARAM wParam, LPARAM lParam)
2275{
2276 Win32BaseWindow *window;
2277 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
2278
2279 dprintf(("BroadCastMessageW %x %x %x %s", msg, wParam, lParam, (type == BROADCAST_SEND) ? "Send" : "Post"));
2280
2281 for(int i=0;i<MAX_WINDOW_HANDLES;i++) {
2282 window = GetWindowFromHandle(hwnd++);
2283 if(window) {
2284 if ((window->getStyle() & WS_POPUP) || ((window->getStyle() & WS_CAPTION) == WS_CAPTION))
2285 {
2286 if(type == BROADCAST_SEND) {
2287 ::SendMessageW(window->getWindowHandle(), msg, wParam, lParam);
2288 }
2289 else PostMessageW(window->getWindowHandle(), msg, wParam, lParam);
2290 }
2291 RELEASE_WNDOBJ(window);
2292 }
2293 }
2294 return 0;
2295}
2296//******************************************************************************
2297//******************************************************************************
2298void Win32BaseWindow::NotifyParent(UINT Msg, WPARAM wParam, LPARAM lParam)
2299{
2300 Win32BaseWindow *window = this;
2301 Win32BaseWindow *parentwindow;
2302
2303 while(window)
2304 {
2305 if(window->getStyle() & WS_CHILD && !(window->getExStyle() & WS_EX_NOPARENTNOTIFY) )
2306 {
2307 /* Notify the parent window only */
2308 parentwindow = window->getParent();
2309 if(parentwindow) {
2310 parentwindow->SendInternalMessageA(WM_PARENTNOTIFY, MAKEWPARAM(Msg, getWindowId()), lParam );
2311 }
2312 }
2313 else break;
2314
2315 window = parentwindow;
2316 }
2317}
2318//******************************************************************************
2319// Returns the big or small icon for the window, falling back to the
2320// class as windows does.
2321//******************************************************************************
2322HICON Win32BaseWindow::IconForWindow(WPARAM fType)
2323{
2324 HICON hWndIcon;
2325
2326 if (fType == ICON_BIG)
2327 {
2328 if (hIcon)
2329 hWndIcon = hIcon;
2330 else
2331 if (windowClass && windowClass->getIcon())
2332 hWndIcon = windowClass->getIcon();
2333 else
2334 if (!(dwStyle & DS_MODALFRAME))
2335 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR);
2336 else hWndIcon = 0;
2337 }
2338 else
2339 {
2340 if (hIconSm)
2341 hWndIcon = hIconSm;
2342 else
2343 if (hIcon)
2344 hWndIcon = hIcon;
2345 else
2346 if (windowClass && windowClass->getIconSm())
2347 hWndIcon = windowClass->getIconSm();
2348 else
2349 if (windowClass && windowClass->getIcon())
2350 hWndIcon = windowClass->getIcon();
2351 else
2352 if (!(dwStyle & DS_MODALFRAME))
2353 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR);
2354 else hWndIcon = 0;
2355 }
2356
2357 return hWndIcon;
2358}
2359//******************************************************************************
2360//******************************************************************************
2361BOOL Win32BaseWindow::ShowWindow(ULONG nCmdShow)
2362{
2363 ULONG swp = 0;
2364 HWND hWinAfter;
2365 BOOL rc,wasVisible,showFlag;
2366 RECT newPos = {0, 0, 0, 0};
2367
2368 dprintf(("ShowWindow %x %x", getWindowHandle(), nCmdShow));
2369 wasVisible = (getStyle() & WS_VISIBLE) != 0;
2370
2371 dwOldStyle = getStyle();
2372
2373 switch(nCmdShow)
2374 {
2375 case SW_HIDE:
2376 if (!wasVisible) goto END;
2377
2378 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER;
2379 break;
2380
2381 case SW_SHOWMINNOACTIVE:
2382 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2383 /* fall through */
2384 case SW_SHOWMINIMIZED:
2385 swp |= SWP_SHOWWINDOW;
2386 /* fall through */
2387 case SW_MINIMIZE:
2388 swp |= SWP_FRAMECHANGED;
2389 if( !(getStyle() & WS_MINIMIZE) ) {
2390 swp |= MinMaximize(SW_MINIMIZE, &newPos );
2391 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2392 }
2393 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2394 break;
2395
2396 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
2397 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2398 if( !(getStyle() & WS_MAXIMIZE) ) {
2399 swp |= MinMaximize(SW_MAXIMIZE, &newPos );
2400 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2401 }
2402 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2403 break;
2404
2405 case SW_SHOWNA:
2406 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2407 /* fall through */
2408 case SW_SHOW:
2409 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2410
2411 /*
2412 * ShowWindow has a little peculiar behavior that if the
2413 * window is already the topmost window, it will not
2414 * activate it.
2415 */
2416 if (::GetTopWindow((HWND)0)==getWindowHandle() && (wasVisible || GetActiveWindow() == getWindowHandle()))
2417 swp |= SWP_NOACTIVATE;
2418
2419 break;
2420
2421 case SW_SHOWNOACTIVATE:
2422 swp |= SWP_NOZORDER;
2423 if (GetActiveWindow())
2424 swp |= SWP_NOACTIVATE;
2425 /* fall through */
2426 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
2427 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2428 case SW_RESTORE:
2429 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2430
2431 if( getStyle() & (WS_MINIMIZE | WS_MAXIMIZE) ) {
2432 swp |= MinMaximize(SW_RESTORE, &newPos );
2433 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2434 }
2435 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2436 break;
2437 }
2438
2439 showFlag = (nCmdShow != SW_HIDE);
2440 if (showFlag != wasVisible)
2441 {
2442 SendInternalMessageA(WM_SHOWWINDOW, showFlag, 0 );
2443 if (!::IsWindow( getWindowHandle() )) goto END;
2444 }
2445
2446 /* We can't activate a child window */
2447 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_MDICHILD))
2448 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2449
2450 SetWindowPos(HWND_TOP, newPos.left, newPos.top, newPos.right, newPos.bottom, LOWORD(swp));
2451
2452 if(!(swp & SWP_NOACTIVATE)) {
2453 OSLibWinSetActiveWindow(OS2HwndFrame);
2454 }
2455
2456 if (flags & WIN_NEED_SIZE)
2457 {
2458 /* should happen only in CreateWindowEx() */
2459 int wParam = SIZE_RESTORED;
2460
2461 flags &= ~WIN_NEED_SIZE;
2462 if (dwStyle & WS_MAXIMIZE)
2463 wParam = SIZE_MAXIMIZED;
2464 else
2465 if (dwStyle & WS_MINIMIZE)
2466 wParam = SIZE_MINIMIZED;
2467
2468 SendInternalMessageA(WM_SIZE, wParam,
2469 MAKELONG(rectClient.right-rectClient.left,
2470 rectClient.bottom-rectClient.top));
2471 SendInternalMessageA(WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
2472 }
2473//testestest
2474 //temporary workaround for file dialogs with template dialog child
2475 //they don't redraw when switching directories
2476 //For some reason the new child's (syslistview32) update rectangle stays
2477 //empty after its parent is made visible with ShowWindow
2478 //TODO: find real cause
2479 if(!wasVisible) {
2480 InvalidateRect(getWindowHandle(), NULL, TRUE);
2481 }
2482//testestest
2483END:
2484 fMinMaxChange = FALSE;
2485 return wasVisible;
2486}
2487//******************************************************************************
2488//******************************************************************************
2489BOOL Win32BaseWindow::SetWindowPos(HWND hwndInsertAfter, int x, int y, int cx, int cy, UINT fuFlags)
2490{
2491 BOOL rc = FALSE;
2492 Win32BaseWindow *window;
2493 HWND hParent = 0;
2494 RECT oldClientRect = rectClient;
2495
2496 if (fuFlags &
2497 ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
2498 SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
2499 SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
2500 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_DEFERERASE |
2501 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE))
2502 {
2503 dprintf(("ERROR: SetWindowPos; UNKNOWN flag"));
2504 return FALSE;
2505 }
2506
2507 if( fuFlags & (SWP_DEFERERASE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)) {
2508 dprintf(("WARNING: SetWindowPos; unsupported flag"));
2509 }
2510
2511 if(IsWindowDestroyed()) {
2512 //changing the position of a window that's being destroyed can cause crashes in PMMERGE
2513 dprintf(("SetWindowPos; window already destroyed"));
2514 return TRUE;
2515 }
2516
2517#if 0
2518 /* Fix redundant flags */
2519 if(getStyle() & WS_VISIBLE) {
2520 fuFlags &= ~SWP_SHOWWINDOW;
2521 }
2522 else
2523 {
2524 if (!(fuFlags & SWP_SHOWWINDOW))
2525 fuFlags |= SWP_NOREDRAW;
2526 fuFlags &= ~SWP_HIDEWINDOW;
2527 }
2528
2529//// if(cx < 0) cx = 0;
2530//// if(cy < 0) cy = 0;
2531
2532 if((rectWindow.right - rectWindow.left == cx) && (rectWindow.bottom - rectWindow.top == cy)) {
2533 fuFlags |= SWP_NOSIZE; /* Already the right size */
2534 }
2535
2536 if((rectWindow.left == x) && (rectWindow.top == y)) {
2537 fuFlags |= SWP_NOMOVE; /* Already the right position */
2538 }
2539
2540 if(getWindowHandle() == GetActiveWindow()) {
2541 fuFlags |= SWP_NOACTIVATE; /* Already active */
2542 }
2543 else
2544 if((getStyle() & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2545 {
2546 if(!(fuFlags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2547 {
2548 fuFlags &= ~SWP_NOZORDER;
2549 hwndInsertAfter = HWND_TOP;
2550 }
2551 }
2552 /* TODO: Check hwndInsertAfter */
2553
2554#endif
2555
2556 //Note: Solitaire crashes when receiving WM_SIZE messages before WM_CREATE
2557 if(state < STATE_POST_WMNCCREATE)
2558 {//don't change size; modify internal structures only
2559 //TODO: not 100% correct yet (activate)
2560 dprintf2(("state < STATE_POST_WMNCCREATE"));
2561 if(!(fuFlags & SWP_NOZORDER)) {
2562 hwndLinkAfter = hwndInsertAfter;
2563 }
2564 if(!(fuFlags & SWP_NOMOVE)) {
2565 rectWindow.bottom = (rectWindow.bottom - rectWindow.top) + y;
2566 rectWindow.top = y;
2567 rectWindow.right = (rectWindow.right - rectWindow.left) + x;
2568 rectWindow.left = x;
2569 }
2570 if(!(fuFlags & SWP_NOSIZE)) {
2571 rectWindow.bottom = rectWindow.top + cy;
2572 rectWindow.right = rectWindow.left + cx;
2573 }
2574 return TRUE;
2575 }
2576
2577 WINDOWPOS wpos;
2578 SWP swp, swpOld;
2579 wpos.flags = fuFlags;
2580 wpos.cy = cy;
2581 wpos.cx = cx;
2582 wpos.x = x;
2583 wpos.y = y;
2584 wpos.hwndInsertAfter = hwndInsertAfter;
2585 wpos.hwnd = getWindowHandle();
2586
2587 if(~fuFlags & (SWP_NOMOVE | SWP_NOSIZE))
2588 {
2589 if (isChild())
2590 {
2591 if(!getParent()) {
2592 dprintf(("WARNING: Win32BaseWindow::SetWindowPos window %x is child but has no parent!!", getWindowHandle()));
2593 }
2594 }
2595 OSLibWinQueryWindowPos(OS2HwndFrame, &swpOld);
2596 }
2597
2598 if(getParent()) {
2599 OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, getParent()->getClientHeight(),
2600 OS2HwndFrame);
2601 }
2602 else OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, OSLibQueryScreenHeight(), OS2HwndFrame);
2603
2604 if (swp.fl == 0) {
2605 dprintf2(("swp.fl == 0"));
2606 if(fuFlags & SWP_FRAMECHANGED)
2607 {
2608 NotifyFrameChanged(&wpos, &oldClientRect);
2609 }
2610 return TRUE;
2611 }
2612
2613// if ((swp.fl & SWPOS_ZORDER) && (swp.hwndInsertBehind > HWNDOS_BOTTOM))
2614 if ((swp.hwndInsertBehind > HWNDOS_BOTTOM))
2615 {
2616 Win32BaseWindow *wndBehind = Win32BaseWindow::GetWindowFromHandle(swp.hwndInsertBehind);
2617 if(wndBehind) {
2618 swp.hwndInsertBehind = wndBehind->getOS2FrameWindowHandle();
2619 RELEASE_WNDOBJ(wndBehind);
2620 }
2621 else {
2622 dprintf(("ERROR: SetWindowPos: hwndInsertBehind %x invalid!",swp.hwndInsertBehind));
2623 swp.hwndInsertBehind = 0;
2624 }
2625 }
2626 swp.hwnd = OS2HwndFrame;
2627
2628 if(fuFlags & SWP_SHOWWINDOW && !IsWindowVisible(getWindowHandle())) {
2629 setStyle(getStyle() | WS_VISIBLE);
2630 if(hTaskList) {
2631 dprintf(("Adding window %x to tasklist", getWindowHandle()));
2632 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 1);
2633 }
2634 }
2635 else
2636 if((fuFlags & SWP_HIDEWINDOW) && IsWindowVisible(getWindowHandle())) {
2637 setStyle(getStyle() & ~WS_VISIBLE);
2638 if(hTaskList && !(getStyle() & WS_MINIMIZE)) {
2639 dprintf(("Removing window %x from tasklist", getWindowHandle()));
2640 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 0);
2641 }
2642 }
2643 dprintf (("WinSetWindowPos %x %x (%d,%d)(%d,%d) %x", swp.hwnd, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, swp.fl));
2644 rc = OSLibWinSetMultWindowPos(&swp, 1);
2645
2646 if(rc == FALSE)
2647 {
2648 dprintf(("OSLibWinSetMultWindowPos failed! Error %x",OSLibWinGetLastError()));
2649 return 0;
2650 }
2651
2652 if((fuFlags & SWP_FRAMECHANGED) && (fuFlags & (SWP_NOMOVE | SWP_NOSIZE) == (SWP_NOMOVE | SWP_NOSIZE)))
2653 {
2654 NotifyFrameChanged(&wpos, &oldClientRect);
2655 }
2656 return (rc);
2657}
2658//******************************************************************************
2659//Called by ScrollWindowEx (dc.cpp) to notify child window that it has moved
2660//******************************************************************************
2661BOOL Win32BaseWindow::ScrollWindow(int dx, int dy)
2662{
2663 rectWindow.left += dx;
2664 rectWindow.right += dx;
2665 rectWindow.top += dy;
2666 rectWindow.bottom += dy;
2667 SendInternalMessageA(WM_MOVE, 0, MAKELONG(rectClient.left, rectClient.top));
2668 return TRUE;
2669}
2670//******************************************************************************
2671//******************************************************************************
2672void Win32BaseWindow::NotifyFrameChanged(WINDOWPOS *wpos, RECT *oldClientRect)
2673{
2674 HRGN hrgn, hrgnClient;
2675 RECT rect;
2676
2677 MsgFormatFrame(NULL);
2678
2679 if(RECT_WIDTH(rectClient) != RECT_WIDTH(*oldClientRect) ||
2680 RECT_HEIGHT(rectClient) != RECT_HEIGHT(*oldClientRect))
2681 {
2682 wpos->flags &= ~(SWP_NOSIZE|SWP_NOCLIENTSIZE);
2683 wpos->cx = RECT_WIDTH(rectWindow);
2684 wpos->cy = RECT_HEIGHT(rectWindow);
2685 }
2686
2687 if(rectClient.left != oldClientRect->left ||
2688 rectClient.top != oldClientRect->top)
2689 {
2690 wpos->flags &= ~(SWP_NOMOVE|SWP_NOCLIENTMOVE);
2691 wpos->x = rectWindow.left;
2692 wpos->y = rectWindow.top;
2693 }
2694
2695 WINDOWPOS wpOld = *wpos;
2696 if(!(wpos->flags & SWP_NOSENDCHANGING))
2697 SendInternalMessageA(WM_WINDOWPOSCHANGING, 0, (LPARAM)wpos);
2698
2699 if ((wpos->hwndInsertAfter != wpOld.hwndInsertAfter) ||
2700 (wpos->x != wpOld.x) || (wpos->y != wpOld.y) || (wpos->cx != wpOld.cx) || (wpos->cy != wpOld.cy) || (wpos->flags != wpOld.flags))
2701 {
2702 dprintf(("WARNING, NotifyFrameChanged: TODO -> adjust flags!!!!"));
2703 SetWindowPos(wpos->hwndInsertAfter, wpos->x, wpos->y, wpos->cx, wpos->cy, wpos->flags | SWP_NOSENDCHANGING);
2704 }
2705 else SendInternalMessageA(WM_WINDOWPOSCHANGED, 0, (LPARAM)wpos);
2706
2707 //Calculate invalid areas
2708 rect = rectWindow;
2709 OffsetRect(&rect, -rectWindow.left, -rectWindow.top);
2710 hrgn = CreateRectRgnIndirect(&rect);
2711 if (!hrgn) {
2712 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2713 return;
2714 }
2715 rect = rectClient;
2716 hrgnClient = CreateRectRgnIndirect(&rect);
2717 if (!hrgn) {
2718 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2719 return;
2720 }
2721 CombineRgn(hrgn, hrgn, hrgnClient, RGN_DIFF);
2722 DeleteObject(hrgnClient);
2723
2724 if(!EqualRect(oldClientRect, &rectClient)) {
2725 UnionRect(oldClientRect, oldClientRect, &rectClient);
2726 hrgnClient = CreateRectRgnIndirect(oldClientRect);
2727 if (!hrgn) {
2728 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2729 return;
2730 }
2731 CombineRgn(hrgn, hrgn, hrgnClient, RGN_OR);
2732 DeleteObject(hrgnClient);
2733 }
2734 RedrawWindow(getWindowHandle(), NULL, hrgn, RDW_ALLCHILDREN |
2735 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
2736 DeleteObject(hrgn);
2737}
2738//******************************************************************************
2739//TODO: Check how this api really works in NT
2740//******************************************************************************
2741BOOL Win32BaseWindow::SetWindowPlacement(WINDOWPLACEMENT *wndpl)
2742{
2743 dprintf(("SetWindowPlacement %x min (%d,%d)", getWindowHandle(), wndpl->ptMinPosition.x, wndpl->ptMinPosition.y));
2744 dprintf(("SetWindowPlacement %x max (%d,%d)", getWindowHandle(), wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y));
2745 dprintf(("SetWindowPlacement %x norm (%d,%d)(%d,%d)", getWindowHandle(), wndpl->rcNormalPosition.left, wndpl->rcNormalPosition.top, wndpl->rcNormalPosition.right, wndpl->rcNormalPosition.bottom));
2746 windowpos.ptMinPosition = wndpl->ptMinPosition;
2747 windowpos.ptMaxPosition = wndpl->ptMaxPosition;
2748 windowpos.rcNormalPosition = wndpl->rcNormalPosition;
2749
2750 if(getStyle() & WS_MINIMIZE )
2751 {
2752 //TODO: Why can't this be (0,0)?
2753 if(wndpl->flags & WPF_SETMINPOSITION && !(!windowpos.ptMinPosition.x && !windowpos.ptMinPosition.y)) {
2754 SetWindowPos(0, windowpos.ptMinPosition.x, windowpos.ptMinPosition.y,
2755 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2756 }
2757 }
2758 else
2759 if(getStyle() & WS_MAXIMIZE )
2760 {
2761 //TODO: Why can't this be (0,0)?
2762 if(windowpos.ptMaxPosition.x != 0 || windowpos.ptMaxPosition.y != 0 )
2763 SetWindowPos(0, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
2764 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2765 }
2766 else {
2767 SetWindowPos(0, windowpos.rcNormalPosition.left, windowpos.rcNormalPosition.top,
2768 windowpos.rcNormalPosition.right - windowpos.rcNormalPosition.left,
2769 windowpos.rcNormalPosition.bottom - windowpos.rcNormalPosition.top,
2770 SWP_NOZORDER | SWP_NOACTIVATE );
2771 }
2772 ShowWindow(wndpl->showCmd);
2773 if( ::IsWindow(getWindowHandle()) && getStyle() & WS_MINIMIZE )
2774 {
2775 /* SDK: ...valid only the next time... */
2776 if(wndpl->flags & WPF_RESTORETOMAXIMIZED)
2777 setFlags(getFlags() | WIN_RESTORE_MAX);
2778 }
2779 return TRUE;
2780}
2781//******************************************************************************
2782//******************************************************************************
2783BOOL Win32BaseWindow::GetWindowPlacement(LPWINDOWPLACEMENT wndpl)
2784{
2785 wndpl->length = sizeof(*wndpl);
2786 if(getStyle() & WS_MINIMIZE )
2787 wndpl->showCmd = SW_SHOWMINIMIZED;
2788 else wndpl->showCmd = (getStyle() & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
2789
2790 //TODO: Verify if this is correct -> SDK docs claim this flag must always be set to 0
2791 if(getFlags() & WIN_RESTORE_MAX )
2792 wndpl->flags = WPF_RESTORETOMAXIMIZED;
2793 else wndpl->flags = 0;
2794
2795 wndpl->ptMinPosition = windowpos.ptMinPosition;
2796 wndpl->ptMaxPosition = windowpos.ptMaxPosition;
2797 //Must be in parent coordinates (or screen if no parent); verified in NT4, SP6
2798 wndpl->rcNormalPosition = rectWindow;
2799
2800 return TRUE;
2801}
2802//******************************************************************************
2803//Also destroys all the child windows (destroy children first, parent last)
2804//******************************************************************************
2805BOOL Win32BaseWindow::DestroyWindow()
2806{
2807 HWND hwnd = getWindowHandle();
2808
2809 dprintf(("DestroyWindow %x", hwnd));
2810
2811 /* Call hooks */
2812 if(HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, getWindowHandle(), 0L))
2813 {
2814 return FALSE;
2815 }
2816
2817 if(!(getStyle() & WS_CHILD) && getOwner() == NULL)
2818 {
2819 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWDESTROYED, getWindowHandle(), 0L);
2820 /* FIXME: clean up palette - see "Internals" p.352 */
2821 }
2822
2823 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
2824 {
2825 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
2826 {
2827 /* Notify the parent window only */
2828 getParent()->SendMessageA(WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
2829 if(!::IsWindow(hwnd) )
2830 {
2831 return TRUE;
2832 }
2833 }
2834//// else DebugInt3();
2835 }
2836 /* Hide the window */
2837 if(IsWindowVisible(getWindowHandle()))
2838 {
2839 SetWindowPos(0, 0, 0, 0, 0, SWP_HIDEWINDOW |
2840 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2841 if(!::IsWindow(hwnd))
2842 {
2843 return TRUE;
2844 }
2845 }
2846 dprintf(("DestroyWindow %x -> HIDDEN", hwnd));
2847
2848 // check the handle for the last active popup window
2849 Win32BaseWindow* owner = getOwner();
2850 if (NULL != owner)
2851 {
2852 if (owner->getLastActive() == hwnd)
2853 owner->setLastActive( owner->getWindowHandle() );
2854 }
2855
2856 fDestroyWindowCalled = TRUE;
2857 return OSLibWinDestroyWindow(OS2HwndFrame);
2858}
2859//******************************************************************************
2860//******************************************************************************
2861Win32BaseWindow *Win32BaseWindow::getParent()
2862{
2863 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2864 return ((ULONG)wndparent == (ULONG)windowDesktop) ? NULL : wndparent;
2865}
2866//******************************************************************************
2867//Note: does not set last error if no parent (verified in NT4, SP6)
2868//******************************************************************************
2869HWND Win32BaseWindow::GetParent()
2870{
2871 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2872
2873 if(getStyle() & WS_CHILD) {
2874 if(wndparent) {
2875 return wndparent->getWindowHandle();
2876 }
2877 dprintf(("WARNING: GetParent: WS_CHILD but no parent!!"));
2878 DebugInt3();
2879 return 0;
2880 }
2881 else
2882 if(getStyle() & WS_POPUP)
2883 return (getOwner()) ? getOwner()->getWindowHandle() : 0;
2884 else return 0;
2885}
2886//******************************************************************************
2887//******************************************************************************
2888HWND Win32BaseWindow::SetParent(HWND hwndNewParent)
2889{
2890 HWND oldhwnd;
2891 Win32BaseWindow *newparent;
2892 Win32BaseWindow *oldparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2893 BOOL fShow = FALSE;
2894
2895 if(oldparent) {
2896 oldhwnd = oldparent->getWindowHandle();
2897 oldparent->removeChild(this);
2898 }
2899 else oldhwnd = 0;
2900
2901 /* Windows hides the window first, then shows it again
2902 * including the WM_SHOWWINDOW messages and all */
2903 if(IsWindowCreated() && (getStyle() & WS_VISIBLE)) {
2904 ShowWindow(SW_HIDE);
2905 fShow = TRUE;
2906 }
2907 if(oldparent) {
2908 //release parent here (increased refcount during creation)
2909 RELEASE_WNDOBJ(oldparent);
2910 }
2911 newparent = GetWindowFromHandle(hwndNewParent);
2912 if(newparent && !newparent->isDesktopWindow())
2913 {
2914 setParent(newparent);
2915 getParent()->addChild(this);
2916 fParentChange = TRUE;
2917
2918 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
2919 if(!(getStyle() & WS_CHILD))
2920 {
2921 //TODO: Send WM_STYLECHANGED msg?
2922 setStyle(getStyle() | WS_CHILD);
2923 if(getWindowId())
2924 {
2925 DestroyMenu( (HMENU) getWindowId() );
2926 setWindowId(0);
2927 }
2928 }
2929 //SvL: Even though the win32 coordinates might not change, the PM
2930 // coordinates can. We must make sure the control stays at the
2931 // same position (y) relative to the (new) parent.
2932 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
2933 SWP_NOACTIVATE|SWP_NOSIZE);
2934 fParentChange = FALSE;
2935 }
2936 else {
2937 if(newparent) RELEASE_WNDOBJ(newparent);
2938
2939 setParent(windowDesktop);
2940 windowDesktop->addRef();
2941 windowDesktop->addChild(this);
2942 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
2943
2944 //TODO: Send WM_STYLECHANGED msg?
2945 setStyle(getStyle() & ~WS_CHILD);
2946 setWindowId(0);
2947 }
2948 /* SetParent additionally needs to make hwndChild the topmost window
2949 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2950 WM_WINDOWPOSCHANGED notification messages.
2951 */
2952 if(state >= STATE_PRE_WMNCCREATE) {
2953 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
2954 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
2955
2956 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2957 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2958 }
2959 return oldhwnd;
2960}
2961//******************************************************************************
2962//******************************************************************************
2963BOOL Win32BaseWindow::IsChild(HWND hwndParent)
2964{
2965 // PH: Optimizer won't unroll calls to getParent() even
2966 // in release build.
2967 Win32BaseWindow *_parent = getParent();
2968
2969 if(_parent)
2970 {
2971 if(_parent->getWindowHandle() == hwndParent)
2972 return TRUE;
2973
2974 return _parent->IsChild(hwndParent);
2975 }
2976 else
2977 return 0;
2978}
2979//******************************************************************************
2980//******************************************************************************
2981HWND Win32BaseWindow::GetTopWindow()
2982{
2983 HWND hwndTop;
2984 Win32BaseWindow *topwindow;
2985
2986 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
2987 if(!isDesktopWindow())
2988 {
2989 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
2990 //Note: GetTopWindow can't return a window that hasn't processed
2991 // WM_NCCREATE yet (verified in NT4, SP6)
2992 if(topwindow) {
2993 if(topwindow->state >= STATE_POST_WMNCCREATE) {
2994 hwndTop = topwindow->getWindowHandle();
2995 }
2996 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
2997 RELEASE_WNDOBJ(topwindow);
2998 return hwndTop;
2999 }
3000 if(topwindow) RELEASE_WNDOBJ(topwindow);
3001 return 0;
3002 }
3003 while(hwndTop) {
3004 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3005 //Note: GetTopWindow can't return a window that hasn't processed
3006 // WM_NCCREATE yet (verified in NT4, SP6)
3007 if(topwindow) {
3008 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3009 hwndTop = topwindow->getWindowHandle();
3010 }
3011 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3012 RELEASE_WNDOBJ(topwindow);
3013 return hwndTop;
3014 }
3015 if(topwindow) RELEASE_WNDOBJ(topwindow);
3016 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
3017 }
3018
3019 return 0;
3020}
3021//******************************************************************************
3022// Get the top-level parent for a child window.
3023//******************************************************************************
3024HWND Win32BaseWindow::GetTopParent()
3025{
3026 Win32BaseWindow *window = this;
3027 HWND hwndTopParent = 0;
3028
3029 lock();
3030 while(window && (window->getStyle() & WS_CHILD))
3031 {
3032 window = window->getParent();
3033 }
3034 if(window) {
3035 hwndTopParent = window->getWindowHandle();
3036 }
3037 unlock();
3038 return hwndTopParent;
3039}
3040//******************************************************************************
3041//TODO: Should not enumerate children that are created during the enumeration!
3042//******************************************************************************
3043BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
3044{
3045 BOOL rc = TRUE;
3046 HWND hwnd;
3047 Win32BaseWindow *prevchild = 0, *child = 0;
3048
3049 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
3050 lock();
3051 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
3052 {
3053 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
3054 hwnd = child->getWindowHandle();
3055 if(child->IsWindowDestroyed() || child->getOwner()) {
3056 continue; //shouldn't have an owner (Wine)
3057 }
3058 child->addRef();
3059 unlock();
3060 if(lpfn(hwnd, lParam) == FALSE)
3061 {
3062 child->release();
3063 return FALSE;
3064 }
3065 child->release();
3066 lock();
3067 //check if the window still exists
3068 if(!::IsWindow(hwnd))
3069 {
3070 child = prevchild;
3071 if(child == NULL) break;
3072 continue;
3073 }
3074 if(child->getFirstChild() != NULL)
3075 {
3076 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
3077 child->addRef();
3078 unlock();
3079 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
3080 {
3081 child->release();
3082 return FALSE;
3083 }
3084 child->release();
3085 lock();
3086 }
3087 prevchild = child;
3088 }
3089 unlock();
3090 return rc;
3091}
3092//******************************************************************************
3093//Enumerate first-level children only and check thread id
3094//******************************************************************************
3095BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
3096{
3097 Win32BaseWindow *child = 0;
3098 ULONG tid, pid;
3099 BOOL rc;
3100 HWND hwnd;
3101
3102 dprintf(("EnumThreadWindows %x %x %x", dwThreadId, lpfn, lParam));
3103
3104 for (child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3105 {
3106 OSLibWinQueryWindowProcess(child->getOS2WindowHandle(), &pid, &tid);
3107
3108 if(dwThreadId == tid) {
3109 dprintf2(("EnumThreadWindows: Found Window %x", child->getWindowHandle()));
3110 if((rc = lpfn(child->getWindowHandle(), lParam)) == FALSE) {
3111 break;
3112 }
3113 }
3114 }
3115 return TRUE;
3116}
3117//******************************************************************************
3118//Enumerate first-level children only
3119//******************************************************************************
3120BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
3121{
3122 Win32BaseWindow *child = 0;
3123 BOOL rc;
3124 HWND hwnd;
3125
3126 dprintf(("EnumWindows %x %x", lpfn, lParam));
3127
3128 for (child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3129 {
3130 hwnd = child->getWindowHandle();
3131
3132 dprintf2(("EnumWindows: Found Window %x", child->getWindowHandle()));
3133 if((rc = lpfn(child->getWindowHandle(), lParam)) == FALSE) {
3134 break;
3135 }
3136 }
3137 return TRUE;
3138}
3139//******************************************************************************
3140//******************************************************************************
3141HWND Win32BaseWindow::FindWindowById(int id)
3142{
3143 HWND hwnd;
3144
3145 lock();
3146 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3147 {
3148 if (child->getWindowId() == id)
3149 {
3150 hwnd = child->getWindowHandle();
3151 unlock();
3152 return hwnd;
3153 }
3154 }
3155 unlock();
3156 return 0;
3157}
3158//******************************************************************************
3159//TODO:
3160//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3161//the current process owns them.
3162//******************************************************************************
3163HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3164{
3165 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3166 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3167 Win32BaseWindow *firstchild = child;
3168
3169 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3170 if((hwndParent != 0 && !parent) ||
3171 (hwndChildAfter != 0 && !child) ||
3172 (hwndParent == 0 && hwndChildAfter != 0))
3173 {
3174 if(parent) RELEASE_WNDOBJ(parent);
3175 if(firstchild) RELEASE_WNDOBJ(firstchild);
3176 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3177 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3178 return 0;
3179 }
3180 SetLastError(0);
3181 if(hwndParent != 0)
3182 {//if the current process owns the window, just do a quick search
3183 lock(&critsect);
3184 child = (Win32BaseWindow *)parent->getFirstChild();
3185 if(hwndChildAfter != 0)
3186 {
3187 while(child)
3188 {
3189 if(child->getWindowHandle() == hwndChildAfter)
3190 {
3191 child = (Win32BaseWindow *)child->getNextChild();
3192 break;
3193 }
3194 child = (Win32BaseWindow *)child->getNextChild();
3195 }
3196 }
3197 while(child)
3198 {
3199 //According to Wine, the class doesn't need to be specified
3200 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3201 (!lpszWindow || child->hasWindowName(lpszWindow)))
3202 {
3203 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3204 HWND hwndChild = child->getWindowHandle();
3205 unlock(&critsect);
3206 if(parent) RELEASE_WNDOBJ(parent);
3207 if(firstchild) RELEASE_WNDOBJ(firstchild);
3208 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3209 return hwndChild;
3210 }
3211 child = (Win32BaseWindow *)child->getNextChild();
3212 }
3213 unlock(&critsect);
3214 if(parent) RELEASE_WNDOBJ(parent);
3215 if(firstchild) RELEASE_WNDOBJ(firstchild);
3216 }
3217 else {
3218 Win32BaseWindow *wnd;
3219 HWND henum, hwnd;
3220
3221 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3222 hwnd = OSLibWinGetNextWindow(henum);
3223
3224 while(hwnd)
3225 {
3226 wnd = GetWindowFromOS2FrameHandle(hwnd);
3227 if(wnd == NULL) {
3228 hwnd = OSLibWinQueryClientWindow(hwnd);
3229 if(hwnd) wnd = GetWindowFromOS2Handle(hwnd);
3230 }
3231
3232 if(wnd) {
3233 //According to Wine, the class doesn't need to be specified
3234 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3235 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3236 {
3237 OSLibWinEndEnumWindows(henum);
3238 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3239 HWND hwndret = wnd->getWindowHandle();
3240 RELEASE_WNDOBJ(wnd);
3241 return hwndret;
3242 }
3243 RELEASE_WNDOBJ(wnd);
3244 }
3245 hwnd = OSLibWinGetNextWindow(henum);
3246 }
3247 OSLibWinEndEnumWindows(henum);
3248 if(parent) RELEASE_WNDOBJ(parent);
3249 if(firstchild) RELEASE_WNDOBJ(firstchild);
3250 }
3251 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3252 return 0;
3253}
3254//******************************************************************************
3255//******************************************************************************
3256HWND Win32BaseWindow::GetWindow(UINT uCmd)
3257{
3258 HWND hwndRelated = 0;
3259 Win32BaseWindow *window;
3260
3261 switch(uCmd)
3262 {
3263 case GW_HWNDFIRST:
3264 window = (Win32BaseWindow *)getParent();
3265 if(window)
3266 {
3267 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3268 window = GetWindowFromOS2FrameHandle(hwndRelated);
3269 if(window) {
3270 hwndRelated = window->getWindowHandle();
3271 RELEASE_WNDOBJ(window);
3272 }
3273 else hwndRelated = 0;
3274 }
3275 else {
3276 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3277 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3278 }
3279 break;
3280
3281 case GW_HWNDLAST:
3282 window = (Win32BaseWindow *)getParent();
3283 if(window) {
3284 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3285 dprintf(("os2 handle %x", hwndRelated));
3286 window = GetWindowFromOS2FrameHandle(hwndRelated);
3287 if(window) {
3288 hwndRelated = window->getWindowHandle();
3289 RELEASE_WNDOBJ(window);
3290 }
3291 else hwndRelated = 0;
3292 }
3293 else {
3294 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3295 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3296 }
3297 break;
3298
3299 case GW_HWNDNEXT:
3300 if(getParent()) {
3301 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3302 window = GetWindowFromOS2FrameHandle(hwndRelated);
3303 if(window) {
3304 hwndRelated = window->getWindowHandle();
3305 RELEASE_WNDOBJ(window);
3306 }
3307 else hwndRelated = 0;
3308 }
3309 else {
3310 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3311 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3312 }
3313 break;
3314
3315 case GW_HWNDPREV:
3316 if(getParent()) {
3317 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3318 window = GetWindowFromOS2FrameHandle(hwndRelated);
3319 if(window) {
3320 hwndRelated = window->getWindowHandle();
3321 RELEASE_WNDOBJ(window);
3322 }
3323 else hwndRelated = 0;
3324 }
3325 else {
3326 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3327 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3328 }
3329 break;
3330
3331 case GW_OWNER:
3332 {
3333 Win32BaseWindow *owner = getOwner();
3334 if(owner) {
3335 hwndRelated = owner->getWindowHandle();
3336 }
3337 break;
3338 }
3339
3340 case GW_CHILD:
3341 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3342 window = GetWindowFromOS2FrameHandle(hwndRelated);
3343
3344 //Before a window has processed WM_NCCREATE:
3345 //- GetWindow(parent, GW_CHILD) can't return that window handle
3346 //(verified in NT4, SP6)
3347 if(window) {
3348 if(window->state >= STATE_POST_WMNCCREATE) {
3349 hwndRelated = window->getWindowHandle();
3350 RELEASE_WNDOBJ(window);
3351 }
3352 else {
3353 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3354 RELEASE_WNDOBJ(window);
3355 }
3356 }
3357 else hwndRelated = 0;
3358
3359 break;
3360
3361 //for internal use only
3362 case GW_HWNDNEXTCHILD:
3363 lock();
3364 window = (Win32BaseWindow *)getNextChild();
3365 if(window) {
3366 hwndRelated = window->getWindowHandle();
3367 }
3368 else hwndRelated = 0;
3369 unlock();
3370 break;
3371
3372 case GW_HWNDPREVCHILD:
3373 DebugInt3();
3374 break;
3375
3376 case GW_HWNDFIRSTCHILD:
3377 lock();
3378 window = (Win32BaseWindow *)getFirstChild();
3379 if(window) {
3380 hwndRelated = window->getWindowHandle();
3381 }
3382 else hwndRelated = 0;
3383 unlock();
3384 break;
3385
3386 case GW_HWNDLASTCHILD:
3387 lock();
3388 window = (Win32BaseWindow *)getFirstChild();
3389 if(window) {
3390 while (window->getNextChild())
3391 {
3392 window = (Win32BaseWindow *)window->getNextChild();
3393 }
3394 hwndRelated = window->getWindowHandle();
3395 }
3396 else hwndRelated = 0;
3397 unlock();
3398 break;
3399 }
3400end:
3401 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3402 return hwndRelated;
3403}
3404//******************************************************************************
3405//******************************************************************************
3406HWND Win32BaseWindow::SetActiveWindow()
3407{
3408 HWND hwndActive;
3409
3410 dprintf(("SetActiveWindow %x", getWindowHandle()));
3411 if(getStyle() & WS_CHILD) {
3412// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3413 dprintf(("WARNING: Window is a child or disabled"));
3414 return 0;
3415 }
3416
3417 if(GetActiveWindow() == getWindowHandle()) {
3418 dprintf(("Window already active"));
3419 return getWindowHandle();
3420 }
3421 if (HOOK_IsHooked( WH_CBT ))
3422 {
3423 CBTACTIVATESTRUCT cbta;
3424 LRESULT ret;
3425
3426 cbta.fMouse = FALSE;
3427 cbta.hWndActive = GetActiveWindow();
3428 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3429 if(ret)
3430 {
3431 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3432 return cbta.hWndActive;
3433 }
3434 }
3435 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3436
3437// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3438// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3439// }
3440 hwndActive = GetActiveWindow();
3441 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3442}
3443//******************************************************************************
3444//Used to change active status of an mdi window
3445//******************************************************************************
3446BOOL Win32BaseWindow::DeactivateChildWindow()
3447{
3448 /* child windows get a WM_CHILDACTIVATE message */
3449 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3450 {
3451 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3452 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3453 return TRUE;
3454 }
3455 DebugInt3(); //should not be called for non-child window
3456 return FALSE;
3457}
3458//******************************************************************************
3459//WM_ENABLE is sent to hwnd, but not to it's children (as it should be)
3460//******************************************************************************
3461BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3462{
3463 BOOL rc;
3464
3465 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3466 //return true if previous state was disabled, else false (sdk docs)
3467 rc = (getStyle() & WS_DISABLED) != 0;
3468 if(rc && !fEnable) {
3469 SendMessageA(WM_CANCELMODE, 0, 0);
3470 }
3471 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3472 if(fEnable == FALSE) {
3473 //SvL: No need to clear focus as PM already does this
3474 if(getWindowHandle() == GetCapture()) {
3475 ReleaseCapture(); /* A disabled window can't capture the mouse */
3476 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3477 }
3478 }
3479 return rc;
3480}
3481//******************************************************************************
3482//******************************************************************************
3483BOOL Win32BaseWindow::CloseWindow()
3484{
3485 return OSLibWinMinimizeWindow(OS2Hwnd);
3486}
3487//******************************************************************************
3488//TODO: Not be 100% correct; should return active window of current thread
3489// or NULL when there is none -> WinQueryActiveWindow just returns
3490// the current active window
3491//******************************************************************************
3492HWND Win32BaseWindow::GetActiveWindow()
3493{
3494 HWND hwndActive;
3495
3496 hwndActive = OSLibWinQueryActiveWindow();
3497 return OS2ToWin32Handle(hwndActive);
3498}
3499//******************************************************************************
3500//******************************************************************************
3501BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3502{
3503 INT len = GetWindowTextLength(fUnicode);
3504 BOOL res;
3505
3506 if (wndname == NULL)
3507 return (len == 0);
3508
3509 len++;
3510 if (fUnicode)
3511 {
3512 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3513
3514 GetWindowTextW(text,len);
3515 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3516 free(text);
3517 }
3518 else
3519 {
3520 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3521
3522 GetWindowTextA(text,len);
3523 res = (strcmp(text,wndname) == 0);
3524 free(text);
3525 }
3526
3527 return res;
3528}
3529//******************************************************************************
3530//******************************************************************************
3531CHAR *Win32BaseWindow::getWindowNamePtrA()
3532{
3533 INT len = GetWindowTextLength(FALSE);
3534 CHAR *text;
3535
3536 if (len == 0) return NULL;
3537 len++;
3538 text = (CHAR*)malloc(len*sizeof(CHAR));
3539 GetWindowTextA(text,len);
3540
3541 return text;
3542}
3543//******************************************************************************
3544//******************************************************************************
3545WCHAR *Win32BaseWindow::getWindowNamePtrW()
3546{
3547 INT len = GetWindowTextLength(TRUE);
3548 WCHAR *text;
3549
3550 if (len == 0) return NULL;
3551 len++;
3552 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3553 GetWindowTextW(text,len);
3554
3555 return text;
3556}
3557//******************************************************************************
3558//******************************************************************************
3559VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3560{
3561 if (namePtr) free(namePtr);
3562}
3563//******************************************************************************
3564//When using this API for a window that was created by a different process, NT
3565//does NOT send WM_GETTEXTLENGTH.
3566//******************************************************************************
3567int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3568{
3569 //if the destination window is created by this process, send message
3570 if(dwProcessId == currentProcessId) {
3571 if(fUnicode) {
3572 return SendInternalMessageW(WM_GETTEXTLENGTH,0,0);
3573 }
3574 else return SendInternalMessageA(WM_GETTEXTLENGTH,0,0);
3575 }
3576 //else get data directory from window structure
3577 //TODO: must lock window structure.... (TODO)
3578 return windowNameLength;
3579}
3580//******************************************************************************
3581//When using this API for a window that was created by a different process, NT
3582//does NOT send WM_GETTEXT.
3583//******************************************************************************
3584int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3585{
3586 //if the destination window is created by this process, send message
3587 if(dwProcessId == currentProcessId) {
3588 return SendInternalMessageA(WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3589 }
3590
3591 //else get data directory from window structure
3592 if (!lpsz || !cch) return 0;
3593 if (!windowNameA) lpsz[0] = 0;
3594 else memcpy(lpsz, windowNameA, min(windowNameLength + 1, cch) );
3595 return min(windowNameLength, cch);
3596}
3597//******************************************************************************
3598//When using this API for a window that was created by a different process, NT
3599//does NOT send WM_GETTEXT.
3600//******************************************************************************
3601int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3602{
3603 //if the destination window is created by this process, send message
3604 if(dwProcessId == currentProcessId) {
3605 return SendInternalMessageW(WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3606 }
3607 //else get data directory from window structure
3608 if (!lpsz || !cch)
3609 return 0;
3610 if (!windowNameW)
3611 lpsz[0] = 0;
3612 else
3613 memcpy(lpsz, windowNameW, min( sizeof(WCHAR) * (windowNameLength+1), cch));
3614
3615 return min(windowNameLength, cch);
3616}
3617//******************************************************************************
3618//TODO: How does this work when the target window belongs to a different process???
3619//******************************************************************************
3620BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3621{
3622 return SendInternalMessageA(WM_SETTEXT,0,(LPARAM)lpsz);
3623}
3624//******************************************************************************
3625//******************************************************************************
3626BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3627{
3628 return SendInternalMessageW(WM_SETTEXT,0,(LPARAM)lpsz);
3629}
3630//******************************************************************************
3631//******************************************************************************
3632LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3633{
3634 LONG oldval;
3635
3636 switch(index) {
3637 case GWL_EXSTYLE:
3638 {
3639 STYLESTRUCT ss;
3640
3641 if(dwExStyle == value) {
3642 oldval = value;
3643 break;
3644 }
3645 ss.styleOld = dwExStyle;
3646 ss.styleNew = value;
3647 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3648 SendInternalMessageA(WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3649 setExStyle(ss.styleNew);
3650 SendInternalMessageA(WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3651 oldval = ss.styleOld;
3652 break;
3653 }
3654 case GWL_STYLE:
3655 {
3656 STYLESTRUCT ss;
3657
3658 //SvL: TODO: Can you change minimize or maximize status here too?
3659
3660 if(dwStyle == value) {
3661 oldval = value;
3662 break;
3663 }
3664 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3665#ifdef DEBUG
3666// if((value & WS_CHILD) != (dwStyle & WS_CHILD)) {
3667// DebugInt3(); //is this allowed?
3668// }
3669#endif
3670 value &= ~(WS_CHILD);
3671 ss.styleOld = getStyle();
3672 ss.styleNew = value | (ss.styleOld & WS_CHILD);
3673 SendInternalMessageA(WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3674 setStyle(ss.styleNew);
3675 SendInternalMessageA(WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3676 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
3677
3678 //TODO: Might not be correct to use ShowWindow here
3679 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3680 if(ss.styleNew & WS_VISIBLE)
3681 ShowWindow(SW_SHOWNOACTIVATE);
3682 else ShowWindow(SW_HIDE);
3683 }
3684#ifdef DEBUG
3685 PrintWindowStyle(ss.styleNew, 0);
3686#endif
3687 oldval = ss.styleOld;
3688 break;
3689 }
3690 case GWL_WNDPROC:
3691 {
3692 //Note: Type of SetWindowLong determines new window proc type
3693 // UNLESS the new window proc has already been registered
3694 // (use the old type in that case)
3695 // (VERIFIED in NT 4, SP6)
3696 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3697 if(type == WIN_PROC_INVALID) {
3698 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3699 }
3700 oldval = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3701 dprintf(("SetWindowLong GWL_WNDPROC %x old %x new wndproc %x", getWindowHandle(), oldval, value));
3702 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3703 break;
3704 }
3705 case GWL_HINSTANCE:
3706 oldval = hInstance;
3707 hInstance = value;
3708 break;
3709
3710 case GWL_HWNDPARENT:
3711 oldval = SetParent((HWND)value);
3712 break;
3713
3714 case GWL_ID:
3715 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3716 oldval = getWindowId();
3717 setWindowId(value);
3718 break;
3719
3720 case GWL_USERDATA:
3721 oldval = userData;
3722 userData = value;
3723 break;
3724
3725 default:
3726 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3727 {
3728 oldval = *(ULONG *)(userWindowBytes + index);
3729 *(ULONG *)(userWindowBytes + index) = value;
3730 break;
3731 }
3732 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3733 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3734 return 0;
3735 }
3736 //Note: NT4, SP6 does not set the last error to 0
3737 SetLastError(ERROR_SUCCESS);
3738 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3739 return oldval;
3740}
3741//******************************************************************************
3742//******************************************************************************
3743ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3744{
3745 ULONG value;
3746
3747 switch(index) {
3748 case GWL_EXSTYLE:
3749 value = dwExStyle;
3750 break;
3751 case GWL_STYLE:
3752 value = dwStyle;
3753 break;
3754 case GWL_WNDPROC:
3755 value = (LONG)WINPROC_GetProc(win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3756 break;
3757 case GWL_HINSTANCE:
3758 value = hInstance;
3759 break;
3760 case GWL_HWNDPARENT:
3761 value = GetParent();
3762 break;
3763 case GWL_ID:
3764 value = getWindowId();
3765 break;
3766 case GWL_USERDATA:
3767 value = userData;
3768 break;
3769 default:
3770 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3771 {
3772 value = *(ULONG *)(userWindowBytes + index);
3773 break;
3774 }
3775 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3776 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3777 return 0;
3778 }
3779 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3780 //Note: NT4, SP6 does not set the last error to 0
3781 SetLastError(ERROR_SUCCESS);
3782 return value;
3783}
3784//******************************************************************************
3785//******************************************************************************
3786WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3787{
3788 WORD oldval;
3789
3790 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3791 {
3792 oldval = *(WORD *)(userWindowBytes + index);
3793 *(WORD *)(userWindowBytes + index) = value;
3794 //Note: NT4, SP6 does not set the last error to 0
3795 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3796 SetLastError(ERROR_SUCCESS);
3797 return oldval;
3798 }
3799 switch(index)
3800 {
3801 case GWW_HINSTANCE:
3802 oldval = hInstance;
3803 hInstance = value;
3804 break;
3805
3806 case GWW_HWNDPARENT:
3807 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3808 break;
3809
3810 case GWW_ID:
3811 oldval = getWindowId();
3812 setWindowId(value);
3813 break;
3814
3815 default:
3816 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3817 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3818 return 0;
3819 }
3820 //Note: NT4, SP6 does not set the last error to 0
3821 SetLastError(ERROR_SUCCESS);
3822 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3823 return oldval;
3824}
3825//******************************************************************************
3826//******************************************************************************
3827WORD Win32BaseWindow::GetWindowWord(int index)
3828{
3829 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3830 {
3831 //Note: NT4, SP6 does not set the last error to 0
3832 SetLastError(ERROR_SUCCESS);
3833 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
3834 return *(WORD *)(userWindowBytes + index);
3835 }
3836 switch(index)
3837 {
3838 case GWW_ID:
3839 if(HIWORD(getWindowId()))
3840 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
3841 return (WORD)getWindowId();
3842
3843 case GWW_HWNDPARENT:
3844 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
3845 return (WORD) GetParent();
3846
3847 case GWW_HINSTANCE:
3848 if (HIWORD(hInstance))
3849 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
3850 return (WORD)hInstance;
3851 }
3852
3853 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
3854 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3855 return 0;
3856}
3857//******************************************************************************
3858//Locates window in linked list and increases reference count (if found)
3859//Window object must be unreferenced after usage
3860//******************************************************************************
3861Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
3862{
3863 Win32BaseWindow *window;
3864
3865////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
3866//// while browsing
3867//// Not thread safe now!
3868//// lock(&critsect);
3869 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
3870 if(window) {
3871//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
3872 window->addRef();
3873 }
3874//// unlock(&critsect);
3875 return window;
3876 }
3877//// unlock(&critsect);
3878// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
3879 return NULL;
3880}
3881//******************************************************************************
3882//Locates window in linked list and increases reference count (if found)
3883//Window object must be unreferenced after usage
3884//******************************************************************************
3885Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
3886{
3887 DWORD magic;
3888 HWND hwnd;
3889
3890 if(hwndOS2 == OSLIB_HWND_DESKTOP)
3891 {
3892 windowDesktop->addRef();
3893 return windowDesktop;
3894 }
3895
3896 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
3897 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
3898
3899 if(hwnd && CheckMagicDword(magic)) {
3900 return GetWindowFromHandle(hwnd);
3901 }
3902// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
3903 return 0;
3904}
3905//******************************************************************************
3906//Locates window in linked list and increases reference count (if found)
3907//Window object must be unreferenced after usage
3908//******************************************************************************
3909Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
3910{
3911 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
3912}
3913//******************************************************************************
3914//******************************************************************************
3915HWND WIN32API Win32ToOS2Handle(HWND hwnd)
3916{
3917 HWND hwndOS2;
3918
3919 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3920
3921 if(window) {
3922 hwndOS2 = window->getOS2WindowHandle();
3923 RELEASE_WNDOBJ(window);
3924 return hwndOS2;
3925 }
3926// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3927 return hwnd;
3928}
3929//******************************************************************************
3930//******************************************************************************
3931HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
3932{
3933 HWND hwndOS2;
3934
3935 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3936
3937 if(window) {
3938 hwndOS2 = window->getOS2FrameWindowHandle();
3939 RELEASE_WNDOBJ(window);
3940 return hwndOS2;
3941 }
3942// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
3943 return hwnd;
3944}
3945//******************************************************************************
3946//******************************************************************************
3947HWND WIN32API OS2ToWin32Handle(HWND hwnd)
3948{
3949 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
3950 HWND hwndWin32;
3951
3952 if(window) {
3953 hwndWin32 = window->getWindowHandle();
3954 RELEASE_WNDOBJ(window);
3955 return hwndWin32;
3956 }
3957 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
3958 if(window) {
3959 hwndWin32 = window->getWindowHandle();
3960 RELEASE_WNDOBJ(window);
3961 return hwndWin32;
3962 }
3963
3964// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
3965 return 0;
3966// else return hwnd; //OS/2 window handle
3967}
3968#ifdef DEBUG
3969LONG Win32BaseWindow::addRef()
3970{
3971 dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
3972 return GenericObject::addRef();
3973}
3974//******************************************************************************
3975//******************************************************************************
3976LONG Win32BaseWindow::release(char *function, int line)
3977{
3978 dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
3979 return GenericObject::release();
3980}
3981#endif
3982//******************************************************************************
3983//******************************************************************************
3984GenericObject *Win32BaseWindow::windows = NULL;
3985CRITICAL_SECTION Win32BaseWindow::critsect = {0};
3986
3987//******************************************************************************
3988//******************************************************************************
3989#ifdef DEBUG
3990void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
3991{
3992 char style[256] = "";
3993 char exstyle[256] = "";
3994
3995 /* Window styles */
3996 if(dwStyle & WS_CHILD)
3997 strcat(style, "WS_CHILD ");
3998 if(dwStyle & WS_POPUP)
3999 strcat(style, "WS_POPUP ");
4000 if(dwStyle & WS_VISIBLE)
4001 strcat(style, "WS_VISIBLE ");
4002 if(dwStyle & WS_DISABLED)
4003 strcat(style, "WS_DISABLED ");
4004 if(dwStyle & WS_CLIPSIBLINGS)
4005 strcat(style, "WS_CLIPSIBLINGS ");
4006 if(dwStyle & WS_CLIPCHILDREN)
4007 strcat(style, "WS_CLIPCHILDREN ");
4008 if(dwStyle & WS_MAXIMIZE)
4009 strcat(style, "WS_MAXIMIZE ");
4010 if(dwStyle & WS_MINIMIZE)
4011 strcat(style, "WS_MINIMIZE ");
4012 if(dwStyle & WS_GROUP)
4013 strcat(style, "WS_GROUP ");
4014 if(dwStyle & WS_TABSTOP)
4015 strcat(style, "WS_TABSTOP ");
4016
4017 if((dwStyle & WS_CAPTION) == WS_CAPTION)
4018 strcat(style, "WS_CAPTION ");
4019 if(dwStyle & WS_DLGFRAME)
4020 strcat(style, "WS_DLGFRAME ");
4021 if(dwStyle & WS_BORDER)
4022 strcat(style, "WS_BORDER ");
4023
4024 if(dwStyle & WS_VSCROLL)
4025 strcat(style, "WS_VSCROLL ");
4026 if(dwStyle & WS_HSCROLL)
4027 strcat(style, "WS_HSCROLL ");
4028 if(dwStyle & WS_SYSMENU)
4029 strcat(style, "WS_SYSMENU ");
4030 if(dwStyle & WS_THICKFRAME)
4031 strcat(style, "WS_THICKFRAME ");
4032 if(dwStyle & WS_MINIMIZEBOX)
4033 strcat(style, "WS_MINIMIZEBOX ");
4034 if(dwStyle & WS_MAXIMIZEBOX)
4035 strcat(style, "WS_MAXIMIZEBOX ");
4036
4037 if(dwExStyle & WS_EX_DLGMODALFRAME)
4038 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
4039 if(dwExStyle & WS_EX_ACCEPTFILES)
4040 strcat(exstyle, "WS_EX_ACCEPTFILES ");
4041 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
4042 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
4043 if(dwExStyle & WS_EX_TOPMOST)
4044 strcat(exstyle, "WS_EX_TOPMOST ");
4045 if(dwExStyle & WS_EX_TRANSPARENT)
4046 strcat(exstyle, "WS_EX_TRANSPARENT ");
4047
4048 if(dwExStyle & WS_EX_MDICHILD)
4049 strcat(exstyle, "WS_EX_MDICHILD ");
4050 if(dwExStyle & WS_EX_TOOLWINDOW)
4051 strcat(exstyle, "WS_EX_TOOLWINDOW ");
4052 if(dwExStyle & WS_EX_WINDOWEDGE)
4053 strcat(exstyle, "WS_EX_WINDOWEDGE ");
4054 if(dwExStyle & WS_EX_CLIENTEDGE)
4055 strcat(exstyle, "WS_EX_CLIENTEDGE ");
4056 if(dwExStyle & WS_EX_CONTEXTHELP)
4057 strcat(exstyle, "WS_EX_CONTEXTHELP ");
4058 if(dwExStyle & WS_EX_RIGHT)
4059 strcat(exstyle, "WS_EX_RIGHT ");
4060 if(dwExStyle & WS_EX_LEFT)
4061 strcat(exstyle, "WS_EX_LEFT ");
4062 if(dwExStyle & WS_EX_RTLREADING)
4063 strcat(exstyle, "WS_EX_RTLREADING ");
4064 if(dwExStyle & WS_EX_LTRREADING)
4065 strcat(exstyle, "WS_EX_LTRREADING ");
4066 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
4067 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
4068 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
4069 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
4070 if(dwExStyle & WS_EX_CONTROLPARENT)
4071 strcat(exstyle, "WS_EX_CONTROLPARENT ");
4072 if(dwExStyle & WS_EX_STATICEDGE)
4073 strcat(exstyle, "WS_EX_STATICEDGE ");
4074 if(dwExStyle & WS_EX_APPWINDOW)
4075 strcat(exstyle, "WS_EX_APPWINDOW ");
4076
4077 dprintf(("Window style: %x %s", dwStyle, style));
4078 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
4079}
4080#endif
4081//******************************************************************************
4082//******************************************************************************
Note: See TracBrowser for help on using the repository browser.