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

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

WM_ACTIVATE(APP) changes

File size: 15.7 KB
Line 
1/* $Id: win32wmdichild.cpp,v 1.2 1999-09-29 09:16:32 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 hwnd = ::CreateWindowA(cs->szClass, cs->szTitle, style,
329 cs->x, cs->y, cs->cx, cs->cy, client->getWindowHandle(),
330 (HMENU)wIDmenu, cs->hOwner, cs );
331
332 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
333 newchild = (Win32MDIChildWindow *)GetWindowFromHandle(hwnd);
334 if (hwnd && newchild)
335 {
336 newchild->menuModifyItem();
337
338 if( newchild->getStyle() & WS_MINIMIZE && client->getActiveChild()) {
339 newchild->ShowWindow(SW_SHOWMINNOACTIVE);
340 }
341 else
342 {
343 /* WS_VISIBLE is clear if a) the MDI client has
344 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
345 * MDICreateStruct. If so the created window is not shown nor
346 * activated.
347 */
348 int showflag = newchild->getStyle() & WS_VISIBLE;
349 /* clear visible flag, otherwise SetWindoPos32 ignores
350 * the SWP_SHOWWINDOW command.
351 */
352 newchild->SetWindowLongA(GWL_STYLE, showflag & ~WS_VISIBLE);
353 if(showflag){
354 newchild->SetWindowPos(0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
355
356 /* Set maximized state here in case hwnd didn't receive WM_SIZE
357 * during CreateWindow - bad!
358 */
359
360 if((newchild->getStyle() & WS_MAXIMIZE) && !client->getMaximizedChild() )
361 {
362 client->setMaximizedChild(newchild);
363#if 0
364 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
365#endif
366 client->updateFrameText(MDI_REPAINTFRAME, NULL );
367 }
368 }
369 else
370 /* needed, harmless ? */
371 newchild->SetWindowPos(0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
372
373 }
374 }
375 else
376 {
377 client->decNrActiveChildren();
378 DeleteMenu(client->getMDIMenu(), wIDmenu,MF_BYCOMMAND);
379
380 maximizedChild = client->getMaximizedChild();
381 if( maximizedChild && maximizedChild->IsWindow() )
382 maximizedChild->ShowWindow(SW_SHOWMAXIMIZED);
383 }
384 return hwnd;
385}
386/**********************************************************************
387 * MDI_MenuModifyItem
388 */
389BOOL Win32MDIChildWindow::menuModifyItem()
390{
391 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
392 char buffer[128];
393 UINT n = sprintf(buffer, "%d ", getWindowId() - client->getFirstChildId() + 1);
394 BOOL bRet = 0;
395
396 if( !client->getMDIMenu() )
397 {
398 return FALSE;
399 }
400
401 if (getWindowNameA()) lstrcpynA(buffer + n, getWindowNameA(), sizeof(buffer) - n );
402
403 n = GetMenuState(client->getMDIMenu(), getWindowId() ,MF_BYCOMMAND);
404 bRet = ModifyMenuA(client->getMDIMenu() , getWindowId(),
405 MF_BYCOMMAND | MF_STRING, getWindowId(), buffer );
406 CheckMenuItem(client->getMDIMenu(), getWindowId() , n & MF_CHECKED);
407
408 return bRet;
409}
410
411/**********************************************************************
412 * MDI_MenuDeleteItem
413 */
414BOOL Win32MDIChildWindow::menuDeleteItem()
415{
416 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
417 char buffer[128];
418 UINT index = 0,id,n;
419 BOOL retvalue;
420
421 if( !client->getNrOfChildren() ||
422 !client->getMDIMenu())
423 {
424 return FALSE;
425 }
426
427 id = getWindowId();
428 DeleteMenu(client->getMDIMenu(),id,MF_BYCOMMAND);
429
430 /* walk the rest of MDI children to prevent gaps in the id
431 * sequence and in the menu child list */
432
433 for( index = id+1; index <= client->getNrOfChildren() +
434 client->getFirstChildId(); index++ )
435 {
436 Win32MDIChildWindow *tmpWnd = client->getChildByID(index);
437 if( !tmpWnd )
438 {
439 dprintf(("no window for id=%i\n",index));
440 continue;
441 }
442
443 /* set correct id */
444 tmpWnd->setWindowId(tmpWnd->getWindowId()-1);
445
446 n = sprintf(buffer, "%d ",index - client->getFirstChildId());
447 if (tmpWnd->getWindowNameA())
448 lstrcpynA(buffer + n, tmpWnd->getWindowNameA(), sizeof(buffer) - n );
449
450 /* change menu */
451 ModifyMenuA(client->getMDIMenu(), index ,MF_BYCOMMAND | MF_STRING,
452 index - 1 , buffer );
453 }
454 return TRUE;
455}
456/**********************************************************************
457 * MDI_CalcDefaultChildPos
458 *
459 * It seems that the default height is about 2/3 of the client rect
460 */
461void Win32MDIChildWindow::calcDefaultChildPos(Win32MDIClientWindow *client, WORD n, LPPOINT lpPos, INT delta)
462{
463 INT nstagger;
464 RECT rect = *client->getClientRect();
465 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
466 GetSystemMetrics(SM_CYFRAME) - 1;
467
468 if( rect.bottom - rect.top - delta >= spacing )
469 rect.bottom -= delta;
470
471 nstagger = (rect.bottom - rect.top)/(3 * spacing);
472 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
473 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
474 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
475}
476
477/**********************************************************************
478 * MDI_ChildGetMinMaxInfo
479 *
480 * Note: The rule here is that client rect of the maximized MDI child
481 * is equal to the client rect of the MDI client window.
482 */
483void Win32MDIChildWindow::childGetMinMaxInfo(MINMAXINFO* lpMinMax )
484{
485 Win32MDIClientWindow *client = (Win32MDIClientWindow *)getParent();
486 RECT rect = *client->getClientRect();
487
488 if(client->getParent() == NULL) {
489 dprintf(("Win32MDIChildWindow::childGetMinMaxInfo:: client parent == NULL!!"));
490 return;
491 }
492 MapWindowPoints(client->getParent()->getWindowHandle(), client->getWindowHandle(), (LPPOINT)&rect, 2);
493
494 AdjustWindowRectEx( &rect, getStyle(), 0, getExStyle());
495
496 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
497 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
498
499 lpMinMax->ptMaxPosition.x = rect.left;
500 lpMinMax->ptMaxPosition.y = rect.top;
501}
502
503//******************************************************************************
504//******************************************************************************
505
Note: See TracBrowser for help on using the repository browser.