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

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

SetParent bugfix

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