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

Last change on this file since 2114 was 2114, checked in by cbratschi, 26 years ago

MDI fixes, ChildWindowFromPointEx

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