source: trunk/src/user32/new/win32wmdichild.cpp@ 760

Last change on this file since 760 was 760, checked in by sandervl, 26 years ago

MDI + menu changes

File size: 14.5 KB
Line 
1/* $Id: win32wmdichild.cpp,v 1.2 1999-08-31 17:14:51 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 *
12 *
13 * TODO: See #if 0's
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 */
18#include <os2win.h>
19#include <win.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <stdarg.h>
24#include <assert.h>
25#include <misc.h>
26#include <heapstring.h>
27#include <win32wnd.h>
28#include <win32wmdiclient.h>
29#include <win32wmdichild.h>
30#include <spy.h>
31#include "wndmsg.h"
32#include "hooks.h"
33#include <oslibwin.h>
34#include <oslibutil.h>
35#include <oslibgdi.h>
36#include <oslibres.h>
37#include "oslibdos.h"
38#include <winres.h>
39#include "syscolor.h"
40#include "win32wndhandle.h"
41#include "heapshared.h"
42
43
44//******************************************************************************
45//******************************************************************************
46Win32MDIChildWindow::Win32MDIChildWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
47 : Win32BaseWindow(lpCreateStructA, classAtom, isUnicode)
48{
49}
50//******************************************************************************
51//******************************************************************************
52Win32MDIChildWindow::~Win32MDIChildWindow()
53{
54}
55//******************************************************************************
56//******************************************************************************
57LRESULT Win32MDIChildWindow::DefMDIChildProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
58{
59 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
60
61 switch (Msg)
62 {
63 case WM_SETTEXT:
64 DefWindowProcA(Msg, wParam, lParam);
65 menuModifyItem();
66#if 0
67 if( client->getMaximizedChild() == this )
68 MDI_UpdateFrameText( clientWnd->parent, ci->self, MDI_REPAINTFRAME, NULL );
69#endif
70 return 0;
71
72 case WM_GETMINMAXINFO:
73 {
74 childGetMinMaxInfo((MINMAXINFO *)lParam);
75 return 0;
76 }
77
78 case WM_MENUCHAR:
79 /* MDI children don't have menu bars */
80 client->PostMessageA(WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
81 return 0x00010000L;
82
83 case WM_CLOSE:
84 client->SendMessageA(WM_MDIDESTROY,(WPARAM16)getWindowHandle(), 0L);
85 return 0;
86
87 case WM_SETFOCUS:
88 if(client->getActiveChild() != this )
89 client->childActivate(this);
90 break;
91
92 case WM_CHILDACTIVATE:
93 client->childActivate(this);
94 return 0;
95
96 case WM_NCPAINT:
97 break;
98
99 case WM_SYSCOMMAND:
100 switch( wParam )
101 {
102 case SC_MOVE:
103 if( client->getMaximizedChild() == this)
104 {
105 return 0;
106 }
107 break;
108 case SC_RESTORE:
109 case SC_MINIMIZE:
110 setStyle(getStyle() | WS_SYSMENU);
111 break;
112
113 case SC_MAXIMIZE:
114 if( client->getMaximizedChild() == this)
115 {
116 return client->SendMessageA(Msg, wParam, lParam);
117 }
118 setStyle(getStyle() & ~WS_SYSMENU);
119 break;
120
121 case SC_NEXTWINDOW:
122 client->SendMessageA(WM_MDINEXT, 0, 0);
123 return 0;
124
125 case SC_PREVWINDOW: //WM_MDINEXT??
126 client->SendMessageA(WM_MDINEXT, 0, 0);
127 return 0;
128 }
129 break;
130
131 case WM_SETVISIBLE:
132#if 0
133 if( client->getMaximizedChild()) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
134 else
135 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
136#endif
137 break;
138
139#if 0
140 case WM_SIZE:
141 /* do not change */
142
143 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
144 {
145 ci->hwndChildMaximized = 0;
146
147 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
148 MDI_UpdateFrameText( clientWnd->parent, ci->self,
149 MDI_REPAINTFRAME, NULL );
150 }
151
152 if( wParam == SIZE_MAXIMIZED )
153 {
154 HWND16 hMaxChild = ci->hwndChildMaximized;
155
156 if( hMaxChild == hwnd ) break;
157
158 if( hMaxChild)
159 {
160 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
161
162 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
163 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
164
165 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
166 }
167
168 ci->hwndChildMaximized = hwnd; /* !!! */
169 ci->hwndActiveChild = hwnd;
170
171 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
172 MDI_UpdateFrameText( clientWnd->parent, ci->self,
173 MDI_REPAINTFRAME, NULL );
174 }
175
176 if( wParam == SIZE_MINIMIZED )
177 {
178 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
179
180 if( switchTo )
181 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
182 }
183
184 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
185 break;
186#endif
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 SendMessageA(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 switch (Msg)
217 {
218 case WM_SETTEXT:
219 DefWindowProcW(Msg, wParam, lParam);
220 menuModifyItem();
221#if 0
222 if( client->getMaximizedChild() == this )
223 MDI_UpdateFrameText( clientWnd->parent, ci->self, MDI_REPAINTFRAME, NULL );
224#endif
225 return 0;
226
227 case WM_GETMINMAXINFO:
228 case WM_MENUCHAR:
229 case WM_CLOSE:
230 case WM_SETFOCUS:
231 case WM_CHILDACTIVATE:
232 case WM_NCPAINT:
233 case WM_SYSCOMMAND:
234 case WM_SETVISIBLE:
235 case WM_SIZE:
236 case WM_NEXTMENU:
237 return DefMDIChildProcA(Msg, wParam, lParam );
238
239 case WM_SYSCHAR:
240 if (wParam == '-')
241 {
242 SendMessageW(WM_SYSCOMMAND, SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
243 return 0;
244 }
245 break;
246 }
247 return DefWindowProcW(Msg, wParam, lParam);
248}
249/**********************************************************************
250 * MDICreateChild
251 */
252HWND Win32MDIChildWindow::createChild(Win32MDIClientWindow *client, LPMDICREATESTRUCTA cs )
253{
254 POINT pos[2];
255 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
256 HWND hwnd;
257 WORD wIDmenu = client->getFirstChildId() + client->getNrOfChildren();
258 char lpstrDef[]="junk!";
259 Win32MDIChildWindow *maximizedChild, *newchild;
260
261 dprintf(("Win32MDIChildWindow::createChild %i,%i - dim %i,%i, style %08x\n",
262 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style));
263
264 /* calculate placement */
265 calcDefaultChildPos(client, client->incTotalCreated(), pos, 0);
266
267 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
268 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
269
270 if( cs->x == CW_USEDEFAULT )
271 {
272 cs->x = pos[0].x;
273 cs->y = pos[0].y;
274 }
275
276 /* restore current maximized child */
277 if( style & WS_VISIBLE && client->getMaximizedChild() )
278 {
279 if( style & WS_MAXIMIZE )
280 client->SendMessageA(WM_SETREDRAW, FALSE, 0L );
281
282 maximizedChild = client->getMaximizedChild();
283
284 maximizedChild->ShowWindow( SW_SHOWNOACTIVATE );
285
286 if( style & WS_MAXIMIZE )
287 client->SendMessageA(WM_SETREDRAW, TRUE, 0L );
288 }
289
290 /* this menu is needed to set a check mark in MDI_ChildActivate */
291 AppendMenuA(client->getMDIMenu(), MF_STRING ,wIDmenu, lpstrDef );
292
293 client->incNrActiveChildren();
294
295 /* fix window style */
296 if( !(client->getStyle() & MDIS_ALLCHILDSTYLES) )
297 {
298 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
299 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
300 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
301 }
302
303 hwnd = ::CreateWindowA(cs->szClass, cs->szTitle, style,
304 cs->x, cs->y, cs->cx, cs->cy, client->getWindowHandle(),
305 (HMENU)wIDmenu, cs->hOwner, cs );
306
307 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
308 newchild = (Win32MDIChildWindow *)GetWindowFromHandle(hwnd);
309 if (hwnd && newchild)
310 {
311 newchild->menuModifyItem();
312
313 if( newchild->getStyle() & WS_MINIMIZE && client->getActiveChild()) {
314 newchild->ShowWindow(SW_SHOWMINNOACTIVE);
315 }
316 else
317 {
318 /* WS_VISIBLE is clear if a) the MDI client has
319 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
320 * MDICreateStruct. If so the created window is not shown nor
321 * activated.
322 */
323 int showflag = newchild->getStyle() & WS_VISIBLE;
324 /* clear visible flag, otherwise SetWindoPos32 ignores
325 * the SWP_SHOWWINDOW command.
326 */
327 newchild->SetWindowLongA(GWL_STYLE, showflag & ~WS_VISIBLE);
328 if(showflag){
329 newchild->SetWindowPos(0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
330
331 /* Set maximized state here in case hwnd didn't receive WM_SIZE
332 * during CreateWindow - bad!
333 */
334
335 if((newchild->getStyle() & WS_MAXIMIZE) && !client->getMaximizedChild() )
336 {
337 client->setMaximizedChild(newchild);
338#if 0
339 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
340 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
341#endif
342 }
343 }
344 else
345 /* needed, harmless ? */
346 newchild->SetWindowPos(0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
347
348 }
349 }
350 else
351 {
352 client->decNrActiveChildren();
353 DeleteMenu(client->getMDIMenu(), wIDmenu,MF_BYCOMMAND);
354
355 maximizedChild = client->getMaximizedChild();
356 if( maximizedChild && maximizedChild->IsWindow() )
357 maximizedChild->ShowWindow(SW_SHOWMAXIMIZED);
358 }
359 return hwnd;
360}
361/**********************************************************************
362 * MDI_MenuModifyItem
363 */
364BOOL Win32MDIChildWindow::menuModifyItem()
365{
366 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
367 char buffer[128];
368 UINT n = sprintf(buffer, "%d ", getWindowId() - client->getFirstChildId() + 1);
369 BOOL bRet = 0;
370
371 if( !client->getMDIMenu() )
372 {
373 return FALSE;
374 }
375
376 if (getWindowNameA()) lstrcpynA(buffer + n, getWindowNameA(), sizeof(buffer) - n );
377
378 n = GetMenuState(client->getMDIMenu(), getWindowId() ,MF_BYCOMMAND);
379 bRet = ModifyMenuA(client->getMDIMenu() , getWindowId(),
380 MF_BYCOMMAND | MF_STRING, getWindowId(), buffer );
381 CheckMenuItem(client->getMDIMenu(), getWindowId() , n & MF_CHECKED);
382
383 return bRet;
384}
385
386/**********************************************************************
387 * MDI_MenuDeleteItem
388 */
389BOOL Win32MDIChildWindow::menuDeleteItem()
390{
391 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
392 char buffer[128];
393 UINT index = 0,id,n;
394 BOOL retvalue;
395
396 if( !client->getNrOfChildren() ||
397 !client->getMDIMenu())
398 {
399 return FALSE;
400 }
401
402 id = getWindowId();
403 DeleteMenu(client->getMDIMenu(),id,MF_BYCOMMAND);
404
405 /* walk the rest of MDI children to prevent gaps in the id
406 * sequence and in the menu child list */
407
408 for( index = id+1; index <= client->getNrOfChildren() +
409 client->getFirstChildId(); index++ )
410 {
411 Win32MDIChildWindow *tmpWnd = client->getChildByID(index);
412 if( !tmpWnd )
413 {
414 dprintf(("no window for id=%i\n",index));
415 continue;
416 }
417
418 /* set correct id */
419 tmpWnd->setWindowId(tmpWnd->getWindowId()-1);
420
421 n = sprintf(buffer, "%d ",index - client->getFirstChildId());
422 if (tmpWnd->getWindowNameA())
423 lstrcpynA(buffer + n, tmpWnd->getWindowNameA(), sizeof(buffer) - n );
424
425 /* change menu */
426 ModifyMenuA(client->getMDIMenu(), index ,MF_BYCOMMAND | MF_STRING,
427 index - 1 , buffer );
428 }
429 return TRUE;
430}
431/**********************************************************************
432 * MDI_CalcDefaultChildPos
433 *
434 * It seems that the default height is about 2/3 of the client rect
435 */
436void Win32MDIChildWindow::calcDefaultChildPos(Win32MDIClientWindow *client, WORD n, LPPOINT lpPos, INT delta)
437{
438 INT nstagger;
439 RECT rect = *client->getClientRect();
440 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
441 GetSystemMetrics(SM_CYFRAME) - 1;
442
443 if( rect.bottom - rect.top - delta >= spacing )
444 rect.bottom -= delta;
445
446 nstagger = (rect.bottom - rect.top)/(3 * spacing);
447 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
448 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
449 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
450}
451
452/**********************************************************************
453 * MDI_ChildGetMinMaxInfo
454 *
455 * Note: The rule here is that client rect of the maximized MDI child
456 * is equal to the client rect of the MDI client window.
457 */
458void Win32MDIChildWindow::childGetMinMaxInfo(MINMAXINFO* lpMinMax )
459{
460 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
461 RECT rect = *client->getClientRect();
462
463 if(client->getParent() == NULL) {
464 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client parent == NULL!!"));
465 return;
466 }
467 MapWindowPoints(client->getParent()->getWindowHandle(), client->getWindowHandle(), (LPPOINT)&rect, 2);
468
469 AdjustWindowRectEx( &rect, getStyle(), 0, getExStyle());
470
471 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
472 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
473
474 lpMinMax->ptMaxPosition.x = rect.left;
475 lpMinMax->ptMaxPosition.y = rect.top;
476}
477
478//******************************************************************************
479//******************************************************************************
480
Note: See TracBrowser for help on using the repository browser.