source: trunk/src/user32/win32wmdiclient.cpp@ 2844

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

Added new logging feature

File size: 37.8 KB
Line 
1/* $Id: win32wmdiclient.cpp,v 1.24 2000-02-16 14:28:24 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 <math.h>
20#include <string.h>
21#include <stdarg.h>
22#include <assert.h>
23#include <misc.h>
24#include <heapstring.h>
25#include <win32wnd.h>
26#include <win32wmdiclient.h>
27#include <spy.h>
28#include "wndmsg.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
38#define DBG_LOCALLOG DBG_win32wmdiclient
39#include "dbglocal.h"
40
41
42//******************************************************************************
43//******************************************************************************
44Win32MDIClientWindow::Win32MDIClientWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
45 : maximizedChild(0), activeChild(0), nActiveChildren(0), nTotalCreated(0),
46 frameTitle(NULL), mdiFlags(0), idFirstChild(0), hWindowMenu(0),
47 sbRecalc(0),
48 Win32BaseWindow(OBJTYPE_WINDOW)
49{
50 Init();
51 this->isUnicode = isUnicode;
52 CreateWindowExA(lpCreateStructA, classAtom);
53}
54//******************************************************************************
55//******************************************************************************
56Win32MDIClientWindow::~Win32MDIClientWindow()
57{
58 if(frameTitle)
59 HeapFree(GetProcessHeap(), 0, frameTitle);
60}
61//******************************************************************************
62//******************************************************************************
63BOOL Win32MDIClientWindow::isMDIClient()
64{
65 return TRUE;
66}
67//******************************************************************************
68//******************************************************************************
69LRESULT Win32MDIClientWindow::MDIClientWndProc(UINT message, WPARAM wParam, LPARAM lParam)
70{
71 LPCREATESTRUCTA cs;
72 LPCLIENTCREATESTRUCT ccs;
73 RECT rect;
74 INT nItems;
75 LRESULT retvalue;
76 Win32Window *frameWnd;
77 Win32MDIChildWindow *mdichild;
78
79 frameWnd = (Win32Window *)getParent();
80 if(frameWnd == NULL) {
81 return 0;
82 }
83
84 switch (message)
85 {
86 case WM_CREATE:
87 cs = (LPCREATESTRUCTA)lParam;
88 ccs = (LPCLIENTCREATESTRUCT)cs->lpCreateParams;
89
90 hWindowMenu = ccs->hWindowMenu;
91 idFirstChild = ccs->idFirstChild;
92
93 maximizedChild = 0;
94 activeChild = 0;
95 nActiveChildren = 0;
96 nTotalCreated = 0;
97 frameTitle = NULL;
98 mdiFlags = 0;
99
100 setStyle(getStyle() | WS_CLIPCHILDREN);
101
102 updateFrameText(MDI_NOFRAMEREPAINT, getParent()->getWindowNameA());
103
104 AppendMenuA( hWindowMenu, MF_SEPARATOR, 0, NULL );
105
106 setClientRect(frameWnd->getClientRectPtr());
107
108 dprintf(("MDIClient created - hwnd = %04x, idFirst = %u\n", getWindowHandle(), idFirstChild ));
109
110 retvalue = 0;
111 goto END;
112
113 case WM_DESTROY:
114 if( maximizedChild ) restoreFrameMenu(getParent());
115
116 if((nItems = GetMenuItemCount(hWindowMenu)) > 0)
117 {
118 idFirstChild = nItems - 1;
119 nActiveChildren++; /* to delete a separator */
120 while( nActiveChildren-- )
121 DeleteMenu(hWindowMenu,MF_BYPOSITION,idFirstChild--);
122 }
123 retvalue = 0;
124 goto END;
125
126 case WM_MDIACTIVATE:
127 if( activeChild && activeChild->getWindowHandle() != (HWND)wParam )
128 {
129 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
130 if(mdichild) {
131 mdichild->SetWindowPos(0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
132 }
133 }
134 retvalue = 0;
135 goto END;
136
137 case WM_MDICASCADE:
138 retvalue = cascade(wParam);
139 goto END;
140
141 case WM_MDICREATE:
142 if (lParam) {
143 retvalue = Win32MDIChildWindow::createChild( this, (MDICREATESTRUCTA*)lParam );
144 }
145 else retvalue = 0;
146 goto END;
147
148 case WM_MDIDESTROY:
149 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
150 if(mdichild) {
151 retvalue = destroyChild(mdichild, TRUE );
152 }
153 goto END;
154
155 case WM_MDIGETACTIVE:
156 dprintf(("WM_MDIGETACTIVE: %x %x", this, (activeChild) ? activeChild->getWindowHandle() : 0));
157 if (lParam)
158 *(BOOL *)lParam = (maximizedChild != 0);
159
160 retvalue = (activeChild) ? activeChild->getWindowHandle() : 0;
161 goto END;
162
163 case WM_MDIICONARRANGE:
164 mdiFlags |= MDIF_NEEDUPDATE;
165 ArrangeIconicWindows(Win32Hwnd);
166 sbRecalc = SB_BOTH+1;
167 SendMessageA(WM_MDICALCCHILDSCROLL,0,0L);
168 retvalue = 0;
169 goto END;
170
171 case WM_MDIMAXIMIZE:
172 ::ShowWindow( (HWND)wParam, SW_MAXIMIZE );
173 retvalue = 0;
174 goto END;
175
176 case WM_MDINEXT: /* lParam != 0 means previous window */
177 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
178 if(mdichild) {
179 switchActiveChild(mdichild, (lParam)? FALSE : TRUE );
180 }
181 break;
182
183 case WM_MDIRESTORE:
184 ::SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
185 retvalue = 0;
186 goto END;
187 case WM_MDISETMENU:
188 retvalue = setMDIMenu((HMENU)wParam, (HMENU)lParam );
189 goto END;
190
191 case WM_MDIREFRESHMENU:
192 retvalue = refreshMDIMenu((HMENU)wParam, (HMENU)lParam );
193 goto END;
194
195 case WM_MDITILE:
196 mdiFlags |= MDIF_NEEDUPDATE;
197 ShowScrollBar(Win32Hwnd,SB_BOTH,FALSE);
198 tile(wParam);
199 mdiFlags &= ~MDIF_NEEDUPDATE;
200 retvalue = 0;
201 goto END;
202
203 case WM_VSCROLL:
204 case WM_HSCROLL:
205 mdiFlags |= MDIF_NEEDUPDATE;
206 ScrollChildren(Win32Hwnd, message, wParam, lParam);
207 mdiFlags &= ~MDIF_NEEDUPDATE;
208 retvalue = 0;
209 goto END;
210
211 case WM_SETFOCUS:
212 if( activeChild )
213 {
214 if( !(activeChild->getStyle() & WS_MINIMIZE) )
215 ::SetFocus(activeChild->getWindowHandle());
216 }
217 retvalue = 0;
218 goto END;
219
220 case WM_NCACTIVATE:
221 if( activeChild )
222 activeChild->SendInternalMessageA(message, wParam, lParam);
223 break;
224
225 case WM_PARENTNOTIFY:
226 if (LOWORD(wParam) == WM_LBUTTONDOWN)
227 {
228 POINTS pt = MAKEPOINTS(lParam);
229 POINT point;
230
231 point.x = pt.x;
232 point.y = pt.y;
233
234 HWND child = ChildWindowFromPoint(getWindowHandle(), point);
235
236 if( child && child != getWindowHandle() && (!activeChild || activeChild->getWindowHandle() != child) )
237 ::SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
238 }
239 retvalue = 0;
240 goto END;
241
242 case WM_SIZE:
243 if( maximizedChild && maximizedChild->IsWindow() )
244 {
245 RECT rect;
246
247 rect.left = 0;
248 rect.top = 0;
249 rect.right = LOWORD(lParam);
250 rect.bottom = HIWORD(lParam);
251
252 AdjustWindowRectEx(&rect, maximizedChild->getStyle(), 0, maximizedChild->getExStyle());
253 ::MoveWindow(maximizedChild->getWindowHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 1);
254 }
255 else postUpdate(SB_BOTH+1);
256 break;
257
258 case WM_MDICALCCHILDSCROLL:
259 if( (mdiFlags & MDIF_NEEDUPDATE) && sbRecalc )
260 {
261 CalcChildScroll(Win32Hwnd, sbRecalc-1);
262 sbRecalc = 0;
263 mdiFlags &= ~MDIF_NEEDUPDATE;
264 }
265 retvalue = 0;
266 goto END;
267 }
268 retvalue = DefWindowProcA(message, wParam, lParam );
269END:
270 return retvalue;
271}
272/**********************************************************************
273 * MDIClientWndProc
274 *
275 * This function handles all MDI requests.
276 */
277LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
278 LPARAM lParam )
279{
280 Win32MDIClientWindow *window;
281
282 window = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwnd);
283 if(!window) {
284 dprintf(("MDIClientWndProc, window %x not found", hwnd));
285 return 0;
286 }
287 return window->MDIClientWndProc(message, wParam, lParam);
288}
289/**********************************************************************
290 * MDI_GetWindow
291 *
292 * returns "activateable" child different from the current or zero
293 */
294Win32MDIChildWindow *Win32MDIClientWindow::getWindow(Win32MDIChildWindow *actchild, BOOL bNext,
295 DWORD dwStyleMask)
296{
297 Win32MDIChildWindow *lastchild = 0, *curchild;
298
299 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
300
301 if( !actchild ) actchild = getActiveChild();
302 if( !actchild) return 0;
303
304 for ( curchild = (Win32MDIChildWindow *)actchild->getNextChild(); ; curchild = (Win32MDIChildWindow *)curchild->getNextChild())
305 {
306 if (!curchild ) curchild = (Win32MDIChildWindow *)getFirstChild();
307
308 if ( curchild == actchild ) break; /* went full circle */
309
310 if (!curchild->getOwner() && (curchild->getStyle() & dwStyleMask) == WS_VISIBLE )
311 {
312 lastchild = curchild;
313 if ( bNext ) break;
314 }
315 }
316 return lastchild;
317}
318/**********************************************************************
319 * MDI_ChildActivate
320 *
321 * Note: hWndChild is NULL when last child is being destroyed
322 */
323LONG Win32MDIClientWindow::childActivate(Win32MDIChildWindow *child)
324{
325 BOOL isActiveFrameWnd = 0;
326 LONG retvalue;
327 Win32MDIChildWindow *prevActive = activeChild;
328
329 if( child && child->getStyle() & WS_DISABLED )
330 {
331 return 0;
332 }
333
334 if( GetActiveWindow() == getParent()->getWindowHandle())
335 isActiveFrameWnd = TRUE;
336
337 /* deactivate prev. active child */
338 if( prevActive )
339 {
340 prevActive->setStyle(prevActive->getStyle() | WS_SYSMENU);
341 prevActive->SendInternalMessageA( WM_NCACTIVATE, FALSE, 0L );
342 prevActive->SendInternalMessageA( WM_MDIACTIVATE, (WPARAM)prevActive->getWindowHandle(), (LPARAM)(child) ? child->getWindowHandle() : 0);
343
344 /* uncheck menu item */
345 if( getMDIMenu() )
346 CheckMenuItem(getMDIMenu(), prevActive->getWindowId(), 0);
347 }
348
349 /* set appearance */
350 if( maximizedChild)
351 {
352 if( maximizedChild != child) {
353 if( child ) {
354 activeChild = child;
355 child->ShowWindow(SW_SHOWMAXIMIZED);
356 }
357 else
358 if(activeChild) activeChild->ShowWindow( SW_SHOWNORMAL );
359 }
360 }
361
362 dprintf(("childActivate: %x %x", this, (child) ? child->getWindowHandle() : 0));
363 activeChild = child;
364
365 /* check if we have any children left */
366 if( !activeChild )
367 {
368 if( isActiveFrameWnd )
369 SetFocus(getWindowHandle());
370
371 return 0;
372 }
373
374 /* check menu item */
375 if( getMDIMenu() )
376 CheckMenuItem(getMDIMenu(), child->getWindowId(), MF_CHECKED);
377
378 /* bring active child to the top */
379 child->SetWindowPos( 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
380
381 if( isActiveFrameWnd )
382 {
383 child->SendInternalMessageA( WM_NCACTIVATE, TRUE, 0L);
384 if( GetFocus() == getWindowHandle())
385 SendInternalMessageA( WM_SETFOCUS, (WPARAM)getWindowHandle(), 0L );
386 else
387 SetFocus( getWindowHandle() );
388 }
389
390 /* @@@PH prevActive may be NULL actually ?! */
391 child->SendInternalMessageA( WM_MDIACTIVATE,
392 prevActive ? (WPARAM)prevActive->getWindowHandle() : 0,
393 child->getWindowHandle());
394 return TRUE;
395}
396/**********************************************************************
397 * MDI_SwitchActiveChild
398 *
399 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
400 * being activated
401 */
402void Win32MDIClientWindow::switchActiveChild(Win32MDIChildWindow *nextActiveChild, BOOL bNextWindow )
403{
404 Win32MDIChildWindow *prevActiveChild = 0;
405
406 if ( !nextActiveChild) return; /* no window to switch to */
407
408 prevActiveChild = getActiveChild();
409
410 if ( prevActiveChild != nextActiveChild)
411 {
412 BOOL bOptimize = 0;
413
414 if( getMaximizedChild() )
415 {
416 bOptimize = 1;
417 nextActiveChild->setStyle(nextActiveChild->getStyle()& ~WS_VISIBLE);
418 }
419
420 nextActiveChild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
421
422 if( bNextWindow && prevActiveChild )
423 prevActiveChild->SetWindowPos(HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
424
425 if( bOptimize )
426 ShowWindow(SW_SHOW );
427 }
428}
429
430
431/**********************************************************************
432 * MDIDestroyChild
433 */
434LRESULT Win32MDIClientWindow::destroyChild(Win32MDIChildWindow *child, BOOL flagDestroy )
435{
436 if( child == getActiveChild())
437 {
438 switchActiveChild(child, TRUE);
439
440 if( child == getActiveChild() )
441 {
442 ::ShowWindow(child->getWindowHandle(),SW_HIDE);
443 if( child == getMaximizedChild() )
444 {
445 restoreFrameMenu(child);
446 setMaximizedChild(NULL);
447 updateFrameText(TRUE,NULL);
448 }
449 childActivate(0);
450 }
451 }
452 child->menuDeleteItem();
453
454 decNrActiveChildren();
455
456 dprintf(("child destroyed - %04x\n", child->getWindowHandle()));
457
458 if (flagDestroy)
459 {
460 postUpdate(SB_BOTH+1);
461 ::DestroyWindow(child->getWindowHandle());
462 }
463
464 return 0;
465}
466/**********************************************************************
467 * MDI_UpdateFrameText
468 *
469 * used when child window is maximized/restored
470 *
471 * Note: lpTitle can be NULL
472 */
473void Win32MDIClientWindow::updateFrameText(BOOL repaint, LPCSTR lpTitle )
474{
475 char lpBuffer[MDI_MAXTITLELENGTH+1];
476
477 /* store new "default" title if lpTitle is not NULL */
478 if (lpTitle)
479 {
480 if (frameTitle) HeapFree( GetProcessHeap(), 0, frameTitle );
481 frameTitle = HEAP_strdupA( GetProcessHeap(), 0, lpTitle );
482 }
483
484 if (frameTitle)
485 {
486 Win32MDIChildWindow *childWnd = getMaximizedChild();
487
488 if( childWnd && childWnd->getWindowNameA() )
489 {
490 /* combine frame title and child title if possible */
491
492 LPCSTR lpBracket = " - [";
493 int i_frame_text_length = strlen(frameTitle);
494 int i_child_text_length = strlen(childWnd->getWindowNameA());
495
496 lstrcpynA( lpBuffer, frameTitle, MDI_MAXTITLELENGTH);
497
498 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
499 {
500 strcat( lpBuffer, lpBracket );
501
502 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
503 {
504 strcat( lpBuffer, childWnd->getWindowNameA());
505 strcat( lpBuffer, "]" );
506 }
507 else
508 {
509 lstrcpynA(lpBuffer + i_frame_text_length + 4,
510 childWnd->getWindowNameA(), MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
511 strcat( lpBuffer, "]" );
512 }
513 }
514 }
515 else
516 {
517 lstrcpynA(lpBuffer, frameTitle, MDI_MAXTITLELENGTH );
518 lpBuffer[MDI_MAXTITLELENGTH]='\0';
519 }
520 }
521 else
522 lpBuffer[0] = '\0';
523
524 getParent()->SetWindowTextA(lpBuffer);
525 if( repaint == MDI_REPAINTFRAME)
526 getParent()->SetWindowPos(0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
527}
528/**********************************************************************
529 * MDISetMenu
530 */
531LRESULT Win32MDIClientWindow::setMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
532{
533 HWND hwndFrame = ::GetParent(getWindowHandle());
534 HMENU oldFrameMenu = ::GetMenu(hwndFrame);
535
536 if( maximizedChild && hmenuFrame && hmenuFrame!=oldFrameMenu )
537 restoreFrameMenu(maximizedChild);
538
539 if( hmenuWindow && hmenuWindow != hWindowMenu )
540 {
541 /* delete menu items from ci->hWindowMenu
542 * and add them to hmenuWindow */
543
544 INT i = GetMenuItemCount(hWindowMenu) - 1;
545 INT pos = GetMenuItemCount(hmenuWindow) + 1;
546
547 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
548
549 if( nActiveChildren )
550 {
551 INT j = i - nActiveChildren + 1;
552 char buffer[100];
553 UINT id,state;
554
555 for( ; i >= j ; i-- )
556 {
557 id = GetMenuItemID(hWindowMenu,i );
558 state = GetMenuState(hWindowMenu,i,MF_BYPOSITION);
559
560 GetMenuStringA(hWindowMenu, i, buffer, 100, MF_BYPOSITION);
561
562 DeleteMenu(hWindowMenu, i , MF_BYPOSITION);
563 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
564 id, buffer);
565 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
566 }
567 }
568
569 /* remove separator */
570 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
571
572 hWindowMenu = hmenuWindow;
573 }
574
575 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
576 {
577 ::SetMenu(hwndFrame, hmenuFrame);
578
579 if (maximizedChild)
580 augmentFrameMenu(maximizedChild);
581
582 return oldFrameMenu;
583 }
584 return 0;
585}
586
587/**********************************************************************
588 * MDIRefreshMenu
589 */
590LRESULT Win32MDIClientWindow::refreshMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
591{
592 HMENU oldFrameMenu = getParent()->GetMenu();
593
594// FIXME("partially function stub\n");
595
596 return oldFrameMenu;
597}
598/**********************************************************************
599 * MDI_RestoreFrameMenu
600 */
601BOOL Win32MDIClientWindow::restoreFrameMenu(Win32BaseWindow *child)
602{
603 MENUITEMINFOA menuInfo;
604 INT nItems = GetMenuItemCount(getParent()->GetMenu()) - 1;
605 UINT iId = GetMenuItemID(getParent()->GetMenu(),nItems) ;
606
607 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
608 return 0;
609
610 /*
611 * Remove the system menu, If that menu is the icon of the window
612 * as it is in win95, we have to delete the bitmap.
613 */
614 menuInfo.cbSize = sizeof(MENUITEMINFOA);
615 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
616
617 GetMenuItemInfoA(getParent()->GetMenu(),
618 0,
619 TRUE,
620 &menuInfo);
621
622 RemoveMenu(getParent()->GetMenu(),0,MF_BYPOSITION);
623
624//TODO: See augmentframemenu
625#if 0
626 if ((menuInfo.fType & MFT_BITMAP) &&
627 (LOWORD(menuInfo.dwTypeData)!=0) &&
628 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
629 {
630 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
631 }
632#endif
633
634 /* close */
635 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
636
637 /* restore */
638 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
639 /* minimize */
640 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
641
642 DrawMenuBar(getParent()->getWindowHandle());
643
644 return 1;
645}
646
647Win32BaseWindow** Win32MDIClientWindow::buildWindowArray(UINT bwaFlags,PUINT total)
648{
649 Win32BaseWindow **list = NULL,*win32wnd,**pos;
650 UINT skipHidden;
651 DWORD skipFlags;
652
653 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
654 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
655 if (bwaFlags & BWA_SKIPICONIC) skipFlags |= WS_MINIMIZE;
656
657 /* First count the windows */
658 *total = 0;
659 win32wnd = (Win32BaseWindow*)this->getFirstChild();
660 while (win32wnd)
661 {
662 if (!(win32wnd->getStyle() & skipFlags) && (!skipHidden || (win32wnd->getStyle() & WS_VISIBLE)))
663 (*total)++;
664 win32wnd = (Win32BaseWindow*)win32wnd->getNextChild();
665 }
666
667 if (*total)
668 {
669 /* Now build the list of all windows */
670 list = (Win32BaseWindow**)HeapAlloc(GetProcessHeap(),0,sizeof(Win32BaseWindow*)*(*total+1));
671 if (list)
672 {
673 for (win32wnd = (Win32BaseWindow*)this->getFirstChild(),pos = list;win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
674 {
675 if ((win32wnd->getStyle() & skipFlags));
676 else if(!skipHidden || win32wnd->getStyle() & WS_VISIBLE)
677 *pos++ = win32wnd;
678 }
679 *pos = NULL;
680 }
681 }
682
683 return list;
684}
685
686void Win32MDIClientWindow::releaseWindowArray(Win32BaseWindow **wndArray)
687{
688 HeapFree(GetProcessHeap(),0,wndArray);
689}
690
691/**********************************************************************
692 * MDI_CalcDefaultChildPos
693 *
694 * It seems that the default height is about 2/3 of the client rect
695 */
696void Win32MDIClientWindow::calcDefaultChildPos(WORD n,LPPOINT lpPos,INT delta)
697{
698 INT nstagger;
699 RECT rect;
700 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
701 GetSystemMetrics(SM_CYFRAME) - 1;
702
703 getClientRect(&rect);
704 if( rect.bottom - rect.top - delta >= spacing )
705 rect.bottom -= delta;
706
707 nstagger = (rect.bottom - rect.top)/(3 * spacing);
708 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
709 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
710 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
711}
712
713/**********************************************************************
714 * MDICascade
715 */
716BOOL Win32MDIClientWindow::cascade(UINT fuCascade)
717{
718 Win32BaseWindow **list;
719 UINT total = 0;
720
721 if (getMaximizedChild())
722 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
723
724 if (nActiveChildren == 0) return 0;
725
726 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC,&total);
727 if (list)
728 {
729 Win32BaseWindow** heapPtr = list;
730 if (total)
731 {
732 INT delta = 0,n = 0;
733 POINT pos[2];
734
735
736 if (total < nActiveChildren)
737 delta = GetSystemMetrics(SM_CYICONSPACING)+GetSystemMetrics(SM_CYICON);
738
739 // walk the list (backwards) and move windows
740 while (*list) list++;
741 while (list != heapPtr)
742 {
743 list--;
744
745 calcDefaultChildPos(n++,pos,delta);
746 ::SetWindowPos((*list)->getWindowHandle(),0,pos[0].x,pos[0].y,pos[1].x,pos[1].y,SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
747 }
748 }
749 releaseWindowArray(heapPtr);
750 }
751
752 if (total < nActiveChildren)
753 ArrangeIconicWindows(Win32Hwnd);
754
755 return TRUE;
756}
757
758/**********************************************************************
759 * MDITile
760 */
761BOOL Win32MDIClientWindow::tile(UINT fuTile)
762{
763 Win32BaseWindow** list;
764 UINT total = 0;
765
766 if (getMaximizedChild())
767 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
768
769 if (nActiveChildren == 0) return TRUE;
770
771 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
772 ((fuTile & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
773
774 if (list)
775 {
776 Win32BaseWindow** heapPtr = list;
777
778 if (total)
779 {
780 RECT rect;
781 int x, y, xsize, ysize;
782 int rows, columns, r, c, i;
783
784 GetClientRect(Win32Hwnd,&rect);
785 rows = (int) sqrt((double)total);
786 columns = total / rows;
787
788 if( fuTile & MDITILE_HORIZONTAL ) // version >= 3.1
789 {
790 i = rows;
791 rows = columns; // exchange r and c
792 columns = i;
793 }
794
795 if( total != nActiveChildren)
796 {
797 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
798 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
799 }
800
801 ysize = rect.bottom / rows;
802 xsize = rect.right / columns;
803
804 for (x = i = 0, c = 1; c <= columns && *list; c++)
805 {
806 if (c == columns)
807 {
808 rows = total - i;
809 ysize = rect.bottom / rows;
810 }
811
812 y = 0;
813 for (r = 1; r <= rows && *list; r++, i++)
814 {
815 ::SetWindowPos((*list)->getWindowHandle(), 0, x, y, xsize, ysize,
816 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
817 y += ysize;
818 list++;
819 }
820 x += xsize;
821 }
822 }
823 releaseWindowArray(heapPtr);
824 }
825
826 if( total < nActiveChildren ) ArrangeIconicWindows(Win32Hwnd);
827
828 return TRUE;
829}
830
831/* ----------------------- Frame window ---------------------------- */
832
833/**********************************************************************
834 * MDI_AugmentFrameMenu
835 */
836BOOL Win32MDIClientWindow::augmentFrameMenu(Win32MDIChildWindow *child)
837{
838 HMENU hSysPopup = 0,hFrameMenu = ::GetMenu(getParent()->getWindowHandle()),hSysMenu = ::GetSystemMenu(child->getWindowHandle(),FALSE);
839 HBITMAP hSysMenuBitmap = 0;
840
841 if (!hFrameMenu || !hSysMenu)
842 return 0;
843
844 // create a copy of sysmenu popup and insert it into frame menu bar
845
846 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
847 return 0;
848
849 //TRACE("\tgot popup %04x in sysmenu %04x\n",
850 // hSysPopup, child->hSysMenu);
851
852 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
853 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
854 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
855 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
856
857 // In Win 95 look, the system menu is replaced by the child icon
858
859 HICON hIcon = GetClassLongA(child->getWindowHandle(), GCL_HICONSM);
860 if (!hIcon)
861 hIcon = GetClassLongA(child->getWindowHandle(), GCL_HICON);
862 if (hIcon)
863 {
864 HDC hMemDC;
865 HBITMAP hBitmap, hOldBitmap;
866 HBRUSH hBrush;
867 HDC hdc = GetDC(child->getWindowHandle());
868
869 if (hdc)
870 {
871 int cx, cy;
872
873 cx = GetSystemMetrics(SM_CXSMICON);
874 cy = GetSystemMetrics(SM_CYSMICON);
875 hMemDC = CreateCompatibleDC(hdc);
876 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
877 hOldBitmap = SelectObject(hMemDC, hBitmap);
878 SetMapMode(hMemDC, MM_TEXT);
879 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
880 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
881 SelectObject (hMemDC, hOldBitmap);
882 DeleteObject(hBrush);
883 DeleteDC(hMemDC);
884 ReleaseDC(child->getWindowHandle(), hdc);
885 hSysMenuBitmap = hBitmap;
886 }
887 }
888
889 if( !InsertMenuA(hFrameMenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
890 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
891 {
892 //TRACE("not inserted\n");
893 DestroyMenu(hSysPopup);
894 return 0;
895 }
896
897 // The close button is only present in Win 95 look
898
899 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
900 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
901
902 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
903 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
904 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
905 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
906
907 // redraw menu
908 DrawMenuBar(getParent()->getWindowHandle());
909
910 return 1;
911}
912
913/**********************************************************************
914 * MDI_RestoreFrameMenu
915 */
916BOOL Win32MDIClientWindow::restoreFrameMenu(Win32MDIChildWindow *child)
917{
918 MENUITEMINFOA menuInfo;
919 HMENU hFrameMenu = ::GetMenu(getParent()->getWindowHandle());
920 INT nItems = GetMenuItemCount(hFrameMenu) - 1;
921 UINT iId = GetMenuItemID(hFrameMenu,nItems) ;
922
923 //TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
924
925 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
926 return 0;
927
928 /*
929 * Remove the system menu, If that menu is the icon of the window
930 * as it is in win95, we have to delete the bitmap.
931 */
932
933 menuInfo.cbSize = sizeof(MENUITEMINFOA);
934 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
935
936 GetMenuItemInfoA(hFrameMenu,
937 0,
938 TRUE,
939 &menuInfo);
940
941 RemoveMenu(hFrameMenu,0,MF_BYPOSITION);
942
943#if 0 //CB: hBmpClose not (yet) defined
944 if ( (menuInfo.fType & MFT_BITMAP) &&
945 (LOWORD(menuInfo.dwTypeData)!=0) &&
946 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
947 {
948 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
949 }
950#endif
951
952 // close
953 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
954
955 // restore
956 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
957 // minimize
958 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
959
960 DrawMenuBar(getParent()->getWindowHandle());
961
962 return 1;
963}
964
965/***********************************************************************
966 * CalcChildScroll (USER.462)
967 */
968void WINAPI CalcChildScroll(HWND hwnd,WORD scroll)
969{
970 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
971 SCROLLINFO info;
972 RECT childRect, clientRect;
973 INT vmin, vmax, hmin, hmax, vpos, hpos;
974
975 if (!win32wnd) return;
976
977 GetClientRect( hwnd, &clientRect );
978 SetRectEmpty( &childRect );
979
980 for (win32wnd = (Win32BaseWindow*)win32wnd->getFirstChild();win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
981 {
982 if( win32wnd->getStyle() & WS_MAXIMIZE )
983 {
984 ShowScrollBar(hwnd, SB_BOTH, FALSE);
985 return;
986 }
987 UnionRect(&childRect,win32wnd->getWindowRect(),&childRect);
988 }
989 UnionRect( &childRect, &clientRect, &childRect );
990
991 hmin = childRect.left; hmax = childRect.right - clientRect.right;
992 hpos = clientRect.left - childRect.left;
993 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
994 vpos = clientRect.top - childRect.top;
995
996 switch( scroll )
997 {
998 case SB_HORZ:
999 vpos = hpos; vmin = hmin; vmax = hmax;
1000 case SB_VERT:
1001 info.cbSize = sizeof(info);
1002 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1003 info.fMask = SIF_POS | SIF_RANGE;
1004 SetScrollInfo(hwnd, scroll, &info, TRUE);
1005 break;
1006 case SB_BOTH:
1007 {
1008 SCROLLINFO vInfo, hInfo;
1009
1010 vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO);
1011 vInfo.nMin = vmin;
1012 hInfo.nMin = hmin;
1013 vInfo.nMax = vmax;
1014 hInfo.nMax = hmax;
1015 vInfo.nPos = vpos;
1016 hInfo.nPos = hpos;
1017 vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS;
1018
1019 SetScrollInfo(hwnd,SB_VERT,&vInfo,TRUE);
1020 SetScrollInfo(hwnd,SB_HORZ,&hInfo,TRUE);
1021 }
1022 }
1023}
1024
1025/***********************************************************************
1026 * ScrollChildren32 (USER32.448)
1027 */
1028void WINAPI ScrollChildren(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
1029{
1030 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hWnd);
1031 INT newPos = -1;
1032 INT curPos, length, minPos, maxPos, shift;
1033
1034 if (!win32wnd) return;
1035
1036 if (uMsg == WM_HSCROLL)
1037 {
1038 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1039 curPos = GetScrollPos(hWnd,SB_HORZ);
1040 length = win32wnd->getClientWidth()/2;
1041 shift = GetSystemMetrics(SM_CYHSCROLL);
1042 } else if (uMsg == WM_VSCROLL)
1043 {
1044 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1045 curPos = GetScrollPos(hWnd,SB_VERT);
1046 length = win32wnd->getClientHeight()/2;
1047 shift = GetSystemMetrics(SM_CXVSCROLL);
1048 } else return;
1049
1050 switch( wParam )
1051 {
1052 case SB_LINEUP:
1053 newPos = curPos - shift;
1054 break;
1055
1056 case SB_LINEDOWN:
1057 newPos = curPos + shift;
1058 break;
1059
1060 case SB_PAGEUP:
1061 newPos = curPos - length;
1062 break;
1063
1064 case SB_PAGEDOWN:
1065 newPos = curPos + length;
1066 break;
1067
1068 case SB_THUMBPOSITION:
1069 newPos = LOWORD(lParam);
1070 break;
1071
1072 case SB_THUMBTRACK:
1073 return;
1074
1075 case SB_TOP:
1076 newPos = minPos;
1077 break;
1078
1079 case SB_BOTTOM:
1080 newPos = maxPos;
1081 break;
1082
1083 case SB_ENDSCROLL:
1084 CalcChildScroll(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
1085 return;
1086 }
1087
1088 if( newPos > maxPos )
1089 newPos = maxPos;
1090 else
1091 if( newPos < minPos )
1092 newPos = minPos;
1093
1094 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
1095
1096 if( uMsg == WM_VSCROLL )
1097 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
1098 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1099 else
1100 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
1101 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1102}
1103
1104/*****************************************************************************
1105 * Name : WORD WIN32API CascadeWindows
1106 * Purpose : The CascadeWindows function cascades the specified windows or
1107 * the child windows of the specified parent window.
1108 * Parameters: HWND hwndParent handle of parent window
1109 * UINT wHow types of windows not to arrange
1110 * CONST RECT * lpRect rectangle to arrange windows in
1111 * UINT cKids number of windows to arrange
1112 * const HWND FAR * lpKids array of window handles
1113 * Variables :
1114 * Result : If the function succeeds, the return value is the number of windows arranged.
1115 * If the function fails, the return value is zero.
1116 * Remark :
1117 * Status : UNTESTED STUB
1118 *
1119 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1120 *****************************************************************************/
1121WORD WIN32API CascadeWindows(HWND hwndParent,
1122 UINT wHow,
1123 CONST LPRECT lpRect,
1124 UINT cKids,
1125 const HWND *lpKids)
1126{
1127 dprintf(("USER32:CascadeWindows(%08xh,%u,%08xh,%u,%08x) not implemented.\n",
1128 hwndParent,
1129 wHow,
1130 lpRect,
1131 cKids,
1132 lpKids));
1133
1134 return (0);
1135}
1136
1137/*****************************************************************************
1138 * Name : BOOL WIN32API CascadeChildWindows
1139 * Purpose : Unknown
1140 * Parameters: Unknown
1141 * Variables :
1142 * Result :
1143 * Remark :
1144 * Status : UNTESTED UNKNOWN STUB
1145 *
1146 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1147 *****************************************************************************/
1148BOOL WIN32API CascadeChildWindows(DWORD x1,
1149 DWORD x2)
1150{
1151 dprintf(("USER32: CascadeChildWindows(%08xh,%08xh) not implemented.\n",
1152 x1,
1153 x2));
1154
1155 return (FALSE); /* default */
1156}
1157
1158/*****************************************************************************
1159 * Name : WORD WIN32API TileWindows
1160 * Purpose : The TileWindows function tiles the specified windows, or the child
1161 * windows of the specified parent window.
1162 * Parameters: HWND hwndParent handle of parent window
1163 * WORD wFlags types of windows not to arrange
1164 * LPCRECT lpRect rectangle to arrange windows in
1165 * WORD cChildrenb number of windows to arrange
1166 * const HWND *ahwndChildren array of window handles
1167 * Variables :
1168 * Result : If the function succeeds, the return value is the number of
1169 * windows arranged.
1170 * If the function fails, the return value is zero.
1171 * Remark :
1172 * Status : UNTESTED STUB
1173 *
1174 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1175 *****************************************************************************/
1176WORD WIN32API TileWindows(HWND hwndParent,
1177 UINT wFlags,
1178 const LPRECT lpRect,
1179 UINT cChildrenb,
1180 const HWND *ahwndChildren)
1181{
1182 dprintf(("USER32:TileWindows (%08xh,%08xh,%08xh,%08xh,%08x) not implemented.\n",
1183 hwndParent,
1184 wFlags,
1185 lpRect,
1186 cChildrenb,
1187 ahwndChildren));
1188
1189 return (0);
1190}
1191
1192/*****************************************************************************
1193 * Name : BOOL WIN32API TileChildWindows
1194 * Purpose : Unknown
1195 * Parameters: Unknown
1196 * Variables :
1197 * Result :
1198 * Remark :
1199 * Status : UNTESTED UNKNOWN STUB
1200 *
1201 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1202 *****************************************************************************/
1203BOOL WIN32API TileChildWindows(DWORD x1,
1204 DWORD x2)
1205{
1206 dprintf(("USER32: TileChildWindows(%08xh,%08xh) not implemented.\n",
1207 x1,
1208 x2));
1209
1210 return (FALSE); /* default */
1211}
1212
1213/* -------- Miscellaneous service functions ----------
1214 *
1215 * MDI_GetChildByID
1216 */
1217Win32MDIChildWindow *Win32MDIClientWindow::getChildByID(INT id)
1218{
1219 Win32MDIChildWindow *child;
1220
1221 for (child = (Win32MDIChildWindow *)getFirstChild() ; child; child = (Win32MDIChildWindow *)child->getNextChild())
1222 if (child->getWindowId() == id) return child;
1223
1224 return 0;
1225}
1226
1227void Win32MDIClientWindow::postUpdate(WORD recalc)
1228{
1229 if( !(mdiFlags & MDIF_NEEDUPDATE) )
1230 {
1231 mdiFlags |= MDIF_NEEDUPDATE;
1232 PostMessageA(getWindowHandle(), WM_MDICALCCHILDSCROLL, 0, 0);
1233 }
1234 sbRecalc = recalc;
1235}
1236//******************************************************************************
1237//******************************************************************************
1238BOOL MDICLIENT_Register()
1239{
1240 WNDCLASSA wndClass;
1241
1242//SvL: Don't check this now
1243// if (GlobalFindAtomA(MDICLIENTCLASSNAMEA)) return FALSE;
1244
1245 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1246 wndClass.style = CS_GLOBALCLASS;
1247 wndClass.lpfnWndProc = (WNDPROC)MDIClientWndProc;
1248 wndClass.cbClsExtra = 0;
1249 wndClass.cbWndExtra = 0;
1250 wndClass.hCursor = 0;
1251 wndClass.hbrBackground = (HBRUSH)LTGRAY_BRUSH;
1252 wndClass.lpszClassName = MDICLIENTCLASSNAMEA;
1253
1254 return RegisterClassA(&wndClass);
1255}
1256//******************************************************************************
1257//******************************************************************************
1258BOOL MDICLIENT_Unregister()
1259{
1260 if (GlobalFindAtomA(MDICLIENTCLASSNAMEA))
1261 return UnregisterClassA(MDICLIENTCLASSNAMEA,(HINSTANCE)NULL);
1262 else return FALSE;
1263}
1264//******************************************************************************
1265//******************************************************************************
Note: See TracBrowser for help on using the repository browser.