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

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

Moved new user32 here

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