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

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

sendmessage + hook updates + misc fixes

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