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

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

focus/activation fixes

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