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

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

Icon api rewrite + small fixes

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