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

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

class changes

File size: 28.7 KB
Line 
1/* $Id: win32wmdiclient.cpp,v 1.10 1999-10-24 22:56:10 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 : maximizedChild(0), activeChild(0), nActiveChildren(0), nTotalCreated(0),
44 frameTitle(NULL), mdiFlags(0), idFirstChild(0), hWindowMenu(0),
45 sbRecalc(0),
46 Win32BaseWindow(OBJTYPE_WINDOW)
47{
48 Init();
49 this->isUnicode = isUnicode;
50 CreateWindowExA(lpCreateStructA, classAtom);
51}
52//******************************************************************************
53//******************************************************************************
54Win32MDIClientWindow::~Win32MDIClientWindow()
55{
56 if(frameTitle)
57 HeapFree(GetProcessHeap(), 0, frameTitle);
58}
59//******************************************************************************
60//******************************************************************************
61BOOL Win32MDIClientWindow::isMDIClient()
62{
63 return TRUE;
64}
65//******************************************************************************
66//******************************************************************************
67LRESULT Win32MDIClientWindow::MDIClientWndProc(UINT message, WPARAM wParam, LPARAM lParam)
68{
69 LPCREATESTRUCTA cs;
70 LPCLIENTCREATESTRUCT ccs;
71 RECT rect;
72 INT nItems;
73 LRESULT retvalue;
74 Win32Window *frameWnd;
75 Win32MDIChildWindow *mdichild;
76
77 frameWnd = (Win32Window *)getParent();
78 if(frameWnd == NULL) {
79 return 0;
80 }
81
82 switch (message)
83 {
84 case WM_CREATE:
85 cs = (LPCREATESTRUCTA)lParam;
86 ccs = (LPCLIENTCREATESTRUCT)cs->lpCreateParams;
87
88 hWindowMenu = ccs->hWindowMenu;
89 idFirstChild = ccs->idFirstChild;
90
91 maximizedChild = 0;
92 activeChild = 0;
93 nActiveChildren = 0;
94 nTotalCreated = 0;
95 frameTitle = NULL;
96 mdiFlags = 0;
97
98 setStyle(getStyle() | WS_CLIPCHILDREN);
99
100 updateFrameText(MDI_NOFRAMEREPAINT, getParent()->getWindowNameA());
101
102 AppendMenuA( hWindowMenu, MF_SEPARATOR, 0, NULL );
103
104 setClientRect(frameWnd->getClientRect());
105
106 dprintf(("MDIClient created - hwnd = %04x, idFirst = %u\n", getWindowHandle(), idFirstChild ));
107
108 retvalue = 0;
109 goto END;
110
111 case WM_DESTROY:
112 if( maximizedChild ) restoreFrameMenu(getParent());
113
114 if((nItems = GetMenuItemCount(hWindowMenu)) > 0)
115 {
116 idFirstChild = nItems - 1;
117 nActiveChildren++; /* to delete a separator */
118 while( nActiveChildren-- )
119 DeleteMenu(hWindowMenu,MF_BYPOSITION,idFirstChild--);
120 }
121 retvalue = 0;
122 goto END;
123
124 case WM_MDIACTIVATE:
125 if( activeChild && activeChild->getWindowHandle() != (HWND)wParam )
126 {
127 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
128 if(mdichild) {
129 mdichild->SetWindowPos(0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
130 }
131 }
132 retvalue = 0;
133 goto END;
134
135#if 0
136 case WM_MDICASCADE:
137 retvalue = MDICascade(w, ci);
138 goto END;
139#endif
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#if 0
164 case WM_MDIICONARRANGE:
165 mdiFlags |= MDIF_NEEDUPDATE;
166 ArrangeIconicWindows(hwnd);
167 sbRecalc = SB_BOTH+1;
168 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
169 retvalue = 0;
170 goto END;
171#endif
172
173 case WM_MDIMAXIMIZE:
174 ::ShowWindow( (HWND)wParam, SW_MAXIMIZE );
175 retvalue = 0;
176 goto END;
177
178 case WM_MDINEXT: /* lParam != 0 means previous window */
179 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
180 if(mdichild) {
181 switchActiveChild(mdichild, (lParam)? FALSE : TRUE );
182 }
183 break;
184
185 case WM_MDIRESTORE:
186 ::SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
187 retvalue = 0;
188 goto END;
189 case WM_MDISETMENU:
190 retvalue = setMDIMenu((HMENU)wParam, (HMENU)lParam );
191 goto END;
192
193 case WM_MDIREFRESHMENU:
194 retvalue = refreshMDIMenu((HMENU)wParam, (HMENU)lParam );
195 goto END;
196
197#if 0
198 case WM_MDITILE:
199 mdiFlags |= MDIF_NEEDUPDATE;
200 ShowScrollBar(hwnd,SB_BOTH,FALSE);
201 MDITile(w, ci, wParam);
202 mdiFlags &= ~MDIF_NEEDUPDATE;
203 retvalue = 0;
204 goto END;
205
206 case WM_VSCROLL:
207 case WM_HSCROLL:
208 mdiFlags |= MDIF_NEEDUPDATE;
209 ScrollChildren(hwnd, message, wParam, lParam);
210 mdiFlags &= ~MDIF_NEEDUPDATE;
211 retvalue = 0;
212 goto END;
213#endif
214
215 case WM_SETFOCUS:
216 if( activeChild )
217 {
218 if( !(activeChild->getStyle() & WS_MINIMIZE) )
219 ::SetFocus(activeChild->getWindowHandle());
220 }
221 retvalue = 0;
222 goto END;
223
224 case WM_NCACTIVATE:
225 if( activeChild )
226 activeChild->SendMessageA(message, wParam, lParam);
227 break;
228
229 case WM_PARENTNOTIFY:
230 if (LOWORD(wParam) == WM_LBUTTONDOWN)
231 {
232 POINTS pt = MAKEPOINTS(lParam);
233 POINT point;
234
235 point.x = pt.x;
236 point.y = pt.y;
237
238 HWND child = ChildWindowFromPoint(getWindowHandle(), point);
239
240 if( child && child != getWindowHandle() && (!activeChild || activeChild->getWindowHandle() != child) )
241 ::SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
242 }
243 retvalue = 0;
244 goto END;
245
246 case WM_SIZE:
247 if( maximizedChild && maximizedChild->IsWindow() )
248 {
249 RECT rect;
250
251 rect.left = 0;
252 rect.top = 0;
253 rect.right = LOWORD(lParam);
254 rect.bottom = HIWORD(lParam);
255
256 AdjustWindowRectEx(&rect, maximizedChild->getStyle(), 0, maximizedChild->getExStyle());
257 ::MoveWindow(maximizedChild->getWindowHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 1);
258 }
259 else postUpdate(SB_BOTH+1);
260 break;
261
262#if 0
263 case WM_MDICALCCHILDSCROLL:
264 if( (mdiFlags & MDIF_NEEDUPDATE) && sbRecalc )
265 {
266 CalcChildScroll(hwnd, sbRecalc-1);
267 sbRecalc = 0;
268 mdiFlags &= ~MDIF_NEEDUPDATE;
269 }
270 retvalue = 0;
271 goto END;
272#endif
273 }
274 retvalue = DefWindowProcA(message, wParam, lParam );
275END:
276 return retvalue;
277}
278/**********************************************************************
279 * MDIClientWndProc
280 *
281 * This function handles all MDI requests.
282 */
283LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
284 LPARAM lParam )
285{
286 Win32MDIClientWindow *window;
287
288 window = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwnd);
289 if(!window) {
290 dprintf(("MDIClientWndProc, window %x not found", hwnd));
291 return 0;
292 }
293 return window->MDIClientWndProc(message, wParam, lParam);
294}
295/**********************************************************************
296 * MDI_GetWindow
297 *
298 * returns "activateable" child different from the current or zero
299 */
300Win32MDIChildWindow *Win32MDIClientWindow::getWindow(Win32MDIChildWindow *actchild, BOOL bNext,
301 DWORD dwStyleMask)
302{
303 Win32MDIChildWindow *lastchild = 0, *curchild;
304
305 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
306
307 if( !actchild ) actchild = getActiveChild();
308 if( !actchild) return 0;
309
310 for ( curchild = (Win32MDIChildWindow *)actchild->getNextChild(); ; curchild = (Win32MDIChildWindow *)curchild->getNextChild())
311 {
312 if (!curchild ) curchild = (Win32MDIChildWindow *)getFirstChild();
313
314 if ( curchild == actchild ) break; /* went full circle */
315
316 if (!curchild->getOwner() && (curchild->getStyle() & dwStyleMask) == WS_VISIBLE )
317 {
318 lastchild = curchild;
319 if ( bNext ) break;
320 }
321 }
322 return lastchild;
323}
324/**********************************************************************
325 * MDI_ChildActivate
326 *
327 * Note: hWndChild is NULL when last child is being destroyed
328 */
329LONG Win32MDIClientWindow::childActivate(Win32MDIChildWindow *child)
330{
331 BOOL isActiveFrameWnd = 0;
332 LONG retvalue;
333 Win32MDIChildWindow *prevActive = activeChild;
334
335 if( child && child->getStyle() & WS_DISABLED )
336 {
337 return 0;
338 }
339
340 if( GetActiveWindow() == getParent()->getWindowHandle())
341 isActiveFrameWnd = TRUE;
342
343 /* deactivate prev. active child */
344 if( prevActive )
345 {
346 prevActive->setStyle(prevActive->getStyle() | WS_SYSMENU);
347 prevActive->SendMessageA( WM_NCACTIVATE, FALSE, 0L );
348 prevActive->SendMessageA( WM_MDIACTIVATE, (WPARAM)prevActive->getWindowHandle(), (LPARAM)(child) ? child->getWindowHandle() : 0);
349
350 /* uncheck menu item */
351 if( getMDIMenu() )
352 CheckMenuItem(getMDIMenu(), prevActive->getWindowId(), 0);
353 }
354
355 /* set appearance */
356 if( maximizedChild)
357 {
358 if( maximizedChild != child) {
359 if( child ) {
360 activeChild = child;
361 child->ShowWindow(SW_SHOWMAXIMIZED);
362 }
363 else
364 if(activeChild) activeChild->ShowWindow( SW_SHOWNORMAL );
365 }
366 }
367
368 dprintf(("childActivate: %x %x", this, child->getWindowHandle()));
369 activeChild = child;
370
371 /* check if we have any children left */
372 if( !activeChild )
373 {
374 if( isActiveFrameWnd )
375 SetFocus(getWindowHandle());
376
377 return 0;
378 }
379
380 /* check menu item */
381 if( getMDIMenu() )
382 CheckMenuItem(getMDIMenu(), child->getWindowId(), MF_CHECKED);
383
384 /* bring active child to the top */
385 child->SetWindowPos( 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
386
387 if( isActiveFrameWnd )
388 {
389 child->SendMessageA( WM_NCACTIVATE, TRUE, 0L);
390 if( GetFocus() == getWindowHandle())
391 SendMessageA( WM_SETFOCUS, (WPARAM)getWindowHandle(), 0L );
392 else
393 SetFocus( getWindowHandle() );
394 }
395
396 /* @@@PH prevActive may be NULL actually ?! */
397 child->SendMessageA( WM_MDIACTIVATE,
398 prevActive ? (WPARAM)prevActive->getWindowHandle() : 0,
399 child->getWindowHandle());
400 return TRUE;
401}
402/**********************************************************************
403 * MDI_SwitchActiveChild
404 *
405 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
406 * being activated
407 */
408void Win32MDIClientWindow::switchActiveChild(Win32MDIChildWindow *nextActiveChild, BOOL bNextWindow )
409{
410 Win32MDIChildWindow *prevActiveChild = 0;
411
412 if ( !nextActiveChild) return; /* no window to switch to */
413
414 prevActiveChild = getActiveChild();
415
416 if ( prevActiveChild != nextActiveChild)
417 {
418 BOOL bOptimize = 0;
419
420 if( getMaximizedChild() )
421 {
422 bOptimize = 1;
423 nextActiveChild->setStyle(nextActiveChild->getStyle()& ~WS_VISIBLE);
424 }
425
426 nextActiveChild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
427
428 if( bNextWindow && prevActiveChild )
429 prevActiveChild->SetWindowPos(HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
430
431 if( bOptimize )
432 ShowWindow(SW_SHOW );
433 }
434}
435
436
437/**********************************************************************
438 * MDIDestroyChild
439 */
440LRESULT Win32MDIClientWindow::destroyChild(Win32MDIChildWindow *child, BOOL flagDestroy )
441{
442 if( child == getActiveChild())
443 {
444 switchActiveChild(child, TRUE);
445
446 if( child == getActiveChild() )
447 {
448 ShowWindow(SW_HIDE);
449 if( child == getMaximizedChild() )
450 {
451 restoreFrameMenu(child);
452 setMaximizedChild(NULL);
453 updateFrameText(TRUE,NULL);
454 }
455 childActivate(0);
456 }
457 }
458 child->menuDeleteItem();
459
460 decNrActiveChildren();
461
462 dprintf(("child destroyed - %04x\n", child->getWindowHandle()));
463
464 if (flagDestroy)
465 {
466// MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
467 ::DestroyWindow(child->getWindowHandle());
468 }
469
470 return 0;
471}
472/**********************************************************************
473 * MDI_UpdateFrameText
474 *
475 * used when child window is maximized/restored
476 *
477 * Note: lpTitle can be NULL
478 */
479void Win32MDIClientWindow::updateFrameText(BOOL repaint, LPCSTR lpTitle )
480{
481 char lpBuffer[MDI_MAXTITLELENGTH+1];
482
483 /* store new "default" title if lpTitle is not NULL */
484 if (lpTitle)
485 {
486 if (frameTitle) HeapFree( GetProcessHeap(), 0, frameTitle );
487 frameTitle = HEAP_strdupA( GetProcessHeap(), 0, lpTitle );
488 }
489
490 if (frameTitle)
491 {
492 Win32MDIChildWindow *childWnd = getMaximizedChild();
493
494 if( childWnd && childWnd->getWindowNameA() )
495 {
496 /* combine frame title and child title if possible */
497
498 LPCSTR lpBracket = " - [";
499 int i_frame_text_length = strlen(frameTitle);
500 int i_child_text_length = strlen(childWnd->getWindowNameA());
501
502 lstrcpynA( lpBuffer, frameTitle, MDI_MAXTITLELENGTH);
503
504 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
505 {
506 strcat( lpBuffer, lpBracket );
507
508 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
509 {
510 strcat( lpBuffer, childWnd->getWindowNameA());
511 strcat( lpBuffer, "]" );
512 }
513 else
514 {
515 lstrcpynA(lpBuffer + i_frame_text_length + 4,
516 childWnd->getWindowNameA(), MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
517 strcat( lpBuffer, "]" );
518 }
519 }
520 }
521 else
522 {
523 strncpy(lpBuffer, frameTitle, MDI_MAXTITLELENGTH );
524 lpBuffer[MDI_MAXTITLELENGTH]='\0';
525 }
526 }
527 else
528 lpBuffer[0] = '\0';
529
530 getParent()->SetWindowTextA(lpBuffer);
531 if( repaint == MDI_REPAINTFRAME)
532 getParent()->SetWindowPos(0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
533}
534/**********************************************************************
535 * MDISetMenu
536 */
537LRESULT Win32MDIClientWindow::setMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
538{
539 HWND hwndFrame = ::GetParent(getWindowHandle());
540 HMENU oldFrameMenu = ::GetMenu(hwndFrame);
541
542 if( maximizedChild && hmenuFrame && hmenuFrame!=oldFrameMenu )
543 restoreFrameMenu(maximizedChild);
544
545 if( hmenuWindow && hmenuWindow != hWindowMenu )
546 {
547 /* delete menu items from ci->hWindowMenu
548 * and add them to hmenuWindow */
549
550 INT i = GetMenuItemCount(hWindowMenu) - 1;
551 INT pos = GetMenuItemCount(hmenuWindow) + 1;
552
553 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
554
555 if( nActiveChildren )
556 {
557 INT j = i - nActiveChildren + 1;
558 char buffer[100];
559 UINT id,state;
560
561 for( ; i >= j ; i-- )
562 {
563 id = GetMenuItemID(hWindowMenu,i );
564 state = GetMenuState(hWindowMenu,i,MF_BYPOSITION);
565
566 GetMenuStringA(hWindowMenu, i, buffer, 100, MF_BYPOSITION);
567
568 DeleteMenu(hWindowMenu, i , MF_BYPOSITION);
569 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
570 id, buffer);
571 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
572 }
573 }
574
575 /* remove separator */
576 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
577
578 hWindowMenu = hmenuWindow;
579 }
580
581 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
582 {
583 ::SetMenu(hwndFrame, hmenuFrame);
584#if 0
585 if( ci->hwndChildMaximized )
586 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
587#endif
588 return oldFrameMenu;
589 }
590 return 0;
591}
592
593/**********************************************************************
594 * MDIRefreshMenu
595 */
596LRESULT Win32MDIClientWindow::refreshMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
597{
598 HMENU oldFrameMenu = getParent()->GetMenu();
599
600// FIXME("partially function stub\n");
601
602 return oldFrameMenu;
603}
604/**********************************************************************
605 * MDI_RestoreFrameMenu
606 */
607BOOL Win32MDIClientWindow::restoreFrameMenu(Win32BaseWindow *child)
608{
609 MENUITEMINFOA menuInfo;
610 INT nItems = GetMenuItemCount(getParent()->GetMenu()) - 1;
611 UINT iId = GetMenuItemID(getParent()->GetMenu(),nItems) ;
612
613 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
614 return 0;
615
616 /*
617 * Remove the system menu, If that menu is the icon of the window
618 * as it is in win95, we have to delete the bitmap.
619 */
620 menuInfo.cbSize = sizeof(MENUITEMINFOA);
621 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
622
623 GetMenuItemInfoA(getParent()->GetMenu(),
624 0,
625 TRUE,
626 &menuInfo);
627
628 RemoveMenu(getParent()->GetMenu(),0,MF_BYPOSITION);
629
630//TODO: See augmentframemenu
631#if 0
632 if ((menuInfo.fType & MFT_BITMAP) &&
633 (LOWORD(menuInfo.dwTypeData)!=0) &&
634 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
635 {
636 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
637 }
638#endif
639
640 /* close */
641 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
642
643 /* restore */
644 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
645 /* minimize */
646 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
647
648 DrawMenuBar(getParent()->getWindowHandle());
649
650 return 1;
651}
652
653#if 0
654/**********************************************************************
655 * MDICascade
656 */
657LONG Win32MDIClientWindow::cascade()
658{
659 WND** ppWnd;
660 UINT total;
661
662 if (getMaximizedChild())
663 SendMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
664
665 if (nActiveChildren == 0) return 0;
666
667 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
668 BWA_SKIPICONIC, &total)))
669 {
670 WND** heapPtr = ppWnd;
671 if( total )
672 {
673 INT delta = 0, n = 0;
674 POINT pos[2];
675 if( total < ci->nActiveChildren )
676 delta = GetSystemMetrics(SM_CYICONSPACING) +
677 GetSystemMetrics(SM_CYICON);
678
679 /* walk the list (backwards) and move windows */
680 while (*ppWnd) ppWnd++;
681 while (ppWnd != heapPtr)
682 {
683 ppWnd--;
684
685 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
686 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
687 pos[1].x, pos[1].y,
688 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
689 }
690 }
691 WIN_ReleaseWinArray(heapPtr);
692 }
693
694 if( total < ci->nActiveChildren )
695 ArrangeIconicWindows( clientWnd->hwndSelf );
696
697 return 0;
698}
699
700/**********************************************************************
701 * MDITile
702 */
703void Win32MDIClientWindow::MDITile(WPARAM wParam )
704{
705 WND** ppWnd;
706 UINT total = 0;
707
708 if (getMaximizedChild())
709 SendMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
710
711 if (nActiveChildren == 0) return;
712
713 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
714 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
715
716 TRACE("%u windows to tile\n", total);
717
718 if( ppWnd )
719 {
720 WND** heapPtr = ppWnd;
721
722 if( total )
723 {
724 RECT rect;
725 int x, y, xsize, ysize;
726 int rows, columns, r, c, i;
727
728 GetClientRect(wndClient->hwndSelf,&rect);
729 rows = (int) sqrt((double)total);
730 columns = total / rows;
731
732 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
733 {
734 i = rows;
735 rows = columns; /* exchange r and c */
736 columns = i;
737 }
738
739 if( total != ci->nActiveChildren)
740 {
741 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
742 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
743 }
744
745 ysize = rect.bottom / rows;
746 xsize = rect.right / columns;
747
748 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
749 {
750 if (c == columns)
751 {
752 rows = total - i;
753 ysize = rect.bottom / rows;
754 }
755
756 y = 0;
757 for (r = 1; r <= rows && *ppWnd; r++, i++)
758 {
759 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
760 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
761 y += ysize;
762 ppWnd++;
763 }
764 x += xsize;
765 }
766 }
767 WIN_ReleaseWinArray(heapPtr);
768 }
769
770 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
771}
772
773/* ----------------------- Frame window ---------------------------- */
774
775/**********************************************************************
776 * MDI_AugmentFrameMenu
777 */
778BOOL Win32MDIClientWindow::augmentFrameMenu(HWND hChild )
779{
780 WND* child = WIN_FindWndPtr(hChild);
781 HMENU hSysPopup = 0;
782 HBITMAP hSysMenuBitmap = 0;
783
784 if( !frame->wIDmenu || !child->hSysMenu )
785 {
786 WIN_ReleaseWndPtr(child);
787 return 0;
788 }
789 WIN_ReleaseWndPtr(child);
790
791 /* create a copy of sysmenu popup and insert it into frame menu bar */
792
793 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
794 return 0;
795
796 TRACE("\tgot popup %04x in sysmenu %04x\n",
797 hSysPopup, child->hSysMenu);
798
799 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
800 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
801 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
802 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
803
804 /* In Win 95 look, the system menu is replaced by the child icon */
805
806 if(TWEAK_WineLook > WIN31_LOOK)
807 {
808 HICON hIcon = GetClassLongA(hChild, GCL_HICONSM);
809 if (!hIcon)
810 hIcon = GetClassLongA(hChild, GCL_HICON);
811 if (hIcon)
812 {
813 HDC hMemDC;
814 HBITMAP hBitmap, hOldBitmap;
815 HBRUSH hBrush;
816 HDC hdc = GetDC(hChild);
817
818 if (hdc)
819 {
820 int cx, cy;
821 cx = GetSystemMetrics(SM_CXSMICON);
822 cy = GetSystemMetrics(SM_CYSMICON);
823 hMemDC = CreateCompatibleDC(hdc);
824 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
825 hOldBitmap = SelectObject(hMemDC, hBitmap);
826 SetMapMode(hMemDC, MM_TEXT);
827 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
828 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
829 SelectObject (hMemDC, hOldBitmap);
830 DeleteObject(hBrush);
831 DeleteDC(hMemDC);
832 ReleaseDC(hChild, hdc);
833 hSysMenuBitmap = hBitmap;
834 }
835 }
836 }
837 else
838 hSysMenuBitmap = hBmpClose;
839
840 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
841 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
842 {
843 TRACE("not inserted\n");
844 DestroyMenu(hSysPopup);
845 return 0;
846 }
847
848 /* The close button is only present in Win 95 look */
849 if(TWEAK_WineLook > WIN31_LOOK)
850 {
851 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
852 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
853 }
854
855 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
856 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
857 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
858 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
859
860 /* redraw menu */
861 DrawMenuBar(frame->hwndSelf);
862
863 return 1;
864}
865
866/**********************************************************************
867 * MDI_RestoreFrameMenu
868 */
869static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
870{
871 MENUITEMINFOA menuInfo;
872 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
873 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
874
875 TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
876
877 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
878 return 0;
879
880 /*
881 * Remove the system menu, If that menu is the icon of the window
882 * as it is in win95, we have to delete the bitmap.
883 */
884 menuInfo.cbSize = sizeof(MENUITEMINFOA);
885 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
886
887 GetMenuItemInfoA(frameWnd->wIDmenu,
888 0,
889 TRUE,
890 &menuInfo);
891
892 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
893
894 if ( (menuInfo.fType & MFT_BITMAP) &&
895 (LOWORD(menuInfo.dwTypeData)!=0) &&
896 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
897 {
898 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
899 }
900
901 if(TWEAK_WineLook > WIN31_LOOK)
902 {
903 /* close */
904 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
905 }
906 /* restore */
907 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
908 /* minimize */
909 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
910
911 DrawMenuBar(frameWnd->hwndSelf);
912
913 return 1;
914}
915#endif
916/* -------- Miscellaneous service functions ----------
917 *
918 * MDI_GetChildByID
919 */
920Win32MDIChildWindow *Win32MDIClientWindow::getChildByID(INT id)
921{
922 Win32MDIChildWindow *child;
923
924 for (child = (Win32MDIChildWindow *)getFirstChild() ; child; child = (Win32MDIChildWindow *)child->getNextChild())
925 if (child->getWindowId() == id) return child;
926
927 return 0;
928}
929
930void Win32MDIClientWindow::postUpdate(WORD recalc)
931{
932 if( !(mdiFlags & MDIF_NEEDUPDATE) )
933 {
934 mdiFlags |= MDIF_NEEDUPDATE;
935 PostMessageA(WM_MDICALCCHILDSCROLL, 0, 0);
936 }
937 sbRecalc = recalc;
938}
939//******************************************************************************
940//******************************************************************************
941BOOL MDICLIENT_Register()
942{
943 WNDCLASSA wndClass;
944
945//SvL: Don't check this now
946// if (GlobalFindAtomA(MDICLIENTCLASSNAMEA)) return FALSE;
947
948 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
949 wndClass.style = CS_GLOBALCLASS;
950 wndClass.lpfnWndProc = (WNDPROC)MDIClientWndProc;
951 wndClass.cbClsExtra = 0;
952 wndClass.cbWndExtra = 0;
953 wndClass.hCursor = 0;
954 wndClass.hbrBackground = (HBRUSH)LTGRAY_BRUSH;
955 wndClass.lpszClassName = MDICLIENTCLASSNAMEA;
956
957 return RegisterClassA(&wndClass);
958}
959//******************************************************************************
960//******************************************************************************
961BOOL MDICLIENT_Unregister()
962{
963 if (GlobalFindAtomA(MDICLIENTCLASSNAMEA))
964 return UnregisterClassA(MDICLIENTCLASSNAMEA,(HINSTANCE)NULL);
965 else return FALSE;
966}
967//******************************************************************************
968//******************************************************************************
Note: See TracBrowser for help on using the repository browser.