3 * Copyright 1994, Bob Amstadt
4 * 1995,1996 Alex Korobka
6 * This file contains routines to support MDI features.
8 * Notes: Fairly complete implementation. Any volunteers for
9 * "More windows..." stuff?
11 * Also, Excel and WinWord do _not_ use MDI so if you're trying
12 * to fix them look elsewhere.
23 #include "nonclient.h"
28 #include "stackframe.h"
30 #include "sysmetrics.h"
34 #define MDIS_ALLCHILDSTYLES 0x1
36 static HBITMAP hBmpClose
= 0;
37 static HBITMAP hBmpRestore
= 0;
39 DWORD
SCROLL_SetNCSbState(WND
*,int,int,int,int,int,int);
41 /* ----------------- declarations ----------------- */
42 void MDI_UpdateFrameText(WND
*, HWND
, BOOL
, LPCSTR
);
43 BOOL
MDI_AugmentFrameMenu(MDICLIENTINFO
*, WND
*, HWND
);
44 BOOL
MDI_RestoreFrameMenu(WND
*, HWND
);
46 void ScrollChildren(HWND
, UINT
, WPARAM
, LPARAM
);
47 void CalcChildScroll(HWND
, WORD
);
49 static LONG
MDI_ChildActivate(WND
* ,HWND
);
51 /* -------- Miscellaneous service functions ----------
56 static HWND
MDI_GetChildByID(WND
* wndPtr
,int id
)
58 for (wndPtr
= wndPtr
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
59 if (wndPtr
->wIDmenu
== id
) return wndPtr
->hwndSelf
;
63 static void MDI_PostUpdate(HWND hwnd
, MDICLIENTINFO
* ci
, WORD recalc
)
65 if( !ci
->sbNeedUpdate
)
67 ci
->sbNeedUpdate
= TRUE
;
68 PostMessage( hwnd
, WM_MDICALCCHILDSCROLL
, 0, 0);
70 ci
->sbRecalc
= recalc
;
73 /**********************************************************************
76 #ifdef SUPERFLUOUS_FUNCTIONS
77 static BOOL
MDI_MenuAppendItem(WND
*clientWnd
, HWND hWndChild
)
80 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
81 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
82 int n
= sprintf(buffer
, "%d ",
83 clientInfo
->nActiveChildren
);
85 if( !clientInfo
->hWindowMenu
) return 0;
87 if (wndPtr
->text
) strncpy(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
- 1);
88 return AppendMenu32A( clientInfo
->hWindowMenu
, MF_STRING
,
89 wndPtr
->wIDmenu
, buffer
);
93 /**********************************************************************
96 static BOOL
MDI_MenuModifyItem(WND
* clientWnd
, HWND hWndChild
)
99 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
100 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
101 UINT n
= sprintf(buffer
, "%d ",
102 wndPtr
->wIDmenu
- clientInfo
->idFirstChild
+ 1);
105 if( !clientInfo
->hWindowMenu
) return 0;
107 if (wndPtr
->text
) lstrcpyn(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
109 n
= GetMenuState(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
,MF_BYCOMMAND
);
110 bRet
= ModifyMenu32A(clientInfo
->hWindowMenu
, wndPtr
->wIDmenu
,
111 MF_BYCOMMAND
| MF_STRING
, wndPtr
->wIDmenu
, buffer
);
112 CheckMenuItem(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
, n
& MF_CHECKED
);
116 /**********************************************************************
119 static BOOL
MDI_MenuDeleteItem(WND
* clientWnd
, HWND hWndChild
)
122 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
123 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
126 if( !clientInfo
->nActiveChildren
||
127 !clientInfo
->hWindowMenu
) return 0;
129 id
= wndPtr
->wIDmenu
;
130 DeleteMenu(clientInfo
->hWindowMenu
,id
,MF_BYCOMMAND
);
132 /* walk the rest of MDI children to prevent gaps in the id
133 * sequence and in the menu child list
136 for( index
= id
+1; index
<= clientInfo
->nActiveChildren
+
137 clientInfo
->idFirstChild
; index
++ )
139 wndPtr
= WIN_FindWndPtr(MDI_GetChildByID(clientWnd
,index
));
142 dprintf_mdi(stddeb
,"MDIMenuDeleteItem: no window for id=%i\n",index
);
149 n
= sprintf(buffer
, "%d ",index
- clientInfo
->idFirstChild
);
151 lstrcpyn(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
154 ModifyMenu32A(clientInfo
->hWindowMenu
,index
,MF_BYCOMMAND
| MF_STRING
,
155 index
- 1 , buffer
);
160 /**********************************************************************
163 * returns "activateable" child or zero
165 HWND
MDI_GetWindow(WND
*clientWnd
, HWND hWnd
, WORD wTo
)
167 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
168 WND
*wndPtr
, *pWnd
, *pWndLast
;
170 if( !hWnd
) hWnd
= clientInfo
->hwndActiveChild
;
172 if( !(wndPtr
= WIN_FindWndPtr(hWnd
)) ) return 0;
179 if (!pWnd
) pWnd
= wndPtr
->parent
->child
;
180 if (pWnd
== wndPtr
) /* not found */
182 if (!wTo
|| !pWndLast
) return 0;
186 /* we are not interested in owned popups */
188 (pWnd
->dwStyle
& WS_VISIBLE
) &&
189 !(pWnd
->dwStyle
& WS_DISABLED
)) /* found one */
195 return pWndLast
? pWndLast
->hwndSelf
: 0;
198 /**********************************************************************
199 * MDI_CalcDefaultChildPos
201 * It seems that default height is 2/3 of client rect
203 void MDI_CalcDefaultChildPos(WND
* w
, WORD n
, LPPOINT16 lpPos
, INT delta
)
205 RECT16 rect
= w
->rectClient
;
206 INT spacing
= GetSystemMetrics(SM_CYCAPTION
) + GetSystemMetrics(SM_CYFRAME
) - 1;
209 if( rect
.bottom
- rect
.top
- delta
>= spacing
)
210 rect
.bottom
-= delta
;
212 nstagger
= (rect
.bottom
- rect
.top
)/(3*spacing
);
213 lpPos
[1].x
= (rect
.right
- rect
.left
- nstagger
*spacing
);
214 lpPos
[1].y
= (rect
.bottom
- rect
.top
- nstagger
*spacing
);
215 lpPos
[0].x
= lpPos
[0].y
= spacing
*(n
%(nstagger
+1));
218 /**********************************************************************
221 HMENU
MDISetMenu(HWND hwnd
, BOOL fRefresh
, HMENU hmenuFrame
, HMENU hmenuWindow
)
223 WND
*w
= WIN_FindWndPtr(hwnd
);
226 dprintf_mdi(stddeb
, "WM_MDISETMENU: %04x %04x %04x %04x\n",
227 hwnd
, fRefresh
, hmenuFrame
, hmenuWindow
);
229 ci
= (MDICLIENTINFO
*) w
->wExtra
;
233 HWND hwndFrame
= GetParent(hwnd
);
234 HMENU oldFrameMenu
= GetMenu(hwndFrame
);
236 if( ci
->hwndChildMaximized
&& hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
237 MDI_RestoreFrameMenu(w
->parent
, ci
->hwndChildMaximized
);
239 if( hmenuWindow
&& hmenuWindow
!=ci
->hWindowMenu
)
241 /* delete menu items from ci->hWindowMenu
242 * and add them to hmenuWindow */
244 INT i
= GetMenuItemCount(ci
->hWindowMenu
) - 1;
245 INT pos
= GetMenuItemCount(hmenuWindow
) + 1;
247 AppendMenu32A( hmenuWindow
, MF_SEPARATOR
, 0, NULL
);
249 if( ci
->nActiveChildren
)
251 INT j
= i
- ci
->nActiveChildren
+ 1;
255 for( ; i
>= j
; i
-- )
257 id
= GetMenuItemID(ci
->hWindowMenu
,i
);
258 state
= GetMenuState(ci
->hWindowMenu
,i
,MF_BYPOSITION
);
260 GetMenuString(ci
->hWindowMenu
, i
, buffer
, 100, MF_BYPOSITION
);
262 DeleteMenu(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
263 InsertMenu32A(hmenuWindow
, pos
, MF_BYPOSITION
| MF_STRING
,
265 CheckMenuItem(hmenuWindow
,pos
, MF_BYPOSITION
| (state
& MF_CHECKED
));
269 /* remove separator */
270 DeleteMenu(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
272 ci
->hWindowMenu
= hmenuWindow
;
275 if( hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
277 SetMenu(hwndFrame
, hmenuFrame
);
278 if( ci
->hwndChildMaximized
)
279 MDI_AugmentFrameMenu(ci
, w
->parent
, ci
->hwndChildMaximized
);
287 /**********************************************************************
290 WORD
MDIIconArrange(HWND parent
)
292 return ArrangeIconicWindows(parent
); /* Any reason why the */
293 /* existing icon arrange */
294 /* can't be used here? */
299 /* ------------------ MDI child window functions ---------------------- */
302 /**********************************************************************
305 HWND
MDICreateChild(WND
*w
, MDICLIENTINFO
*ci
, HWND parent
, LPARAM lParam
)
308 MDICREATESTRUCT
*cs
= (MDICREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
309 DWORD style
= cs
->style
| (WS_CHILD
| WS_CLIPSIBLINGS
);
310 HWND hwnd
, hwndMax
= 0;
311 WORD wIDmenu
= ci
->idFirstChild
+ ci
->nActiveChildren
;
312 char lpstrDef
[]="junk!";
315 * Create child window
319 dprintf_mdi(stdnimp
,"MDICreateChild: origin %i,%i - dim %i,%i, style %08x\n",
320 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, (unsigned)cs
->style
);
321 /* calculate placement */
322 MDI_CalcDefaultChildPos(w
, ci
->nTotalCreated
++, pos
, 0);
324 if( cs
->cx
== CW_USEDEFAULT16
|| !cs
->cx
)
326 if( cs
->cy
== CW_USEDEFAULT16
|| !cs
->cy
)
329 if( cs
->x
== CW_USEDEFAULT16
)
335 /* restore current maximized child */
336 if( style
& WS_VISIBLE
&& ci
->hwndChildMaximized
)
338 if( style
& WS_MAXIMIZE
)
339 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, FALSE
, 0L );
340 hwndMax
= ci
->hwndChildMaximized
;
341 ShowWindow( hwndMax
, SW_SHOWNOACTIVATE
);
342 if( style
& WS_MAXIMIZE
)
343 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, TRUE
, 0L );
346 /* this menu is needed to set a check mark in MDI_ChildActivate */
347 AppendMenu32A(ci
->hWindowMenu
,MF_STRING
,wIDmenu
, lpstrDef
);
349 ci
->nActiveChildren
++;
351 /* fix window style */
352 if( !(w
->dwStyle
& MDIS_ALLCHILDSTYLES
) )
354 style
&= (WS_CHILD
| WS_CLIPSIBLINGS
| WS_MINIMIZE
| WS_MAXIMIZE
|
355 WS_CLIPCHILDREN
| WS_DISABLED
| WS_VSCROLL
| WS_HSCROLL
);
356 style
|= (WS_VISIBLE
| WS_OVERLAPPEDWINDOW
);
359 hwnd
= CreateWindow16( (LPCSTR
)PTR_SEG_TO_LIN(cs
->szClass
),
360 (LPCSTR
)PTR_SEG_TO_LIN(cs
->szTitle
), style
,
361 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
,
362 (HMENU
)(DWORD
)(WORD
)wIDmenu
, w
->hInstance
,
367 MDI_MenuModifyItem(w
,hwnd
);
368 dprintf_mdi(stddeb
, "MDICreateChild: created child - %04x\n",hwnd
);
372 ci
->nActiveChildren
--;
373 DeleteMenu(ci
->hWindowMenu
,wIDmenu
,MF_BYCOMMAND
);
374 if( IsWindow(hwndMax
) )
375 ShowWindow(hwndMax
, SW_SHOWMAXIMIZED
);
381 /**********************************************************************
382 * MDI_ChildGetMinMaxInfo
384 void MDI_ChildGetMinMaxInfo(WND
* clientWnd
, HWND hwnd
, MINMAXINFO16
* lpMinMax
)
386 WND
* childWnd
= WIN_FindWndPtr(hwnd
);
387 RECT16 rect
= clientWnd
->rectClient
;
389 MapWindowPoints16(clientWnd
->parent
->hwndSelf
,
390 ((MDICLIENTINFO
*)clientWnd
->wExtra
)->self
, (LPPOINT16
)&rect
, 2);
391 AdjustWindowRectEx16( &rect
, childWnd
->dwStyle
, 0, childWnd
->dwExStyle
);
393 lpMinMax
->ptMaxSize
.x
= rect
.right
-= rect
.left
;
394 lpMinMax
->ptMaxSize
.y
= rect
.bottom
-= rect
.top
;
396 lpMinMax
->ptMaxPosition
.x
= rect
.left
;
397 lpMinMax
->ptMaxPosition
.y
= rect
.top
;
400 /**********************************************************************
401 * MDI_SwitchActiveChild
403 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
406 * wTo is basically lParam of WM_MDINEXT message or explicit
409 void MDI_SwitchActiveChild(HWND clientHwnd
, HWND childHwnd
, BOOL wTo
)
411 WND
*w
= WIN_FindWndPtr(clientHwnd
);
416 hwndTo
= MDI_GetWindow(w
,childHwnd
,(WORD
)wTo
);
418 ci
= (MDICLIENTINFO
*) w
->wExtra
;
420 dprintf_mdi(stddeb
, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd
,hwndTo
);
422 if ( !hwndTo
) return;
424 hwndPrev
= ci
->hwndActiveChild
;
426 if ( hwndTo
!= hwndPrev
)
430 if( ci
->hwndChildMaximized
)
433 w
->dwStyle
&= ~WS_VISIBLE
;
436 SetWindowPos( hwndTo
, HWND_TOP
, 0, 0, 0, 0,
437 SWP_NOMOVE
| SWP_NOSIZE
);
438 if( !wTo
&& hwndPrev
)
440 SetWindowPos( hwndPrev
, HWND_BOTTOM
, 0, 0, 0, 0,
441 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
445 ShowWindow( clientHwnd
, SW_SHOW
);
450 /**********************************************************************
453 HWND
MDIDestroyChild(WND
*w_parent
, MDICLIENTINFO
*ci
, HWND parent
,
454 HWND child
, BOOL flagDestroy
)
456 WND
*childPtr
= WIN_FindWndPtr(child
);
460 if( child
== ci
->hwndActiveChild
)
462 MDI_SwitchActiveChild(parent
,child
,0);
464 if( child
== ci
->hwndActiveChild
)
466 ShowWindow( child
, SW_HIDE
);
467 if( child
== ci
->hwndChildMaximized
)
469 MDI_RestoreFrameMenu(w_parent
->parent
, child
);
470 ci
->hwndChildMaximized
= 0;
471 MDI_UpdateFrameText(w_parent
->parent
,parent
,TRUE
,NULL
);
474 MDI_ChildActivate(w_parent
,0);
476 MDI_MenuDeleteItem(w_parent
, child
);
479 ci
->nActiveChildren
--;
481 dprintf_mdi(stddeb
,"MDIDestroyChild: child destroyed - %04x\n",child
);
485 MDI_PostUpdate(GetParent(child
), ci
, SB_BOTH
+1);
486 DestroyWindow(child
);
494 /**********************************************************************
497 * Note: hWndChild is NULL when last child is being destroyed
499 LONG
MDI_ChildActivate(WND
*clientPtr
, HWND hWndChild
)
501 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientPtr
->wExtra
;
502 HWND prevActiveWnd
= clientInfo
->hwndActiveChild
;
503 WND
*wndPtr
= WIN_FindWndPtr( hWndChild
);
504 WND
*wndPrev
= WIN_FindWndPtr( prevActiveWnd
);
505 BOOL isActiveFrameWnd
= 0;
507 if( hWndChild
== prevActiveWnd
) return 0L;
510 if( wndPtr
->dwStyle
& WS_DISABLED
) return 0L;
512 dprintf_mdi(stddeb
,"MDI_ChildActivate: %04x\n", hWndChild
);
514 if( GetActiveWindow() == clientPtr
->parent
->hwndSelf
)
515 isActiveFrameWnd
= TRUE
;
517 /* deactivate prev. active child */
520 SendMessage16( prevActiveWnd
, WM_NCACTIVATE
, FALSE
, 0L );
522 SendMessage32A( prevActiveWnd
, WM_MDIACTIVATE
, (WPARAM
)prevActiveWnd
,
525 SendMessage16( prevActiveWnd
, WM_MDIACTIVATE
, FALSE
,
526 MAKELONG(hWndChild
,prevActiveWnd
));
528 /* uncheck menu item */
529 if( clientInfo
->hWindowMenu
)
530 CheckMenuItem( clientInfo
->hWindowMenu
,
531 wndPrev
->wIDmenu
, 0);
535 if( clientInfo
->hwndChildMaximized
)
536 if( clientInfo
->hwndChildMaximized
!= hWndChild
)
539 clientInfo
->hwndActiveChild
= hWndChild
;
540 ShowWindow( hWndChild
, SW_SHOWMAXIMIZED
);
543 ShowWindow( clientInfo
->hwndActiveChild
,
546 clientInfo
->hwndActiveChild
= hWndChild
;
548 /* check if we have any children left */
551 if( isActiveFrameWnd
)
552 SetFocus( clientInfo
->self
);
556 /* check menu item */
557 if( clientInfo
->hWindowMenu
)
558 CheckMenuItem( clientInfo
->hWindowMenu
,
559 wndPtr
->wIDmenu
, MF_CHECKED
);
561 /* bring active child to the top */
562 SetWindowPos( hWndChild
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
564 if( isActiveFrameWnd
)
566 SendMessage16( hWndChild
, WM_NCACTIVATE
, TRUE
, 0L);
567 if( GetFocus() == clientInfo
->self
)
568 SendMessage16( clientInfo
->self
, WM_SETFOCUS
,
569 (WPARAM
)clientInfo
->self
, 0L );
571 SetFocus( clientInfo
->self
);
575 SendMessage32A( hWndChild
, WM_MDIACTIVATE
, (WPARAM
)hWndChild
,
576 (LPARAM
)prevActiveWnd
);
578 SendMessage16( hWndChild
, WM_MDIACTIVATE
, TRUE
,
579 MAKELONG(prevActiveWnd
,hWndChild
) );
585 /**********************************************************************
588 * iTotal returns number of children available for tiling or cascading
590 MDIWCL
* MDI_BuildWCL(WND
* clientWnd
, INT16
* iTotal
)
592 MDIWCL
*listTop
,*listNext
;
595 if (!(listTop
= (MDIWCL
*)malloc( sizeof(MDIWCL
) ))) return NULL
;
597 listTop
->hChild
= clientWnd
->child
? clientWnd
->child
->hwndSelf
: 0;
598 listTop
->prev
= NULL
;
601 /* build linked list from top child to bottom */
603 childWnd
= WIN_FindWndPtr( listTop
->hChild
);
604 while( childWnd
&& childWnd
->next
)
606 listNext
= (MDIWCL
*)xmalloc(sizeof(MDIWCL
));
608 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
609 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
610 !(childWnd
->dwStyle
& WS_VISIBLE
) )
616 listNext
->hChild
= childWnd
->next
->hwndSelf
;
617 listNext
->prev
= listTop
;
621 childWnd
= childWnd
->next
;
624 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
625 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
626 !(childWnd
->dwStyle
& WS_VISIBLE
) )
636 /* -------------------- MDI client window functions ------------------- */
638 /**********************************************************************
639 * CreateMDIMenuBitmap
641 HBITMAP
CreateMDIMenuBitmap(void)
643 HDC hDCSrc
= CreateCompatibleDC(0);
644 HDC hDCDest
= CreateCompatibleDC(hDCSrc
);
645 HBITMAP hbClose
= LoadBitmap(0, MAKEINTRESOURCE(OBM_CLOSE
) );
646 HBITMAP hbCopy
,hb_src
,hb_dest
;
648 hb_src
= SelectObject(hDCSrc
,hbClose
);
649 hbCopy
= CreateCompatibleBitmap(hDCSrc
,SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
);
650 hb_dest
= SelectObject(hDCDest
,hbCopy
);
652 BitBlt(hDCDest
, 0, 0, SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
,
653 hDCSrc
, SYSMETRICS_CXSIZE
, 0, SRCCOPY
);
655 SelectObject(hDCSrc
,hb_src
);
656 SelectObject(hDCDest
,hb_dest
);
658 DeleteObject(hbClose
);
666 /**********************************************************************
669 LONG
MDICascade(WND
* clientWnd
, MDICLIENTINFO
*ci
)
671 MDIWCL
*listTop
,*listPrev
;
672 INT16 delta
= 0,iToPosition
= 0, n
= 0;
675 if (ci
->hwndChildMaximized
)
676 ShowWindow( ci
->hwndChildMaximized
, SW_NORMAL
);
678 if (ci
->nActiveChildren
== 0) return 0;
680 if (!(listTop
= MDI_BuildWCL(clientWnd
,&iToPosition
))) return 0;
682 if( iToPosition
< ci
->nActiveChildren
)
683 delta
= 2 * SYSMETRICS_CYICONSPACING
+ SYSMETRICS_CYICON
;
685 /* walk list and move windows */
688 dprintf_mdi(stddeb
, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
689 listTop
->hChild
, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
);
691 if( listTop
->hChild
)
693 MDI_CalcDefaultChildPos(clientWnd
, n
++, pos
, delta
);
694 SetWindowPos(listTop
->hChild
, 0, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
,
695 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
698 listPrev
= listTop
->prev
;
703 if( iToPosition
< ci
->nActiveChildren
)
704 ArrangeIconicWindows( clientWnd
->hwndSelf
);
709 /**********************************************************************
713 LONG
MDITile(WND
* wndClient
, MDICLIENTINFO
*ci
,WORD wParam
)
715 MDIWCL
*listTop
,*listPrev
;
722 INT16 iToPosition
= 0;
724 if (ci
->hwndChildMaximized
)
725 ShowWindow(ci
->hwndChildMaximized
, SW_NORMAL
);
727 if (ci
->nActiveChildren
== 0) return 0;
729 listTop
= MDI_BuildWCL(wndClient
, &iToPosition
);
731 dprintf_mdi(stddeb
,"MDITile: %i windows to tile\n",iToPosition
);
733 if( !listTop
) return 0;
738 rect
= wndClient
->rectClient
;
739 rows
= (int) sqrt((double) iToPosition
);
740 columns
= iToPosition
/ rows
;
742 if (wParam
== MDITILE_HORIZONTAL
) /* version >= 3.1 */
745 rows
=columns
; /* exchange r and c */
750 if( iToPosition
!= ci
->nActiveChildren
)
752 y
= rect
.bottom
- 2 * SYSMETRICS_CYICONSPACING
- SYSMETRICS_CYICON
;
753 rect
.bottom
= ( y
- SYSMETRICS_CYICON
< rect
.top
)? rect
.bottom
: y
;
756 ysize
= rect
.bottom
/ rows
;
757 xsize
= rect
.right
/ columns
;
762 for (c
= 1; c
<= columns
; c
++)
766 rows
= iToPosition
- i
;
767 ysize
= rect
.bottom
/ rows
;
771 for (r
= 1; r
<= rows
; r
++, i
++)
773 /* shouldn't happen but... */
777 /* skip iconized childs from tiling */
778 while (!listTop
->hChild
)
780 listPrev
= listTop
->prev
;
784 SetWindowPos(listTop
->hChild
, 0, x
, y
, xsize
, ysize
,
785 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
787 listPrev
= listTop
->prev
;
795 /* free the rest if any */
798 listPrev
= listTop
->prev
;
803 if (iToPosition
< ci
->nActiveChildren
)
804 ArrangeIconicWindows( wndClient
->hwndSelf
);
809 /* ----------------------- Frame window ---------------------------- */
812 /**********************************************************************
813 * MDI_AugmentFrameMenu
815 BOOL
MDI_AugmentFrameMenu(MDICLIENTINFO
* ci
, WND
*frame
, HWND hChild
)
817 WND
* child
= WIN_FindWndPtr(hChild
);
821 dprintf_mdi(stddeb
,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame
,hChild
);
823 if( !frame
->wIDmenu
|| !child
->hSysMenu
) return 0;
825 /* create a copy of sysmenu popup and insert it into frame menu bar */
827 if (!(handle
= SYSRES_LoadResource( SYSRES_MENU_SYSMENU
))) return 0;
828 hSysPopup
= LoadMenuIndirect16( GlobalLock16( handle
) );
829 SYSRES_FreeResource( handle
);
831 dprintf_mdi(stddeb
,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup
,child
->hSysMenu
);
833 if( !InsertMenu32A(frame
->wIDmenu
,0,MF_BYPOSITION
| MF_BITMAP
| MF_POPUP
,
834 hSysPopup
, (LPSTR
)(DWORD
)hBmpClose
))
835 { DestroyMenu(hSysPopup
); return 0; }
837 if( !AppendMenu32A(frame
->wIDmenu
,MF_HELP
| MF_BITMAP
,
838 SC_RESTORE
, (LPSTR
)(DWORD
)hBmpRestore
))
840 RemoveMenu(frame
->wIDmenu
,0,MF_BYPOSITION
);
844 EnableMenuItem(hSysPopup
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
845 EnableMenuItem(hSysPopup
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
846 EnableMenuItem(hSysPopup
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
848 child
->dwStyle
&= ~WS_SYSMENU
;
851 DrawMenuBar(frame
->hwndSelf
);
856 /**********************************************************************
857 * MDI_RestoreFrameMenu
859 BOOL
MDI_RestoreFrameMenu( WND
*frameWnd
, HWND hChild
)
861 WND
* child
= WIN_FindWndPtr(hChild
);
862 INT nItems
= GetMenuItemCount(frameWnd
->wIDmenu
) - 1;
864 dprintf_mdi(stddeb
,"MDI_RestoreFrameMenu: for child %04x\n",hChild
);
866 if( GetMenuItemID(frameWnd
->wIDmenu
,nItems
) != SC_RESTORE
)
869 child
->dwStyle
|= WS_SYSMENU
;
871 RemoveMenu(frameWnd
->wIDmenu
,0,MF_BYPOSITION
);
872 DeleteMenu(frameWnd
->wIDmenu
,nItems
-1,MF_BYPOSITION
);
874 DrawMenuBar(frameWnd
->hwndSelf
);
879 /**********************************************************************
880 * MDI_UpdateFrameText
882 * used when child window is maximized/restored
884 * Note: lpTitle can be NULL
886 void MDI_UpdateFrameText(WND
*frameWnd
, HWND hClient
, BOOL repaint
, LPCSTR lpTitle
)
888 char lpBuffer
[MDI_MAXTITLELENGTH
+1];
889 WND
* clientWnd
= WIN_FindWndPtr(hClient
);
891 MDICLIENTINFO
*ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
893 dprintf_mdi(stddeb
, "MDI: repaint %i, frameText %s\n", repaint
, (lpTitle
)?lpTitle
:"NULL");
895 /* store new "default" title if lpTitle is not NULL */
898 if (ci
->frameTitle
) HeapFree( SystemHeap
, 0, ci
->frameTitle
);
899 ci
->frameTitle
= HEAP_strdupA( SystemHeap
, 0, lpTitle
);
904 WND
* childWnd
= WIN_FindWndPtr( ci
->hwndChildMaximized
);
906 if( childWnd
&& childWnd
->text
)
908 /* combine frame title and child title if possible */
910 LPCSTR lpBracket
= " - [";
911 int i_frame_text_length
= strlen(ci
->frameTitle
);
912 int i_child_text_length
= strlen(childWnd
->text
);
914 lstrcpyn( lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
916 if( i_frame_text_length
+ 6 < MDI_MAXTITLELENGTH
)
918 strcat( lpBuffer
, lpBracket
);
920 if( i_frame_text_length
+ i_child_text_length
+ 6 < MDI_MAXTITLELENGTH
)
922 strcat( lpBuffer
, childWnd
->text
);
923 strcat( lpBuffer
, "]" );
927 lstrcpyn( lpBuffer
+ i_frame_text_length
+ 4,
929 MDI_MAXTITLELENGTH
- i_frame_text_length
- 5 );
930 strcat( lpBuffer
, "]" );
936 strncpy(lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
937 lpBuffer
[MDI_MAXTITLELENGTH
]='\0';
943 DEFWND_SetText( frameWnd
, lpBuffer
);
944 if( repaint
== MDI_REPAINTFRAME
)
945 SetWindowPos(frameWnd
->hwndSelf
, 0,0,0,0,0, SWP_FRAMECHANGED
|
946 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
950 /* ----------------------------- Interface ---------------------------- */
953 /**********************************************************************
956 * This function is the handler for all MDI requests.
958 LRESULT
MDIClientWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
961 LPCLIENTCREATESTRUCT ccs
;
964 WND
*w
= WIN_FindWndPtr(hwnd
);
965 WND
*frameWnd
= w
->parent
;
967 ci
= (MDICLIENTINFO
*) w
->wExtra
;
972 cs
= (LPCREATESTRUCT16
) PTR_SEG_TO_LIN(lParam
);
973 ccs
= (LPCLIENTCREATESTRUCT
) PTR_SEG_TO_LIN(cs
->lpCreateParams
);
975 ci
->hWindowMenu
= ccs
->hWindowMenu
;
976 ci
->idFirstChild
= ccs
->idFirstChild
;
977 ci
->hwndChildMaximized
= 0;
978 ci
->nActiveChildren
= 0;
979 ci
->nTotalCreated
= 0;
980 ci
->frameTitle
= NULL
;
981 ci
->sbNeedUpdate
= 0;
983 w
->dwStyle
|= WS_CLIPCHILDREN
;
987 hBmpClose
= CreateMDIMenuBitmap();
988 hBmpRestore
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE
) );
990 MDI_UpdateFrameText(frameWnd
, hwnd
, MDI_NOFRAMEREPAINT
,frameWnd
->text
);
992 AppendMenu32A( ccs
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
994 GetClientRect16(frameWnd
->hwndSelf
, &rect
);
995 NC_HandleNCCalcSize( w
, &rect
);
996 w
->rectClient
= rect
;
998 dprintf_mdi(stddeb
,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd
,ci
->idFirstChild
);
1003 if( ci
->hwndChildMaximized
) MDI_RestoreFrameMenu(w
, frameWnd
->hwndSelf
);
1004 ci
->idFirstChild
= GetMenuItemCount(ci
->hWindowMenu
) - 1;
1005 ci
->nActiveChildren
++; /* to delete a separator */
1007 while( ci
->nActiveChildren
-- )
1008 DeleteMenu(ci
->hWindowMenu
,MF_BYPOSITION
,ci
->idFirstChild
--);
1012 case WM_MDIACTIVATE
:
1013 if( ci
->hwndActiveChild
!= (HWND
)wParam
)
1014 SetWindowPos((HWND
)wParam
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1018 return MDICascade(w
, ci
);
1021 return (LONG
)MDICreateChild(w
, ci
, hwnd
, lParam
);
1024 return (LONG
)MDIDestroyChild(w
, ci
, hwnd
, (HWND
)wParam
, TRUE
);
1026 case WM_MDIGETACTIVE
:
1027 return ((LONG
) ci
->hwndActiveChild
|
1028 ((LONG
) (ci
->hwndChildMaximized
>0) << 16));
1030 case WM_MDIICONARRANGE
:
1031 ci
->sbNeedUpdate
= TRUE
;
1032 MDIIconArrange(hwnd
);
1033 ci
->sbRecalc
= SB_BOTH
+1;
1034 SendMessage16(hwnd
,WM_MDICALCCHILDSCROLL
,0,0L);
1037 case WM_MDIMAXIMIZE
:
1038 ShowWindow((HWND
)wParam
, SW_MAXIMIZE
);
1042 MDI_SwitchActiveChild(hwnd
, (HWND
)wParam
, (lParam
)?1:0);
1046 ShowWindow( (HWND
)wParam
, SW_NORMAL
);
1051 return (LRESULT
)MDISetMenu(hwnd
, FALSE
, (HMENU
)wParam
, (HMENU
)lParam
);
1053 return (LRESULT
)MDISetMenu(hwnd
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1057 ci
->sbNeedUpdate
= TRUE
;
1058 ShowScrollBar(hwnd
,SB_BOTH
,FALSE
);
1059 MDITile(w
, ci
,wParam
);
1060 ci
->sbNeedUpdate
= FALSE
;
1065 ci
->sbNeedUpdate
= TRUE
;
1066 ScrollChildren(hwnd
,message
,wParam
,lParam
);
1067 ci
->sbNeedUpdate
= FALSE
;
1071 if( ci
->hwndActiveChild
)
1073 w
= WIN_FindWndPtr( ci
->hwndActiveChild
);
1074 if( !(w
->dwStyle
& WS_MINIMIZE
) )
1075 SetFocus( ci
->hwndActiveChild
);
1080 if( ci
->hwndActiveChild
)
1081 SendMessage16(ci
->hwndActiveChild
, message
, wParam
, lParam
);
1084 case WM_PARENTNOTIFY
:
1085 if( wParam
== WM_LBUTTONDOWN
)
1087 POINT16 pt
= MAKEPOINT16(lParam
);
1088 HWND child
= ChildWindowFromPoint16(hwnd
, pt
);
1090 dprintf_mdi(stddeb
,"MDIClient: notification from %04x (%i,%i)\n",child
,pt
.x
,pt
.y
);
1092 if( child
&& child
!= hwnd
)
1094 WND
* wnd
= WIN_FindWndPtr( child
);
1096 /* if we got owned popup */
1097 if( wnd
->owner
) child
= wnd
->owner
->hwndSelf
;
1099 if( child
!= ci
->hwndActiveChild
)
1100 SetWindowPos(child
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1106 if( ci
->hwndChildMaximized
)
1108 WND
* child
= WIN_FindWndPtr(ci
->hwndChildMaximized
);
1109 RECT16 rect
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
1111 AdjustWindowRectEx16(&rect
, child
->dwStyle
, 0, child
->dwExStyle
);
1112 MoveWindow(ci
->hwndChildMaximized
, rect
.left
, rect
.top
,
1113 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, 1);
1116 MDI_PostUpdate(hwnd
, ci
, SB_BOTH
+1);
1120 case WM_MDICALCCHILDSCROLL
:
1121 if( ci
->sbNeedUpdate
)
1124 CalcChildScroll(hwnd
, ci
->sbRecalc
-1);
1125 ci
->sbRecalc
= ci
->sbNeedUpdate
= 0;
1130 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1134 /***********************************************************************
1135 * DefFrameProc16 (USER.445)
1137 LRESULT
DefFrameProc16( HWND16 hwnd
, HWND16 hwndMDIClient
, UINT16 message
,
1138 WPARAM16 wParam
, LPARAM lParam
)
1149 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1150 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1152 /* check for possible syscommands for maximized MDI child */
1154 if( wParam
< ci
->idFirstChild
||
1155 wParam
>= ci
->idFirstChild
+ ci
->nActiveChildren
)
1157 if( (wParam
- 0xF000) & 0xF00F ) break;
1168 if( ci
->hwndChildMaximized
)
1169 return SendMessage16( ci
->hwndChildMaximized
, WM_SYSCOMMAND
,
1175 childHwnd
= MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient
),
1178 SendMessage16(hwndMDIClient
, WM_MDIACTIVATE
, (WPARAM
)childHwnd
, 0L);
1183 SendMessage16(hwndMDIClient
, message
, wParam
, lParam
);
1187 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd
), hwndMDIClient
,
1189 (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1193 SetFocus(hwndMDIClient
);
1197 MoveWindow(hwndMDIClient
, 0, 0,
1198 LOWORD(lParam
), HIWORD(lParam
), TRUE
);
1203 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1207 /***********************************************************************
1208 * DefFrameProc32A (USER32.121)
1210 LRESULT
DefFrameProc32A( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1211 WPARAM32 wParam
, LPARAM lParam
)
1218 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1220 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1223 SendMessage32A(hwndMDIClient
, message
, wParam
, lParam
);
1227 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1228 wParam
, (LPARAM
)PTR_SEG_TO_LIN(lParam
) );
1232 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1237 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1241 /***********************************************************************
1242 * DefFrameProc32W (USER32.122)
1244 LRESULT
DefFrameProc32W( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1245 WPARAM32 wParam
, LPARAM lParam
)
1252 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1254 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1257 SendMessage32W(hwndMDIClient
, message
, wParam
, lParam
);
1261 /* FIXME: Unicode */
1262 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1267 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1272 return DefWindowProc32W( hwnd
, message
, wParam
, lParam
);
1276 /***********************************************************************
1277 * DefMDIChildProc16 (USER.447)
1279 LRESULT
DefMDIChildProc16( HWND16 hwnd
, UINT16 message
,
1280 WPARAM16 wParam
, LPARAM lParam
)
1285 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1286 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1291 DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1292 MDI_MenuModifyItem(clientWnd
,hwnd
);
1293 if( ci
->hwndChildMaximized
== hwnd
)
1294 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1295 MDI_REPAINTFRAME
, NULL
);
1299 SendMessage16(ci
->self
,WM_MDIDESTROY
,(WPARAM
)hwnd
,0L);
1303 if( ci
->hwndActiveChild
!= hwnd
)
1304 MDI_ChildActivate(clientWnd
, hwnd
);
1307 case WM_CHILDACTIVATE
:
1308 MDI_ChildActivate(clientWnd
, hwnd
);
1312 dprintf_mdi(stddeb
,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
1313 hwnd
, ci
->hwndActiveChild
);
1320 if( ci
->hwndChildMaximized
== hwnd
) return 0;
1323 if( ci
->hwndChildMaximized
== hwnd
)
1324 return SendMessage16( clientWnd
->parent
->hwndSelf
,
1325 message
, wParam
, lParam
);
1328 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 0);
1331 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 1);
1336 case WM_GETMINMAXINFO
:
1337 MDI_ChildGetMinMaxInfo(clientWnd
, hwnd
, (MINMAXINFO16
*) PTR_SEG_TO_LIN(lParam
));
1341 if( ci
->hwndChildMaximized
)
1342 ci
->sbNeedUpdate
= 0;
1344 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1350 if( ci
->hwndActiveChild
== hwnd
&& wParam
!= SIZE_MAXIMIZED
)
1352 ci
->hwndChildMaximized
= 0;
1354 MDI_RestoreFrameMenu( clientWnd
->parent
, hwnd
);
1355 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1356 MDI_REPAINTFRAME
, NULL
);
1359 if( wParam
== SIZE_MAXIMIZED
)
1361 HWND hMaxChild
= ci
->hwndChildMaximized
;
1363 if( hMaxChild
== hwnd
) break;
1367 SendMessage16( hMaxChild
, WM_SETREDRAW
, FALSE
, 0L );
1369 MDI_RestoreFrameMenu( clientWnd
->parent
, hMaxChild
);
1370 ShowWindow( hMaxChild
, SW_SHOWNOACTIVATE
);
1372 SendMessage16( hMaxChild
, WM_SETREDRAW
, TRUE
, 0L );
1375 ci
->hwndChildMaximized
= hwnd
; /* !!! */
1377 MDI_AugmentFrameMenu( ci
, clientWnd
->parent
, hwnd
);
1378 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1379 MDI_REPAINTFRAME
, NULL
);
1382 if( wParam
== SIZE_MINIMIZED
)
1384 HWND switchTo
= MDI_GetWindow(clientWnd
, hwnd
, 0);
1387 SendMessage16( switchTo
, WM_CHILDACTIVATE
, 0, 0L);
1390 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1395 /* MDI children don't have menus */
1396 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1397 (WPARAM
)SC_KEYMENU
, (LPARAM
)wParam
);
1401 /* set current menu to child system menu */
1406 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1410 /***********************************************************************
1411 * DefMDIChildProc32A (USER32.123)
1413 LRESULT
DefMDIChildProc32A( HWND32 hwnd
, UINT32 message
,
1414 WPARAM32 wParam
, LPARAM lParam
)
1419 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1420 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1425 DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1426 MDI_MenuModifyItem(clientWnd
,hwnd
);
1427 if( ci
->hwndChildMaximized
== hwnd
)
1428 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1429 MDI_REPAINTFRAME
, NULL
);
1432 case WM_GETMINMAXINFO
:
1435 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32
*)lParam
, &mmi
);
1436 MDI_ChildGetMinMaxInfo( clientWnd
, hwnd
, &mmi
);
1437 STRUCT32_MINMAXINFO16to32( &mmi
, (MINMAXINFO32
*)lParam
);
1443 /* MDI children don't have menus */
1444 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1445 (WPARAM
)SC_KEYMENU
, (LPARAM
)LOWORD(wParam
) );
1450 case WM_CHILDACTIVATE
:
1456 return DefMDIChildProc16( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1458 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1462 /***********************************************************************
1463 * DefMDIChildProc32W (USER32.124)
1465 LRESULT
DefMDIChildProc32W( HWND32 hwnd
, UINT32 message
,
1466 WPARAM32 wParam
, LPARAM lParam
)
1471 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1472 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1477 DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1478 MDI_MenuModifyItem(clientWnd
,hwnd
);
1479 if( ci
->hwndChildMaximized
== hwnd
)
1480 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1481 MDI_REPAINTFRAME
, NULL
);
1484 case WM_GETMINMAXINFO
:
1488 case WM_CHILDACTIVATE
:
1494 return DefMDIChildProc32A( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1496 return DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1500 /**********************************************************************
1501 * TranslateMDISysAccel (USER.451)
1504 BOOL
TranslateMDISysAccel(HWND hwndClient
, LPMSG msg
)
1506 WND
* clientWnd
= WIN_FindWndPtr( hwndClient
);
1508 MDICLIENTINFO
*ci
= NULL
;
1511 if( (msg
->message
!= WM_KEYDOWN
&& msg
->message
!= WM_SYSKEYDOWN
) || !clientWnd
)
1514 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1515 wnd
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1517 if( !wnd
) return 0;
1519 if( wnd
->dwStyle
& WS_DISABLED
) return 0;
1521 if ((GetKeyState(VK_CONTROL
) & 0x8000) && !(GetKeyState(VK_MENU
) & 0x8000))
1522 switch( msg
->wParam
)
1526 wParam
= ( GetKeyState(VK_SHIFT
) & 0x8000 )? SC_NEXTWINDOW
: SC_PREVWINDOW
;
1537 dprintf_mdi(stddeb
,"TranslateMDISysAccel: wParam = %04x\n", wParam
);
1539 SendMessage16(ci
->hwndActiveChild
,WM_SYSCOMMAND
, wParam
, (LPARAM
)msg
->wParam
);
1544 /***********************************************************************
1545 * CalcChildScroll (USER.462)
1547 void CalcChildScroll( HWND hwnd
, WORD scroll
)
1549 RECT16 childRect
, clientRect
;
1550 INT vmin
, vmax
, hmin
, hmax
, vpos
, hpos
;
1551 BOOL noscroll
= FALSE
;
1554 if (!(Wnd
= pWnd
= WIN_FindWndPtr( hwnd
))) return;
1555 GetClientRect16( hwnd
, &clientRect
);
1556 SetRectEmpty16( &childRect
);
1558 for ( pWnd
= pWnd
->child
; pWnd
; pWnd
= pWnd
->next
)
1560 UnionRect16( &childRect
, &pWnd
->rectWindow
, &childRect
);
1561 if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1564 UnionRect16( &childRect
, &clientRect
, &childRect
);
1566 /* jump through the hoops to prevent excessive flashing
1569 hmin
= childRect
.left
; hmax
= childRect
.right
- clientRect
.right
;
1570 hpos
= clientRect
.left
- childRect
.left
;
1571 vmin
= childRect
.top
; vmax
= childRect
.bottom
- clientRect
.bottom
;
1572 vpos
= clientRect
.top
- childRect
.top
;
1575 ShowScrollBar(hwnd
, SB_BOTH
, FALSE
);
1580 vpos
= hpos
; vmin
= hmin
; vmax
= hmax
;
1582 SetScrollPos(hwnd
, scroll
, vpos
, FALSE
);
1583 SetScrollRange(hwnd
, scroll
, vmin
, vmax
, TRUE
);
1586 SCROLL_SetNCSbState( Wnd
, vmin
, vmax
, vpos
,
1588 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
1589 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1593 /***********************************************************************
1594 * ScrollChildren (USER.463)
1596 void ScrollChildren(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1598 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1606 if( !wndPtr
) return;
1608 if( uMsg
== WM_HSCROLL
)
1610 GetScrollRange(hWnd
,SB_HORZ
,&minPos
,&maxPos
);
1611 curPos
= GetScrollPos(hWnd
,SB_HORZ
);
1612 length
= (wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
)/2;
1613 shift
= SYSMETRICS_CYHSCROLL
;
1615 else if( uMsg
== WM_VSCROLL
)
1617 GetScrollRange(hWnd
,SB_VERT
,&minPos
,&maxPos
);
1618 curPos
= GetScrollPos(hWnd
,SB_VERT
);
1619 length
= (wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
)/2;
1620 shift
= SYSMETRICS_CXVSCROLL
;
1627 newPos
= curPos
- shift
;
1630 newPos
= curPos
+ shift
;
1633 newPos
= curPos
- length
;
1636 newPos
= curPos
+ length
;
1639 case SB_THUMBPOSITION
:
1640 newPos
= LOWORD(lParam
);
1653 CalcChildScroll(hWnd
,(uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
);
1657 if( newPos
> maxPos
)
1659 else if( newPos
< minPos
)
1662 SetScrollPos(hWnd
, (uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
, newPos
, TRUE
);
1664 if( uMsg
== WM_VSCROLL
)
1665 ScrollWindow(hWnd
,0 ,curPos
- newPos
, NULL
, NULL
);
1667 ScrollWindow(hWnd
,curPos
- newPos
, 0, NULL
, NULL
);