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

Last change on this file since 4485 was 4485, checked in by sandervl, 25 years ago

sendmessage + sc_close fixes

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