source: trunk/src/user32/new/win32wmdiclient.cpp@ 750

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

Added MDI class + ChildWindowFromPointEx by Rene Pronk

File size: 13.6 KB
Line 
1/* $Id: win32wmdiclient.cpp,v 1.2 1999-08-31 10:36:23 sandervl Exp $ */
2/*
3 * Win32 MDI Client Window Class for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 * Parts based on Wine (windows\mdi.c) (990815)
9 *
10 * Copyright 1994, Bob Amstadt
11 * 1995,1996 Alex Korobka
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#include <os2win.h>
17#include <win.h>
18#include <stdlib.h>
19#include <string.h>
20#include <stdarg.h>
21#include <assert.h>
22#include <misc.h>
23#include <heapstring.h>
24#include <win32wnd.h>
25#include <win32wmdiclient.h>
26#include <spy.h>
27#include "wndmsg.h"
28#include "hooks.h"
29#include <oslibwin.h>
30#include <oslibutil.h>
31#include <oslibgdi.h>
32#include <oslibres.h>
33#include "oslibdos.h"
34#include <winres.h>
35#include "syscolor.h"
36#include "win32wndhandle.h"
37#include "heapshared.h"
38
39
40//******************************************************************************
41//******************************************************************************
42Win32MDIClientWindow::Win32MDIClientWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
43 : Win32BaseWindow(lpCreateStructA, classAtom, isUnicode)
44{
45 maximizedChild = 0;
46 activeChild = 0;
47 nActiveChildren = 0;
48 nTotalCreated = 0;
49 frameTitle = NULL;
50 mdiFlags = 0;
51 idFirstChild = 0;
52 hWindowMenu = 0;
53}
54//******************************************************************************
55//******************************************************************************
56Win32MDIClientWindow::~Win32MDIClientWindow()
57{
58}
59//******************************************************************************
60//******************************************************************************
61LRESULT Win32MDIClientWindow::MDIClientWndProc(UINT message, WPARAM wParam, LPARAM lParam)
62{
63 LPCREATESTRUCTA cs;
64 LPCLIENTCREATESTRUCT ccs;
65 RECT rect;
66 INT nItems;
67 LRESULT retvalue;
68 Win32Window *frameWnd;
69 Win32MDIChildWindow *mdichild;
70
71 frameWnd = (Win32Window *)getParent();
72 if(frameWnd == NULL) {
73 return 0;
74 }
75
76 switch (message)
77 {
78 case WM_CREATE:
79 cs = (LPCREATESTRUCTA)lParam;
80 ccs = (LPCLIENTCREATESTRUCT)cs->lpCreateParams;
81
82 hWindowMenu = ccs->hWindowMenu;
83 idFirstChild = ccs->idFirstChild;
84
85 maximizedChild = 0;
86 activeChild = 0;
87 nActiveChildren = 0;
88 nTotalCreated = 0;
89 frameTitle = NULL;
90 mdiFlags = 0;
91
92 setStyle(getStyle() | WS_CLIPCHILDREN);
93
94// MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
95
96 AppendMenuA( hWindowMenu, MF_SEPARATOR, 0, NULL );
97
98 setClientRect(frameWnd->getClientRect());
99
100 dprintf(("MDIClient created - hwnd = %04x, idFirst = %u\n", getWindowHandle(), idFirstChild ));
101
102 retvalue = 0;
103 goto END;
104
105 case WM_DESTROY:
106// if( maximizedChild ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
107
108 if((nItems = GetMenuItemCount(hWindowMenu)) > 0)
109 {
110 idFirstChild = nItems - 1;
111 nActiveChildren++; /* to delete a separator */
112 while( nActiveChildren-- )
113 DeleteMenu(hWindowMenu,MF_BYPOSITION,idFirstChild--);
114 }
115 retvalue = 0;
116 goto END;
117
118 case WM_MDIACTIVATE:
119 if( activeChild && activeChild->getWindowHandle() != (HWND)wParam )
120
121 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
122 if(mdichild) {
123 mdichild->SetWindowPos(0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
124 }
125 retvalue = 0;
126 goto END;
127
128#if 0
129 case WM_MDICASCADE:
130 retvalue = MDICascade(w, ci);
131 goto END;
132#endif
133
134 case WM_MDICREATE:
135 if (lParam) {
136 retvalue = Win32MDIChildWindow::createChild( this, (MDICREATESTRUCTA*)lParam );
137 }
138 else retvalue = 0;
139 goto END;
140
141 case WM_MDIDESTROY:
142// retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
143 goto END;
144
145 case WM_MDIGETACTIVE:
146 if (lParam)
147 *(BOOL *)lParam = (maximizedChild != 0);
148
149 retvalue = (activeChild) ? activeChild->getWindowHandle() : 0;
150 goto END;
151
152#if 0
153 case WM_MDIICONARRANGE:
154 mdiFlags |= MDIF_NEEDUPDATE;
155 ArrangeIconicWindows(hwnd);
156 sbRecalc = SB_BOTH+1;
157 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
158 retvalue = 0;
159 goto END;
160#endif
161
162 case WM_MDIMAXIMIZE:
163 ::ShowWindow( (HWND)wParam, SW_MAXIMIZE );
164 retvalue = 0;
165 goto END;
166
167 case WM_MDINEXT: /* lParam != 0 means previous window */
168// MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
169 break;
170
171 case WM_MDIRESTORE:
172 ::SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
173 retvalue = 0;
174 goto END;
175#if 0
176 case WM_MDISETMENU:
177 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
178 goto END;
179
180 case WM_MDIREFRESHMENU:
181 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
182 goto END;
183
184 case WM_MDITILE:
185 mdiFlags |= MDIF_NEEDUPDATE;
186 ShowScrollBar(hwnd,SB_BOTH,FALSE);
187 MDITile(w, ci, wParam);
188 mdiFlags &= ~MDIF_NEEDUPDATE;
189 retvalue = 0;
190 goto END;
191
192 case WM_VSCROLL:
193 case WM_HSCROLL:
194 mdiFlags |= MDIF_NEEDUPDATE;
195 ScrollChildren(hwnd, message, wParam, lParam);
196 mdiFlags &= ~MDIF_NEEDUPDATE;
197 retvalue = 0;
198 goto END;
199#endif
200
201 case WM_SETFOCUS:
202 if( activeChild )
203 {
204 if( !(activeChild->getStyle() & WS_MINIMIZE) )
205 ::SetFocus(activeChild->getWindowHandle());
206 }
207 retvalue = 0;
208 goto END;
209
210 case WM_NCACTIVATE:
211 if( activeChild )
212 activeChild->SendMessageA(message, wParam, lParam);
213 break;
214
215 case WM_PARENTNOTIFY:
216 if (LOWORD(wParam) == WM_LBUTTONDOWN)
217 {
218 POINTS pt = MAKEPOINTS(lParam);
219 POINT point;
220
221 point.x = pt.x;
222 point.y = pt.y;
223
224 HWND child = ChildWindowFromPoint(getWindowHandle(), point);
225
226 if( child && child != getWindowHandle() && (!activeChild || activeChild->getWindowHandle() != child) )
227 ::SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
228 }
229 retvalue = 0;
230 goto END;
231
232 case WM_SIZE:
233 if( maximizedChild && maximizedChild->IsWindow() )
234 {
235 RECT rect;
236
237 rect.left = 0;
238 rect.top = 0;
239 rect.right = LOWORD(lParam);
240 rect.bottom = HIWORD(lParam);
241
242 AdjustWindowRectEx(&rect, maximizedChild->getStyle(), 0, maximizedChild->getExStyle());
243 ::MoveWindow(maximizedChild->getWindowHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 1);
244 }
245#if 0
246 else
247 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
248#endif
249 break;
250
251#if 0
252 case WM_MDICALCCHILDSCROLL:
253 if( (mdiFlags & MDIF_NEEDUPDATE) && sbRecalc )
254 {
255 CalcChildScroll(hwnd, sbRecalc-1);
256 sbRecalc = 0;
257 mdiFlags &= ~MDIF_NEEDUPDATE;
258 }
259 retvalue = 0;
260 goto END;
261#endif
262 }
263 retvalue = DefWindowProcA(message, wParam, lParam );
264END:
265 return retvalue;
266}
267/**********************************************************************
268 * MDIClientWndProc
269 *
270 * This function handles all MDI requests.
271 */
272LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
273 LPARAM lParam )
274{
275 Win32MDIClientWindow *window;
276
277 window = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwnd);
278 if(!window) {
279 dprintf(("MDIClientWndProc, window %x not found", hwnd));
280 return 0;
281 }
282 return window->MDIClientWndProc(message, wParam, lParam);
283}
284/**********************************************************************
285 * MDI_ChildActivate
286 *
287 * Note: hWndChild is NULL when last child is being destroyed
288 */
289LONG Win32MDIClientWindow::childActivate(Win32MDIChildWindow *child)
290{
291 BOOL isActiveFrameWnd = 0;
292 LONG retvalue;
293 Win32MDIChildWindow *prevActive = activeChild;
294
295 if( child && child->getStyle() & WS_DISABLED )
296 {
297 return 0;
298 }
299
300 if( GetActiveWindow() == getParent()->getWindowHandle())
301 isActiveFrameWnd = TRUE;
302
303 /* deactivate prev. active child */
304 if( prevActive )
305 {
306 prevActive->setStyle(prevActive->getStyle() | WS_SYSMENU);
307 prevActive->SendMessageA( WM_NCACTIVATE, FALSE, 0L );
308 prevActive->SendMessageA( WM_MDIACTIVATE, (WPARAM)prevActive->getWindowHandle(), (LPARAM)(child) ? child->getWindowHandle() : 0);
309
310 /* uncheck menu item */
311 if( getMDIMenu() )
312 CheckMenuItem(getMDIMenu(), prevActive->getWindowId(), 0);
313 }
314
315 /* set appearance */
316 if( maximizedChild)
317 {
318 if( maximizedChild != child) {
319 if( child ) {
320 activeChild = child;
321 child->ShowWindow(SW_SHOWMAXIMIZED);
322 }
323 else
324 if(activeChild) activeChild->ShowWindow( SW_SHOWNORMAL );
325 }
326 }
327
328 activeChild = child;
329
330 /* check if we have any children left */
331 if( !activeChild )
332 {
333 if( isActiveFrameWnd )
334 SetFocus(getWindowHandle());
335
336 return 0;
337 }
338
339 /* check menu item */
340 if( getMDIMenu() )
341 CheckMenuItem(getMDIMenu(), child->getWindowId(), MF_CHECKED);
342
343 /* bring active child to the top */
344 child->SetWindowPos( 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
345
346 if( isActiveFrameWnd )
347 {
348 child->SendMessageA( WM_NCACTIVATE, TRUE, 0L);
349 if( GetFocus() == getWindowHandle())
350 SendMessageA( WM_SETFOCUS, (WPARAM)getWindowHandle(), 0L );
351 else
352 SetFocus( getWindowHandle() );
353 }
354 child->SendMessageA( WM_MDIACTIVATE, (WPARAM)prevActive->getWindowHandle(), (LPARAM)child->getWindowHandle());
355
356 return TRUE;
357}
358/**********************************************************************
359 * MDI_SwitchActiveChild
360 *
361 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
362 * being activated
363 */
364void Win32MDIClientWindow::switchActiveChild(Win32MDIChildWindow *nextActiveChild, BOOL bNextWindow )
365{
366 Win32MDIChildWindow *prevActiveChild = 0;
367
368 if ( !nextActiveChild) return; /* no window to switch to */
369
370 prevActiveChild = getActiveChild();
371
372 if ( prevActiveChild != nextActiveChild)
373 {
374 BOOL bOptimize = 0;
375
376 if( getMaximizedChild() )
377 {
378 bOptimize = 1;
379 nextActiveChild->setStyle(nextActiveChild->getStyle()& ~WS_VISIBLE);
380 }
381
382 nextActiveChild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
383
384 if( bNextWindow && prevActiveChild )
385 prevActiveChild->SetWindowPos(HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
386
387 if( bOptimize )
388 ShowWindow(SW_SHOW );
389 }
390}
391
392
393/**********************************************************************
394 * MDIDestroyChild
395 */
396LRESULT Win32MDIClientWindow::destroyChild(Win32MDIChildWindow *child, BOOL flagDestroy )
397{
398 if( child == getActiveChild())
399 {
400 switchActiveChild(child, TRUE);
401
402 if( child == getActiveChild() )
403 {
404 ShowWindow(SW_HIDE);
405 if( child == getMaximizedChild() )
406 {
407// MDI_RestoreFrameMenu(w_parent->parent, child);
408 setMaximizedChild(NULL);
409// MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
410 }
411 childActivate(0);
412 }
413 }
414 child->menuDeleteItem();
415
416 decNrActiveChildren();
417
418 dprintf(("child destroyed - %04x\n", child->getWindowHandle()));
419
420 if (flagDestroy)
421 {
422// MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
423 ::DestroyWindow(child->getWindowHandle());
424 }
425
426 return 0;
427}
428/* -------- Miscellaneous service functions ----------
429 *
430 * MDI_GetChildByID
431 */
432Win32MDIChildWindow *Win32MDIClientWindow::getChildByID(INT id)
433{
434 Win32MDIChildWindow *child;
435
436 for (child = (Win32MDIChildWindow *)getFirstChild() ; child; child = (Win32MDIChildWindow *)child->getNextChild())
437 if (child->getWindowId() == id) return child;
438
439 return 0;
440}
441//******************************************************************************
442//******************************************************************************
443BOOL MDICLIENT_Register()
444{
445 WNDCLASSA wndClass;
446
447 if (GlobalFindAtomA(MDICLIENTCLASSNAME)) return FALSE;
448
449 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
450 wndClass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC | CS_DBLCLKS;
451 wndClass.lpfnWndProc = (WNDPROC)MDIClientWndProc;
452 wndClass.cbClsExtra = 0;
453 wndClass.cbWndExtra = 0;
454 wndClass.hCursor = 0;
455 wndClass.hbrBackground = (HBRUSH)0;
456 wndClass.lpszClassName = MDICLIENTCLASSNAME;
457
458 return RegisterClassA(&wndClass);
459}
460//******************************************************************************
461//******************************************************************************
462BOOL MDICLIENT_Unregister()
463{
464 if (GlobalFindAtomA(MDICLIENTCLASSNAME))
465 return UnregisterClassA(MDICLIENTCLASSNAME,(HINSTANCE)NULL);
466 else return FALSE;
467}
468//******************************************************************************
469//******************************************************************************
Note: See TracBrowser for help on using the repository browser.