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

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

bug fixes

File size: 17.0 KB
Line 
1/* $Id: win32wmdichild.cpp,v 1.27 2001-06-11 20:08:25 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 dprintf(("Fixing MDI window style! %x -> %x", style, style | WS_VISIBLE | WS_OVERLAPPEDWINDOW));
306 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
307 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
308 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
309 }
310
311 createstruct.lpszName = cs->szTitle;
312 createstruct.style = style;
313 createstruct.dwExStyle = 0;
314 createstruct.x = cs->x;
315 createstruct.y = cs->y;
316 createstruct.cx = cs->cx;
317 createstruct.cy = cs->cy;
318 createstruct.hInstance = cs->hOwner;
319 createstruct.hMenu = wIDmenu;
320 createstruct.hwndParent= client->getWindowHandle();
321 createstruct.lpCreateParams = (LPVOID)cs;
322
323 className = (LPSTR)cs->szClass;
324 /* Find the class atom */
325 classAtom = GlobalFindAtomA(cs->szClass);
326 if(classAtom == 0)
327 {
328 if (!HIWORD(cs->szClass))
329 {
330 sprintf(tmpClassA,"#%d", (int) className);
331 classAtom = GlobalFindAtomA(tmpClassA);
332 className = tmpClassA;
333 }
334 if (!classAtom)
335 {
336 if (!HIWORD(cs->szClass)) {
337 dprintf(("createChild: bad class name %04x\n", LOWORD(className)));
338 }
339 else dprintf(("createChild: bad class name '%s'\n", tmpClassA ));
340
341 SetLastError(ERROR_INVALID_PARAMETER);
342 return 0;
343 }
344 }
345 createstruct.lpszClass = className;
346
347 newchild = new Win32MDIChildWindow(&createstruct, classAtom, FALSE);
348
349 if(newchild && GetLastError() == 0)
350 {
351 /* All MDI child windows have the WS_EX_MDICHILD style */
352 newchild->setExStyle(newchild->getExStyle() | WS_EX_MDICHILD);
353
354 newchild->menuModifyItem();
355
356 if( newchild->getStyle() & WS_MINIMIZE && client->getActiveChild()) {
357 newchild->ShowWindow(SW_SHOWMINNOACTIVE);
358 }
359 else
360 {
361 /* WS_VISIBLE is clear if a) the MDI client has
362 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
363 * MDICreateStruct. If so the created window is not shown nor
364 * activated.
365 */
366 int showflag = newchild->getStyle() & WS_VISIBLE;
367 /* clear visible flag, otherwise SetWindoPos32 ignores
368 * the SWP_SHOWWINDOW command.
369 */
370 newchild->setStyle(newchild->getStyle() & ~WS_VISIBLE);
371
372 if(showflag){
373 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
374 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
375 dprintf(("newchild->SetWindowPos active window %x", GetActiveWindow()));
376
377 /* Set maximized state here in case hwnd didn't receive WM_SIZE
378 * during CreateWindow - bad!
379 */
380
381 if((newchild->getStyle() & WS_MAXIMIZE) && !client->getMaximizedChild() )
382 {
383 client->setMaximizedChild(newchild->getWindowHandle());
384
385 client->augmentFrameMenu(newchild->getWindowHandle());
386
387 client->updateFrameText(MDI_REPAINTFRAME, NULL );
388 }
389 }
390 else
391 /* needed, harmless ? */
392 newchild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
393
394 }
395 }
396 else
397 {
398 client->decNrActiveChildren();
399 if(client->getMDIMenu()) {
400 DeleteMenu(client->getMDIMenu(), wIDmenu,MF_BYCOMMAND);
401 }
402
403 maximizedChild = client->getMaximizedChild();
404 if( ::IsWindow(maximizedChild) )
405 ::ShowWindow(maximizedChild, SW_SHOWMAXIMIZED);
406
407 dprintf(("MDI child creation failed!!"));
408 return 0;
409 }
410 return newchild->getWindowHandle();
411}
412/**********************************************************************
413 * MDI_MenuModifyItem
414 */
415BOOL Win32MDIChildWindow::menuModifyItem()
416{
417 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
418 char buffer[128];
419 UINT id = getWindowId()-client->getFirstChildId()+1;
420 UINT n = sprintf(buffer,(id > 9) ? "%d":"&%d ",id);
421 BOOL bRet = 0;
422
423 if( !client->getMDIMenu() )
424 {
425 return FALSE;
426 }
427
428 if (getWindowNameA()) lstrcpynA(buffer + n, getWindowNameA(), sizeof(buffer) - n );
429
430 n = GetMenuState(client->getMDIMenu(), getWindowId() ,MF_BYCOMMAND);
431 bRet = ModifyMenuA(client->getMDIMenu() , getWindowId(),
432 MF_BYCOMMAND | MF_STRING, getWindowId(), buffer );
433 CheckMenuItem(client->getMDIMenu(), getWindowId() , n & MF_CHECKED);
434
435 return bRet;
436}
437
438/**********************************************************************
439 * MDI_MenuDeleteItem
440 */
441BOOL Win32MDIChildWindow::menuDeleteItem()
442{
443 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
444 char buffer[128];
445 UINT index = 0,id,n;
446 BOOL retvalue;
447
448 if( !client->getNrOfChildren() ||
449 !client->getMDIMenu())
450 {
451 return FALSE;
452 }
453
454 id = getWindowId();
455 DeleteMenu(client->getMDIMenu(),id,MF_BYCOMMAND);
456
457 /* walk the rest of MDI children to prevent gaps in the id
458 * sequence and in the menu child list */
459
460 lock();
461 for( index = id+1; index <= client->getNrOfChildren() +
462 client->getFirstChildId(); index++ )
463 {
464 Win32MDIChildWindow *tmpWnd = (Win32MDIChildWindow *)GetWindowFromHandle(client->getChildByID(index));
465 if( !tmpWnd )
466 {
467 dprintf(("no window for id=%i\n",index));
468 continue;
469 }
470
471 /* set correct id */
472 tmpWnd->setWindowId(tmpWnd->getWindowId()-1);
473
474 n = sprintf(buffer, "%d ",index - client->getFirstChildId());
475 if (tmpWnd->getWindowNameA())
476 lstrcpynA(buffer + n, tmpWnd->getWindowNameA(), sizeof(buffer) - n );
477
478 RELEASE_WNDOBJ(tmpWnd);
479
480 unlock();
481 /* change menu */
482 ModifyMenuA(client->getMDIMenu(), index ,MF_BYCOMMAND | MF_STRING,
483 index - 1 , buffer );
484 lock();
485 }
486 unlock();
487 return TRUE;
488}
489/**********************************************************************
490 * MDI_CalcDefaultChildPos
491 *
492 * It seems that the default height is about 2/3 of the client rect
493 */
494void Win32MDIChildWindow::calcDefaultChildPos(Win32MDIClientWindow *client, WORD n, LPPOINT lpPos, INT delta)
495{
496 INT nstagger;
497 RECT rect;
498 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
499 GetSystemMetrics(SM_CYFRAME) - 1;
500
501 client->getClientRect(&rect);
502 if( rect.bottom - rect.top - delta >= spacing )
503 rect.bottom -= delta;
504
505 nstagger = (rect.bottom - rect.top)/(3 * spacing);
506 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
507 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
508 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
509}
510
511/**********************************************************************
512 * MDI_ChildGetMinMaxInfo
513 *
514 * Note: The rule here is that client rect of the maximized MDI child
515 * is equal to the client rect of the MDI client window.
516 */
517void Win32MDIChildWindow::childGetMinMaxInfo(MINMAXINFO* lpMinMax )
518{
519 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
520 RECT rect;
521
522 if(client == NULL) {
523 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client == NULL!!"));
524 return;
525 }
526
527 client->getClientRect(&rect);
528 if(client->getParent() == NULL) {
529 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client parent == NULL!!"));
530 return;
531 }
532 //SvL: No mapping required as our client rectangle is in frame coordinates (not relative to parent!)
533///// MapWindowPoints(client->getParent()->getWindowHandle(), client->getWindowHandle(), (LPPOINT)&rect, 2);
534
535 AdjustWindowRectEx( &rect, getStyle(), 0, getExStyle());
536
537 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
538 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
539
540 lpMinMax->ptMaxPosition.x = rect.left;
541 lpMinMax->ptMaxPosition.y = rect.top;
542}
543
544//******************************************************************************
545//******************************************************************************
546
Note: See TracBrowser for help on using the repository browser.