source: trunk/src/user32/win32wmdichild.cpp@ 5959

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

reference count (window + class objects) rewrite

File size: 16.9 KB
Line 
1/* $Id: win32wmdichild.cpp,v 1.26 2001-06-09 14:50:23 sandervl Exp $ */
2/*
3 * Win32 MDI Child Window Class for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 * Based on Wine (windows\mdi.c) (990815)
8 *
9 * Copyright 1994, Bob Amstadt
10 * 1995,1996 Alex Korobka
11 * Copyright 1993, 1994 Alexandre Julliard
12 *
13 *
14 *
15 * TODO: See #if 0's
16 *
17 * Project Odin Software License can be found in LICENSE.TXT
18 *
19 */
20#include <os2win.h>
21#include <win.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <stdarg.h>
26#include <assert.h>
27#include <misc.h>
28#include <heapstring.h>
29#include <win32wnd.h>
30#include <win32wmdiclient.h>
31#include <win32wmdichild.h>
32#include <spy.h>
33#include "wndmsg.h"
34#include <oslibwin.h>
35#include <oslibutil.h>
36#include <oslibgdi.h>
37#include <oslibres.h>
38#include "oslibdos.h"
39#include "syscolor.h"
40#include "win32wndhandle.h"
41
42#define DBG_LOCALLOG DBG_win32wmdichild
43#include "dbglocal.h"
44
45//******************************************************************************
46//******************************************************************************
47Win32MDIChildWindow::Win32MDIChildWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL fUnicode)
48 : Win32BaseWindow()
49{
50 isUnicode = fUnicode;
51 CreateWindowExA(lpCreateStructA, classAtom);
52}
53//******************************************************************************
54//******************************************************************************
55Win32MDIChildWindow::~Win32MDIChildWindow()
56{
57}
58//******************************************************************************
59//******************************************************************************
60BOOL Win32MDIChildWindow::isMDIChild()
61{
62 return TRUE;
63}
64//******************************************************************************
65//******************************************************************************
66LRESULT Win32MDIChildWindow::DefMDIChildProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
67{
68 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
69
70 switch (Msg)
71 {
72 case WM_SETTEXT:
73 DefWindowProcA(Msg, wParam, lParam);
74 menuModifyItem();
75 if( client->getMaximizedChild() == getWindowHandle() )
76 client->updateFrameText(MDI_REPAINTFRAME, NULL);
77 return 0;
78
79 case WM_GETMINMAXINFO:
80 {
81 childGetMinMaxInfo((MINMAXINFO *)lParam);
82 return 0;
83 }
84
85 case WM_MENUCHAR:
86 /* MDI children don't have menu bars */
87 PostMessageA(client->getWindowHandle(), WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
88 return 0x00010000L;
89
90 case WM_CLOSE:
91 client->SendMessageA(WM_MDIDESTROY,(WPARAM)getWindowHandle(), 0L);
92 return 0;
93
94 case WM_SETFOCUS:
95 if(client->getActiveChild() != getWindowHandle() )
96 client->childActivate(this);
97 break;
98
99 case WM_CHILDACTIVATE:
100 client->childActivate(this);
101 return 0;
102
103 case WM_NCPAINT:
104 break;
105
106 case WM_SYSCOMMAND:
107 switch( wParam )
108 {
109 case SC_MOVE:
110 if( client->getMaximizedChild() == getWindowHandle())
111 {
112 return 0;
113 }
114 break;
115 case SC_RESTORE:
116 case SC_MINIMIZE:
117 setStyle(getStyle() | WS_SYSMENU);
118 break;
119
120 case SC_MAXIMIZE:
121 if( client->getMaximizedChild() == getWindowHandle())
122 {
123 return client->SendMessageA(Msg, wParam, lParam);
124 }
125 setStyle(getStyle() & ~WS_SYSMENU);
126 break;
127
128 case SC_NEXTWINDOW:
129 client->SendMessageA(WM_MDINEXT, 0, 0);
130 return 0;
131
132 case SC_PREVWINDOW: //WM_MDINEXT??
133 client->SendMessageA(WM_MDINEXT, 0, 0);
134 return 0;
135 }
136 break;
137
138 case WM_SETVISIBLE:
139 if( client->getMaximizedChild()) {
140 client->setMdiFlags(client->getMdiFlags() & ~MDIF_NEEDUPDATE);
141 }
142 else client->postUpdate(SB_BOTH+1);
143 break;
144
145 case WM_SIZE:
146 /* do not change */
147 if( client->getActiveChild() == getWindowHandle() && wParam != SIZE_MAXIMIZED )
148 {
149 client->setMaximizedChild(NULL);
150 client->restoreFrameMenu(getWindowHandle());
151 client->updateFrameText(MDI_REPAINTFRAME, NULL );
152 }
153
154 if( wParam == SIZE_MAXIMIZED )
155 {
156 HWND maxChild = client->getMaximizedChild();
157
158 if( maxChild == getWindowHandle() ) break;
159
160 if( maxChild)
161 {
162 ::SendMessageA(maxChild, WM_SETREDRAW, FALSE, 0L );
163 client->restoreFrameMenu(maxChild);
164 ::ShowWindow(maxChild, SW_SHOWNOACTIVATE);
165
166 ::SendMessageA(maxChild, WM_SETREDRAW, TRUE, 0L );
167 }
168
169 client->setMaximizedChild(getWindowHandle());
170 client->setActiveChild(getWindowHandle());
171
172 client->augmentFrameMenu(getWindowHandle());
173
174 client->updateFrameText(MDI_REPAINTFRAME, NULL );
175 }
176
177 if( wParam == SIZE_MINIMIZED )
178 {
179 Win32MDIChildWindow *switchTo = client->getWindow(this, TRUE, WS_MINIMIZE);
180
181 if( switchTo )
182 switchTo->SendMessageA(WM_CHILDACTIVATE, 0, 0L);
183 }
184
185 client->postUpdate(SB_BOTH+1);
186 break;
187
188#if 0
189 case WM_NEXTMENU:
190 if( wParam == VK_LEFT ) /* switch to frame system menu */
191 {
192 return MAKELONG( GetSubMenu(clientWnd->parent->hSysMenu, 0),
193 clientWnd->parent->hwndSelf );
194 goto END;
195 }
196 if( wParam == VK_RIGHT ) /* to frame menu bar */
197 {
198 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
199 clientWnd->parent->hwndSelf );
200 goto END;
201 }
202#endif
203 case WM_SYSCHAR:
204 if (wParam == '-')
205 {
206 SendInternalMessageA(WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
207 return 0;
208 }
209 }
210 return DefWindowProcA(Msg, wParam, lParam);
211}
212//******************************************************************************
213//******************************************************************************
214LRESULT Win32MDIChildWindow::DefMDIChildProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
215{
216 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
217
218 switch (Msg)
219 {
220 case WM_SETTEXT:
221 DefWindowProcW(Msg, wParam, lParam);
222 menuModifyItem();
223 if( client->getMaximizedChild() == getWindowHandle() )
224 client->updateFrameText(MDI_REPAINTFRAME, NULL );
225
226 return 0;
227
228 case WM_GETMINMAXINFO:
229 case WM_MENUCHAR:
230 case WM_CLOSE:
231 case WM_SETFOCUS:
232 case WM_CHILDACTIVATE:
233 case WM_NCPAINT:
234 case WM_SYSCOMMAND:
235 case WM_SETVISIBLE:
236 case WM_SIZE:
237 case WM_NEXTMENU:
238 return DefMDIChildProcA(Msg, wParam, lParam );
239
240 case WM_SYSCHAR:
241 if (wParam == '-')
242 {
243 SendInternalMessageW(WM_SYSCOMMAND, SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
244 return 0;
245 }
246 break;
247 }
248 return DefWindowProcW(Msg, wParam, lParam);
249}
250/**********************************************************************
251 * MDICreateChild
252 */
253HWND Win32MDIChildWindow::createChild(Win32MDIClientWindow *client, LPMDICREATESTRUCTA cs )
254{
255 POINT pos[2];
256 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
257 WORD wIDmenu = client->getFirstChildId() + client->getNrOfChildren();
258 char lpstrDef[]="junk!";
259 Win32MDIChildWindow *newchild;
260 HWND maximizedChild;
261 CREATESTRUCTA createstruct;
262 ATOM classAtom;
263 char tmpClassA[20] = "";
264 WCHAR tmpClassW[20];
265 LPSTR className;
266
267 dprintf(("Win32MDIChildWindow::createChild %i,%i - dim %i,%i, style %08x\n",
268 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style));
269
270 /* calculate placement */
271 calcDefaultChildPos(client, client->incTotalCreated()-1, pos, 0);
272
273 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
274 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
275
276 if( cs->x == CW_USEDEFAULT )
277 {
278 cs->x = pos[0].x;
279 cs->y = pos[0].y;
280 }
281
282 /* restore current maximized child */
283 if( style & WS_VISIBLE && client->getMaximizedChild() )
284 {
285 if( style & WS_MAXIMIZE )
286 client->SendMessageA(WM_SETREDRAW, FALSE, 0L );
287
288 maximizedChild = client->getMaximizedChild();
289
290 ::ShowWindow(maximizedChild, SW_SHOWNOACTIVATE );
291
292 if( style & WS_MAXIMIZE )
293 client->SendMessageA(WM_SETREDRAW, TRUE, 0L );
294 }
295
296 /* this menu is needed to set a check mark in MDI_ChildActivate */
297 if(client->getMDIMenu())
298 AppendMenuA(client->getMDIMenu(), MF_STRING ,wIDmenu, lpstrDef );
299
300 client->incNrActiveChildren();
301
302 /* fix window style */
303 if( !(client->getStyle() & MDIS_ALLCHILDSTYLES) )
304 {
305 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
306 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
307 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
308 }
309
310 createstruct.lpszName = cs->szTitle;
311 createstruct.style = style;
312 createstruct.dwExStyle = 0;
313 createstruct.x = cs->x;
314 createstruct.y = cs->y;
315 createstruct.cx = cs->cx;
316 createstruct.cy = cs->cy;
317 createstruct.hInstance = cs->hOwner;
318 createstruct.hMenu = wIDmenu;
319 createstruct.hwndParent= client->getWindowHandle();
320 createstruct.lpCreateParams = (LPVOID)cs;
321
322 className = (LPSTR)cs->szClass;
323 /* Find the class atom */
324 classAtom = GlobalFindAtomA(cs->szClass);
325 if(classAtom == 0)
326 {
327 if (!HIWORD(cs->szClass))
328 {
329 sprintf(tmpClassA,"#%d", (int) className);
330 classAtom = GlobalFindAtomA(tmpClassA);
331 className = tmpClassA;
332 }
333 if (!classAtom)
334 {
335 if (!HIWORD(cs->szClass)) {
336 dprintf(("createChild: bad class name %04x\n", LOWORD(className)));
337 }
338 else dprintf(("createChild: bad class name '%s'\n", tmpClassA ));
339
340 SetLastError(ERROR_INVALID_PARAMETER);
341 return 0;
342 }
343 }
344 createstruct.lpszClass = className;
345
346 newchild = new Win32MDIChildWindow(&createstruct, classAtom, FALSE);
347
348 if(newchild && GetLastError() == 0)
349 {
350 /* All MDI child windows have the WS_EX_MDICHILD style */
351 newchild->setExStyle(newchild->getExStyle() | WS_EX_MDICHILD);
352
353 newchild->menuModifyItem();
354
355 if( newchild->getStyle() & WS_MINIMIZE && client->getActiveChild()) {
356 newchild->ShowWindow(SW_SHOWMINNOACTIVE);
357 }
358 else
359 {
360 /* WS_VISIBLE is clear if a) the MDI client has
361 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
362 * MDICreateStruct. If so the created window is not shown nor
363 * activated.
364 */
365 int showflag = newchild->getStyle() & WS_VISIBLE;
366 /* clear visible flag, otherwise SetWindoPos32 ignores
367 * the SWP_SHOWWINDOW command.
368 */
369 newchild->setStyle(newchild->getStyle() & ~WS_VISIBLE);
370
371 if(showflag){
372 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
373 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
374 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
375
376 /* Set maximized state here in case hwnd didn't receive WM_SIZE
377 * during CreateWindow - bad!
378 */
379
380 if((newchild->getStyle() & WS_MAXIMIZE) && !client->getMaximizedChild() )
381 {
382 client->setMaximizedChild(newchild->getWindowHandle());
383
384 client->augmentFrameMenu(newchild->getWindowHandle());
385
386 client->updateFrameText(MDI_REPAINTFRAME, NULL );
387 }
388 }
389 else
390 /* needed, harmless ? */
391 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
392
393 }
394 }
395 else
396 {
397 client->decNrActiveChildren();
398 if(client->getMDIMenu()) {
399 DeleteMenu(client->getMDIMenu(), wIDmenu,MF_BYCOMMAND);
400 }
401
402 maximizedChild = client->getMaximizedChild();
403 if( ::IsWindow(maximizedChild) )
404 ::ShowWindow(maximizedChild, SW_SHOWMAXIMIZED);
405
406 dprintf(("MDI child creation failed!!"));
407 return 0;
408 }
409 return newchild->getWindowHandle();
410}
411/**********************************************************************
412 * MDI_MenuModifyItem
413 */
414BOOL Win32MDIChildWindow::menuModifyItem()
415{
416 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
417 char buffer[128];
418 UINT id = getWindowId()-client->getFirstChildId()+1;
419 UINT n = sprintf(buffer,(id > 9) ? "%d":"&%d ",id);
420 BOOL bRet = 0;
421
422 if( !client->getMDIMenu() )
423 {
424 return FALSE;
425 }
426
427 if (getWindowNameA()) lstrcpynA(buffer + n, getWindowNameA(), sizeof(buffer) - n );
428
429 n = GetMenuState(client->getMDIMenu(), getWindowId() ,MF_BYCOMMAND);
430 bRet = ModifyMenuA(client->getMDIMenu() , getWindowId(),
431 MF_BYCOMMAND | MF_STRING, getWindowId(), buffer );
432 CheckMenuItem(client->getMDIMenu(), getWindowId() , n & MF_CHECKED);
433
434 return bRet;
435}
436
437/**********************************************************************
438 * MDI_MenuDeleteItem
439 */
440BOOL Win32MDIChildWindow::menuDeleteItem()
441{
442 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
443 char buffer[128];
444 UINT index = 0,id,n;
445 BOOL retvalue;
446
447 if( !client->getNrOfChildren() ||
448 !client->getMDIMenu())
449 {
450 return FALSE;
451 }
452
453 id = getWindowId();
454 DeleteMenu(client->getMDIMenu(),id,MF_BYCOMMAND);
455
456 /* walk the rest of MDI children to prevent gaps in the id
457 * sequence and in the menu child list */
458
459 lock();
460 for( index = id+1; index <= client->getNrOfChildren() +
461 client->getFirstChildId(); index++ )
462 {
463 Win32MDIChildWindow *tmpWnd = (Win32MDIChildWindow *)GetWindowFromHandle(client->getChildByID(index));
464 if( !tmpWnd )
465 {
466 dprintf(("no window for id=%i\n",index));
467 continue;
468 }
469
470 /* set correct id */
471 tmpWnd->setWindowId(tmpWnd->getWindowId()-1);
472
473 n = sprintf(buffer, "%d ",index - client->getFirstChildId());
474 if (tmpWnd->getWindowNameA())
475 lstrcpynA(buffer + n, tmpWnd->getWindowNameA(), sizeof(buffer) - n );
476
477 RELEASE_WNDOBJ(tmpWnd);
478
479 unlock();
480 /* change menu */
481 ModifyMenuA(client->getMDIMenu(), index ,MF_BYCOMMAND | MF_STRING,
482 index - 1 , buffer );
483 lock();
484 }
485 unlock();
486 return TRUE;
487}
488/**********************************************************************
489 * MDI_CalcDefaultChildPos
490 *
491 * It seems that the default height is about 2/3 of the client rect
492 */
493void Win32MDIChildWindow::calcDefaultChildPos(Win32MDIClientWindow *client, WORD n, LPPOINT lpPos, INT delta)
494{
495 INT nstagger;
496 RECT rect;
497 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
498 GetSystemMetrics(SM_CYFRAME) - 1;
499
500 client->getClientRect(&rect);
501 if( rect.bottom - rect.top - delta >= spacing )
502 rect.bottom -= delta;
503
504 nstagger = (rect.bottom - rect.top)/(3 * spacing);
505 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
506 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
507 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
508}
509
510/**********************************************************************
511 * MDI_ChildGetMinMaxInfo
512 *
513 * Note: The rule here is that client rect of the maximized MDI child
514 * is equal to the client rect of the MDI client window.
515 */
516void Win32MDIChildWindow::childGetMinMaxInfo(MINMAXINFO* lpMinMax )
517{
518 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
519 RECT rect;
520
521 if(client == NULL) {
522 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client == NULL!!"));
523 return;
524 }
525
526 client->getClientRect(&rect);
527 if(client->getParent() == NULL) {
528 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client parent == NULL!!"));
529 return;
530 }
531 //SvL: No mapping required as our client rectangle is in frame coordinates (not relative to parent!)
532///// MapWindowPoints(client->getParent()->getWindowHandle(), client->getWindowHandle(), (LPPOINT)&rect, 2);
533
534 AdjustWindowRectEx( &rect, getStyle(), 0, getExStyle());
535
536 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
537 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
538
539 lpMinMax->ptMaxPosition.x = rect.left;
540 lpMinMax->ptMaxPosition.y = rect.top;
541}
542
543//******************************************************************************
544//******************************************************************************
545
Note: See TracBrowser for help on using the repository browser.