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

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

EB's fixes + scrollbar changes

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