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

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

EB's unicode changes + seticon + mdi fixes

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