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( cs
->szClass
, cs
->szTitle
, style
,
360 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
,
361 (HMENU
)(DWORD
)(WORD
)wIDmenu
, w
->hInstance
,
366 MDI_MenuModifyItem(w
,hwnd
);
367 dprintf_mdi(stddeb
, "MDICreateChild: created child - %04x\n",hwnd
);
371 ci
->nActiveChildren
--;
372 DeleteMenu(ci
->hWindowMenu
,wIDmenu
,MF_BYCOMMAND
);
373 if( IsWindow(hwndMax
) )
374 ShowWindow(hwndMax
, SW_SHOWMAXIMIZED
);
380 /**********************************************************************
381 * MDI_ChildGetMinMaxInfo
383 void MDI_ChildGetMinMaxInfo(WND
* clientWnd
, HWND hwnd
, MINMAXINFO16
* lpMinMax
)
385 WND
* childWnd
= WIN_FindWndPtr(hwnd
);
386 RECT16 rect
= clientWnd
->rectClient
;
388 MapWindowPoints16(clientWnd
->parent
->hwndSelf
,
389 ((MDICLIENTINFO
*)clientWnd
->wExtra
)->self
, (LPPOINT16
)&rect
, 2);
390 AdjustWindowRectEx16( &rect
, childWnd
->dwStyle
, 0, childWnd
->dwExStyle
);
392 lpMinMax
->ptMaxSize
.x
= rect
.right
-= rect
.left
;
393 lpMinMax
->ptMaxSize
.y
= rect
.bottom
-= rect
.top
;
395 lpMinMax
->ptMaxPosition
.x
= rect
.left
;
396 lpMinMax
->ptMaxPosition
.y
= rect
.top
;
399 /**********************************************************************
400 * MDI_SwitchActiveChild
402 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
405 * wTo is basically lParam of WM_MDINEXT message or explicit
408 void MDI_SwitchActiveChild(HWND clientHwnd
, HWND childHwnd
, BOOL wTo
)
410 WND
*w
= WIN_FindWndPtr(clientHwnd
);
415 hwndTo
= MDI_GetWindow(w
,childHwnd
,(WORD
)wTo
);
417 ci
= (MDICLIENTINFO
*) w
->wExtra
;
419 dprintf_mdi(stddeb
, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd
,hwndTo
);
421 if ( !hwndTo
) return;
423 hwndPrev
= ci
->hwndActiveChild
;
425 if ( hwndTo
!= hwndPrev
)
429 if( ci
->hwndChildMaximized
)
432 w
->dwStyle
&= ~WS_VISIBLE
;
435 SetWindowPos( hwndTo
, HWND_TOP
, 0, 0, 0, 0,
436 SWP_NOMOVE
| SWP_NOSIZE
);
437 if( !wTo
&& hwndPrev
)
439 SetWindowPos( hwndPrev
, HWND_BOTTOM
, 0, 0, 0, 0,
440 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
444 ShowWindow( clientHwnd
, SW_SHOW
);
449 /**********************************************************************
452 HWND
MDIDestroyChild(WND
*w_parent
, MDICLIENTINFO
*ci
, HWND parent
,
453 HWND child
, BOOL flagDestroy
)
455 WND
*childPtr
= WIN_FindWndPtr(child
);
459 if( child
== ci
->hwndActiveChild
)
461 MDI_SwitchActiveChild(parent
,child
,0);
463 if( child
== ci
->hwndActiveChild
)
465 ShowWindow( child
, SW_HIDE
);
466 if( child
== ci
->hwndChildMaximized
)
468 MDI_RestoreFrameMenu(w_parent
->parent
, child
);
469 ci
->hwndChildMaximized
= 0;
470 MDI_UpdateFrameText(w_parent
->parent
,parent
,TRUE
,NULL
);
473 MDI_ChildActivate(w_parent
,0);
475 MDI_MenuDeleteItem(w_parent
, child
);
478 ci
->nActiveChildren
--;
480 dprintf_mdi(stddeb
,"MDIDestroyChild: child destroyed - %04x\n",child
);
484 MDI_PostUpdate(GetParent(child
), ci
, SB_BOTH
+1);
485 DestroyWindow(child
);
493 /**********************************************************************
496 * Note: hWndChild is NULL when last child is being destroyed
498 LONG
MDI_ChildActivate(WND
*clientPtr
, HWND hWndChild
)
500 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientPtr
->wExtra
;
501 HWND prevActiveWnd
= clientInfo
->hwndActiveChild
;
502 WND
*wndPtr
= WIN_FindWndPtr( hWndChild
);
503 WND
*wndPrev
= WIN_FindWndPtr( prevActiveWnd
);
504 BOOL isActiveFrameWnd
= 0;
506 if( hWndChild
== prevActiveWnd
) return 0L;
509 if( wndPtr
->dwStyle
& WS_DISABLED
) return 0L;
511 dprintf_mdi(stddeb
,"MDI_ChildActivate: %04x\n", hWndChild
);
513 if( GetActiveWindow() == clientPtr
->parent
->hwndSelf
)
514 isActiveFrameWnd
= TRUE
;
516 /* deactivate prev. active child */
519 SendMessage16( prevActiveWnd
, WM_NCACTIVATE
, FALSE
, 0L );
521 SendMessage32A( prevActiveWnd
, WM_MDIACTIVATE
, (WPARAM
)prevActiveWnd
,
524 SendMessage16( prevActiveWnd
, WM_MDIACTIVATE
, FALSE
,
525 MAKELONG(hWndChild
,prevActiveWnd
));
527 /* uncheck menu item */
528 if( clientInfo
->hWindowMenu
)
529 CheckMenuItem( clientInfo
->hWindowMenu
,
530 wndPrev
->wIDmenu
, 0);
534 if( clientInfo
->hwndChildMaximized
)
535 if( clientInfo
->hwndChildMaximized
!= hWndChild
)
538 clientInfo
->hwndActiveChild
= hWndChild
;
539 ShowWindow( hWndChild
, SW_SHOWMAXIMIZED
);
542 ShowWindow( clientInfo
->hwndActiveChild
,
545 clientInfo
->hwndActiveChild
= hWndChild
;
547 /* check if we have any children left */
550 if( isActiveFrameWnd
)
551 SetFocus( clientInfo
->self
);
555 /* check menu item */
556 if( clientInfo
->hWindowMenu
)
557 CheckMenuItem( clientInfo
->hWindowMenu
,
558 wndPtr
->wIDmenu
, MF_CHECKED
);
560 /* bring active child to the top */
561 SetWindowPos( hWndChild
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
563 if( isActiveFrameWnd
)
565 SendMessage16( hWndChild
, WM_NCACTIVATE
, TRUE
, 0L);
566 if( GetFocus() == clientInfo
->self
)
567 SendMessage16( clientInfo
->self
, WM_SETFOCUS
,
568 (WPARAM
)clientInfo
->self
, 0L );
570 SetFocus( clientInfo
->self
);
574 SendMessage32A( hWndChild
, WM_MDIACTIVATE
, (WPARAM
)hWndChild
,
575 (LPARAM
)prevActiveWnd
);
577 SendMessage16( hWndChild
, WM_MDIACTIVATE
, TRUE
,
578 MAKELONG(prevActiveWnd
,hWndChild
) );
584 /**********************************************************************
587 * iTotal returns number of children available for tiling or cascading
589 MDIWCL
* MDI_BuildWCL(WND
* clientWnd
, INT16
* iTotal
)
591 MDIWCL
*listTop
,*listNext
;
594 if (!(listTop
= (MDIWCL
*)malloc( sizeof(MDIWCL
) ))) return NULL
;
596 listTop
->hChild
= clientWnd
->child
? clientWnd
->child
->hwndSelf
: 0;
597 listTop
->prev
= NULL
;
600 /* build linked list from top child to bottom */
602 childWnd
= WIN_FindWndPtr( listTop
->hChild
);
603 while( childWnd
&& childWnd
->next
)
605 listNext
= (MDIWCL
*)xmalloc(sizeof(MDIWCL
));
607 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
608 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
609 !(childWnd
->dwStyle
& WS_VISIBLE
) )
615 listNext
->hChild
= childWnd
->next
->hwndSelf
;
616 listNext
->prev
= listTop
;
620 childWnd
= childWnd
->next
;
623 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
624 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
625 !(childWnd
->dwStyle
& WS_VISIBLE
) )
635 /* -------------------- MDI client window functions ------------------- */
637 /**********************************************************************
638 * CreateMDIMenuBitmap
640 HBITMAP
CreateMDIMenuBitmap(void)
642 HDC hDCSrc
= CreateCompatibleDC(0);
643 HDC hDCDest
= CreateCompatibleDC(hDCSrc
);
644 HBITMAP hbClose
= LoadBitmap(0, MAKEINTRESOURCE(OBM_CLOSE
) );
645 HBITMAP hbCopy
,hb_src
,hb_dest
;
647 hb_src
= SelectObject(hDCSrc
,hbClose
);
648 hbCopy
= CreateCompatibleBitmap(hDCSrc
,SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
);
649 hb_dest
= SelectObject(hDCDest
,hbCopy
);
651 BitBlt(hDCDest
, 0, 0, SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
,
652 hDCSrc
, SYSMETRICS_CXSIZE
, 0, SRCCOPY
);
654 SelectObject(hDCSrc
,hb_src
);
655 SelectObject(hDCDest
,hb_dest
);
657 DeleteObject(hbClose
);
665 /**********************************************************************
668 LONG
MDICascade(WND
* clientWnd
, MDICLIENTINFO
*ci
)
670 MDIWCL
*listTop
,*listPrev
;
671 INT16 delta
= 0,iToPosition
= 0, n
= 0;
674 if (ci
->hwndChildMaximized
)
675 ShowWindow( ci
->hwndChildMaximized
, SW_NORMAL
);
677 if (ci
->nActiveChildren
== 0) return 0;
679 if (!(listTop
= MDI_BuildWCL(clientWnd
,&iToPosition
))) return 0;
681 if( iToPosition
< ci
->nActiveChildren
)
682 delta
= 2 * SYSMETRICS_CYICONSPACING
+ SYSMETRICS_CYICON
;
684 /* walk list and move windows */
687 dprintf_mdi(stddeb
, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
688 listTop
->hChild
, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
);
690 if( listTop
->hChild
)
692 MDI_CalcDefaultChildPos(clientWnd
, n
++, pos
, delta
);
693 SetWindowPos(listTop
->hChild
, 0, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
,
694 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
697 listPrev
= listTop
->prev
;
702 if( iToPosition
< ci
->nActiveChildren
)
703 ArrangeIconicWindows( clientWnd
->hwndSelf
);
708 /**********************************************************************
712 LONG
MDITile(WND
* wndClient
, MDICLIENTINFO
*ci
,WORD wParam
)
714 MDIWCL
*listTop
,*listPrev
;
721 INT16 iToPosition
= 0;
723 if (ci
->hwndChildMaximized
)
724 ShowWindow(ci
->hwndChildMaximized
, SW_NORMAL
);
726 if (ci
->nActiveChildren
== 0) return 0;
728 listTop
= MDI_BuildWCL(wndClient
, &iToPosition
);
730 dprintf_mdi(stddeb
,"MDITile: %i windows to tile\n",iToPosition
);
732 if( !listTop
) return 0;
737 rect
= wndClient
->rectClient
;
738 rows
= (int) sqrt((double) iToPosition
);
739 columns
= iToPosition
/ rows
;
741 if (wParam
== MDITILE_HORIZONTAL
) /* version >= 3.1 */
744 rows
=columns
; /* exchange r and c */
749 if( iToPosition
!= ci
->nActiveChildren
)
751 y
= rect
.bottom
- 2 * SYSMETRICS_CYICONSPACING
- SYSMETRICS_CYICON
;
752 rect
.bottom
= ( y
- SYSMETRICS_CYICON
< rect
.top
)? rect
.bottom
: y
;
755 ysize
= rect
.bottom
/ rows
;
756 xsize
= rect
.right
/ columns
;
761 for (c
= 1; c
<= columns
; c
++)
765 rows
= iToPosition
- i
;
766 ysize
= rect
.bottom
/ rows
;
770 for (r
= 1; r
<= rows
; r
++, i
++)
772 /* shouldn't happen but... */
776 if( listTop
->hChild
)
778 SetWindowPos(listTop
->hChild
, 0, x
, y
, xsize
, ysize
,
779 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
782 listPrev
= listTop
->prev
;
790 /* free the rest if any */
793 listPrev
= listTop
->prev
;
798 if (iToPosition
< ci
->nActiveChildren
)
799 ArrangeIconicWindows( wndClient
->hwndSelf
);
804 /* ----------------------- Frame window ---------------------------- */
807 /**********************************************************************
808 * MDI_AugmentFrameMenu
810 BOOL
MDI_AugmentFrameMenu(MDICLIENTINFO
* ci
, WND
*frame
, HWND hChild
)
812 WND
* child
= WIN_FindWndPtr(hChild
);
816 dprintf_mdi(stddeb
,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame
,hChild
);
818 if( !frame
->wIDmenu
|| !child
->hSysMenu
) return 0;
820 /* create a copy of sysmenu popup and insert it into frame menu bar */
822 if (!(handle
= SYSRES_LoadResource( SYSRES_MENU_SYSMENU
))) return 0;
823 hSysPopup
= LoadMenuIndirect16( GlobalLock16( handle
) );
824 SYSRES_FreeResource( handle
);
826 dprintf_mdi(stddeb
,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup
,child
->hSysMenu
);
828 if( !InsertMenu32A(frame
->wIDmenu
,0,MF_BYPOSITION
| MF_BITMAP
| MF_POPUP
,
829 hSysPopup
, (LPSTR
)(DWORD
)hBmpClose
))
830 { DestroyMenu(hSysPopup
); return 0; }
832 if( !AppendMenu32A(frame
->wIDmenu
,MF_HELP
| MF_BITMAP
,
833 SC_RESTORE
, (LPSTR
)(DWORD
)hBmpRestore
))
835 RemoveMenu(frame
->wIDmenu
,0,MF_BYPOSITION
);
839 EnableMenuItem(hSysPopup
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
840 EnableMenuItem(hSysPopup
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
841 EnableMenuItem(hSysPopup
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
843 child
->dwStyle
&= ~WS_SYSMENU
;
846 DrawMenuBar(frame
->hwndSelf
);
851 /**********************************************************************
852 * MDI_RestoreFrameMenu
854 BOOL
MDI_RestoreFrameMenu( WND
*frameWnd
, HWND hChild
)
856 WND
* child
= WIN_FindWndPtr(hChild
);
857 INT nItems
= GetMenuItemCount(frameWnd
->wIDmenu
) - 1;
859 dprintf_mdi(stddeb
,"MDI_RestoreFrameMenu: for child %04x\n",hChild
);
861 if( GetMenuItemID(frameWnd
->wIDmenu
,nItems
) != SC_RESTORE
)
864 child
->dwStyle
|= WS_SYSMENU
;
866 RemoveMenu(frameWnd
->wIDmenu
,0,MF_BYPOSITION
);
867 DeleteMenu(frameWnd
->wIDmenu
,nItems
-1,MF_BYPOSITION
);
869 DrawMenuBar(frameWnd
->hwndSelf
);
874 /**********************************************************************
875 * MDI_UpdateFrameText
877 * used when child window is maximized/restored
879 * Note: lpTitle can be NULL
881 void MDI_UpdateFrameText(WND
*frameWnd
, HWND hClient
, BOOL repaint
, LPCSTR lpTitle
)
883 char lpBuffer
[MDI_MAXTITLELENGTH
+1];
884 WND
* clientWnd
= WIN_FindWndPtr(hClient
);
886 MDICLIENTINFO
*ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
888 dprintf_mdi(stddeb
, "MDI: repaint %i, frameText %s\n", repaint
, (lpTitle
)?lpTitle
:"NULL");
890 /* store new "default" title if lpTitle is not NULL */
893 if (ci
->frameTitle
) HeapFree( SystemHeap
, 0, ci
->frameTitle
);
894 ci
->frameTitle
= HEAP_strdupA( SystemHeap
, 0, lpTitle
);
899 WND
* childWnd
= WIN_FindWndPtr( ci
->hwndChildMaximized
);
901 if( childWnd
&& childWnd
->text
)
903 /* combine frame title and child title if possible */
905 LPCSTR lpBracket
= " - [";
906 int i_frame_text_length
= strlen(ci
->frameTitle
);
907 int i_child_text_length
= strlen(childWnd
->text
);
909 lstrcpyn( lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
911 if( i_frame_text_length
+ 6 < MDI_MAXTITLELENGTH
)
913 strcat( lpBuffer
, lpBracket
);
915 if( i_frame_text_length
+ i_child_text_length
+ 6 < MDI_MAXTITLELENGTH
)
917 strcat( lpBuffer
, childWnd
->text
);
918 strcat( lpBuffer
, "]" );
922 lstrcpyn( lpBuffer
+ i_frame_text_length
+ 4,
924 MDI_MAXTITLELENGTH
- i_frame_text_length
- 5 );
925 strcat( lpBuffer
, "]" );
931 strncpy(lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
932 lpBuffer
[MDI_MAXTITLELENGTH
]='\0';
938 DEFWND_SetText( frameWnd
, lpBuffer
);
939 if( repaint
== MDI_REPAINTFRAME
)
940 SetWindowPos(frameWnd
->hwndSelf
, 0,0,0,0,0, SWP_FRAMECHANGED
|
941 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
945 /* ----------------------------- Interface ---------------------------- */
948 /**********************************************************************
951 * This function is the handler for all MDI requests.
953 LRESULT
MDIClientWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
956 LPCLIENTCREATESTRUCT ccs
;
959 WND
*w
= WIN_FindWndPtr(hwnd
);
960 WND
*frameWnd
= w
->parent
;
962 ci
= (MDICLIENTINFO
*) w
->wExtra
;
967 cs
= (LPCREATESTRUCT16
) PTR_SEG_TO_LIN(lParam
);
968 ccs
= (LPCLIENTCREATESTRUCT
) PTR_SEG_TO_LIN(cs
->lpCreateParams
);
970 ci
->hWindowMenu
= ccs
->hWindowMenu
;
971 ci
->idFirstChild
= ccs
->idFirstChild
;
972 ci
->hwndChildMaximized
= 0;
973 ci
->nActiveChildren
= 0;
974 ci
->nTotalCreated
= 0;
975 ci
->frameTitle
= NULL
;
976 ci
->sbNeedUpdate
= 0;
978 w
->dwStyle
|= WS_CLIPCHILDREN
;
982 hBmpClose
= CreateMDIMenuBitmap();
983 hBmpRestore
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE
) );
985 MDI_UpdateFrameText(frameWnd
, hwnd
, MDI_NOFRAMEREPAINT
,frameWnd
->text
);
987 AppendMenu32A( ccs
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
989 GetClientRect16(frameWnd
->hwndSelf
, &rect
);
990 NC_HandleNCCalcSize( w
, &rect
);
991 w
->rectClient
= rect
;
993 dprintf_mdi(stddeb
,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd
,ci
->idFirstChild
);
998 if( ci
->hwndChildMaximized
) MDI_RestoreFrameMenu(w
, frameWnd
->hwndSelf
);
999 ci
->idFirstChild
= GetMenuItemCount(ci
->hWindowMenu
) - 1;
1000 ci
->nActiveChildren
++; /* to delete a separator */
1002 while( ci
->nActiveChildren
-- )
1003 DeleteMenu(ci
->hWindowMenu
,MF_BYPOSITION
,ci
->idFirstChild
--);
1007 case WM_MDIACTIVATE
:
1008 if( ci
->hwndActiveChild
!= (HWND
)wParam
)
1009 SetWindowPos((HWND
)wParam
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1013 return MDICascade(w
, ci
);
1016 return (LONG
)MDICreateChild(w
, ci
, hwnd
, lParam
);
1019 return (LONG
)MDIDestroyChild(w
, ci
, hwnd
, (HWND
)wParam
, TRUE
);
1021 case WM_MDIGETACTIVE
:
1022 return ((LONG
) ci
->hwndActiveChild
|
1023 ((LONG
) (ci
->hwndChildMaximized
>0) << 16));
1025 case WM_MDIICONARRANGE
:
1026 ci
->sbNeedUpdate
= TRUE
;
1027 MDIIconArrange(hwnd
);
1028 ci
->sbRecalc
= SB_BOTH
+1;
1029 SendMessage16(hwnd
,WM_MDICALCCHILDSCROLL
,0,0L);
1032 case WM_MDIMAXIMIZE
:
1033 ShowWindow((HWND
)wParam
, SW_MAXIMIZE
);
1037 MDI_SwitchActiveChild(hwnd
, (HWND
)wParam
, (lParam
)?1:0);
1041 ShowWindow( (HWND
)wParam
, SW_NORMAL
);
1046 return (LRESULT
)MDISetMenu(hwnd
, FALSE
, (HMENU
)wParam
, (HMENU
)lParam
);
1048 return (LRESULT
)MDISetMenu(hwnd
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1052 ci
->sbNeedUpdate
= TRUE
;
1053 ShowScrollBar(hwnd
,SB_BOTH
,FALSE
);
1054 MDITile(w
, ci
,wParam
);
1055 ci
->sbNeedUpdate
= FALSE
;
1060 ci
->sbNeedUpdate
= TRUE
;
1061 ScrollChildren(hwnd
,message
,wParam
,lParam
);
1062 ci
->sbNeedUpdate
= FALSE
;
1066 if( ci
->hwndActiveChild
)
1068 w
= WIN_FindWndPtr( ci
->hwndActiveChild
);
1069 if( !(w
->dwStyle
& WS_MINIMIZE
) )
1070 SetFocus( ci
->hwndActiveChild
);
1075 if( ci
->hwndActiveChild
)
1076 SendMessage16(ci
->hwndActiveChild
, message
, wParam
, lParam
);
1079 case WM_PARENTNOTIFY
:
1080 if( wParam
== WM_LBUTTONDOWN
)
1082 POINT16 pt
= MAKEPOINT16(lParam
);
1083 HWND child
= ChildWindowFromPoint16(hwnd
, pt
);
1085 dprintf_mdi(stddeb
,"MDIClient: notification from %04x (%i,%i)\n",child
,pt
.x
,pt
.y
);
1087 if( child
&& child
!= hwnd
)
1089 WND
* wnd
= WIN_FindWndPtr( child
);
1091 /* if we got owned popup */
1092 if( wnd
->owner
) child
= wnd
->owner
->hwndSelf
;
1094 if( child
!= ci
->hwndActiveChild
)
1095 SetWindowPos(child
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1101 if( ci
->hwndChildMaximized
)
1103 WND
* child
= WIN_FindWndPtr(ci
->hwndChildMaximized
);
1104 RECT16 rect
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
1106 AdjustWindowRectEx16(&rect
, child
->dwStyle
, 0, child
->dwExStyle
);
1107 MoveWindow(ci
->hwndChildMaximized
, rect
.left
, rect
.top
,
1108 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, 1);
1111 MDI_PostUpdate(hwnd
, ci
, SB_BOTH
+1);
1115 case WM_MDICALCCHILDSCROLL
:
1116 if( ci
->sbNeedUpdate
)
1119 CalcChildScroll(hwnd
, ci
->sbRecalc
-1);
1120 ci
->sbRecalc
= ci
->sbNeedUpdate
= 0;
1125 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1129 /***********************************************************************
1130 * DefFrameProc16 (USER.445)
1132 LRESULT
DefFrameProc16( HWND16 hwnd
, HWND16 hwndMDIClient
, UINT16 message
,
1133 WPARAM16 wParam
, LPARAM lParam
)
1144 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1145 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1147 /* check for possible syscommands for maximized MDI child */
1149 if( wParam
< ci
->idFirstChild
||
1150 wParam
>= ci
->idFirstChild
+ ci
->nActiveChildren
)
1152 if( (wParam
- 0xF000) & 0xF00F ) break;
1163 if( ci
->hwndChildMaximized
)
1164 return SendMessage16( ci
->hwndChildMaximized
, WM_SYSCOMMAND
,
1170 childHwnd
= MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient
),
1173 SendMessage16(hwndMDIClient
, WM_MDIACTIVATE
, (WPARAM
)childHwnd
, 0L);
1178 SendMessage16(hwndMDIClient
, message
, wParam
, lParam
);
1182 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd
), hwndMDIClient
,
1184 (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1188 SetFocus(hwndMDIClient
);
1192 MoveWindow(hwndMDIClient
, 0, 0,
1193 LOWORD(lParam
), HIWORD(lParam
), TRUE
);
1198 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1202 /***********************************************************************
1203 * DefFrameProc32A (USER32.121)
1205 LRESULT
DefFrameProc32A( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1206 WPARAM32 wParam
, LPARAM lParam
)
1213 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1215 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1218 SendMessage32A(hwndMDIClient
, message
, wParam
, lParam
);
1222 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1223 wParam
, (LPARAM
)PTR_SEG_TO_LIN(lParam
) );
1227 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1232 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1236 /***********************************************************************
1237 * DefFrameProc32W (USER32.122)
1239 LRESULT
DefFrameProc32W( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1240 WPARAM32 wParam
, LPARAM lParam
)
1247 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1249 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1252 SendMessage32W(hwndMDIClient
, message
, wParam
, lParam
);
1256 /* FIXME: Unicode */
1257 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1262 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1267 return DefWindowProc32W( hwnd
, message
, wParam
, lParam
);
1271 /***********************************************************************
1272 * DefMDIChildProc16 (USER.447)
1274 LRESULT
DefMDIChildProc16( HWND16 hwnd
, UINT16 message
,
1275 WPARAM16 wParam
, LPARAM lParam
)
1280 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1281 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1286 DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1287 MDI_MenuModifyItem(clientWnd
,hwnd
);
1288 if( ci
->hwndChildMaximized
== hwnd
)
1289 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1290 MDI_REPAINTFRAME
, NULL
);
1294 SendMessage16(ci
->self
,WM_MDIDESTROY
,(WPARAM
)hwnd
,0L);
1298 if( ci
->hwndActiveChild
!= hwnd
)
1299 MDI_ChildActivate(clientWnd
, hwnd
);
1302 case WM_CHILDACTIVATE
:
1303 MDI_ChildActivate(clientWnd
, hwnd
);
1307 dprintf_mdi(stddeb
,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
1308 hwnd
, ci
->hwndActiveChild
);
1315 if( ci
->hwndChildMaximized
== hwnd
) return 0;
1318 if( ci
->hwndChildMaximized
== hwnd
)
1319 return SendMessage16( clientWnd
->parent
->hwndSelf
,
1320 message
, wParam
, lParam
);
1323 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 0);
1326 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 1);
1331 case WM_GETMINMAXINFO
:
1332 MDI_ChildGetMinMaxInfo(clientWnd
, hwnd
, (MINMAXINFO16
*) PTR_SEG_TO_LIN(lParam
));
1336 if( ci
->hwndChildMaximized
)
1337 ci
->sbNeedUpdate
= 0;
1339 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1345 if( ci
->hwndActiveChild
== hwnd
&& wParam
!= SIZE_MAXIMIZED
)
1347 ci
->hwndChildMaximized
= 0;
1349 MDI_RestoreFrameMenu( clientWnd
->parent
, hwnd
);
1350 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1351 MDI_REPAINTFRAME
, NULL
);
1354 if( wParam
== SIZE_MAXIMIZED
)
1356 HWND hMaxChild
= ci
->hwndChildMaximized
;
1358 if( hMaxChild
== hwnd
) break;
1362 SendMessage16( hMaxChild
, WM_SETREDRAW
, FALSE
, 0L );
1364 MDI_RestoreFrameMenu( clientWnd
->parent
, hMaxChild
);
1365 ShowWindow( hMaxChild
, SW_SHOWNOACTIVATE
);
1367 SendMessage16( hMaxChild
, WM_SETREDRAW
, TRUE
, 0L );
1370 ci
->hwndChildMaximized
= hwnd
; /* !!! */
1372 MDI_AugmentFrameMenu( ci
, clientWnd
->parent
, hwnd
);
1373 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1374 MDI_REPAINTFRAME
, NULL
);
1377 if( wParam
== SIZE_MINIMIZED
)
1379 HWND switchTo
= MDI_GetWindow(clientWnd
, hwnd
, 0);
1382 SendMessage16( switchTo
, WM_CHILDACTIVATE
, 0, 0L);
1385 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1390 /* MDI children don't have menus */
1391 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1392 (WPARAM
)SC_KEYMENU
, (LPARAM
)wParam
);
1396 /* set current menu to child system menu */
1401 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1405 /***********************************************************************
1406 * DefMDIChildProc32A (USER32.123)
1408 LRESULT
DefMDIChildProc32A( HWND32 hwnd
, UINT32 message
,
1409 WPARAM32 wParam
, LPARAM lParam
)
1414 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1415 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1420 DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1421 MDI_MenuModifyItem(clientWnd
,hwnd
);
1422 if( ci
->hwndChildMaximized
== hwnd
)
1423 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1424 MDI_REPAINTFRAME
, NULL
);
1427 case WM_GETMINMAXINFO
:
1430 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32
*)lParam
, &mmi
);
1431 MDI_ChildGetMinMaxInfo( clientWnd
, hwnd
, &mmi
);
1432 STRUCT32_MINMAXINFO16to32( &mmi
, (MINMAXINFO32
*)lParam
);
1438 /* MDI children don't have menus */
1439 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1440 (WPARAM
)SC_KEYMENU
, (LPARAM
)LOWORD(wParam
) );
1445 case WM_CHILDACTIVATE
:
1451 return DefMDIChildProc16( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1453 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1457 /***********************************************************************
1458 * DefMDIChildProc32W (USER32.124)
1460 LRESULT
DefMDIChildProc32W( HWND32 hwnd
, UINT32 message
,
1461 WPARAM32 wParam
, LPARAM lParam
)
1466 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1467 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1472 DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1473 MDI_MenuModifyItem(clientWnd
,hwnd
);
1474 if( ci
->hwndChildMaximized
== hwnd
)
1475 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1476 MDI_REPAINTFRAME
, NULL
);
1479 case WM_GETMINMAXINFO
:
1483 case WM_CHILDACTIVATE
:
1489 return DefMDIChildProc32A( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1491 return DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1495 /**********************************************************************
1496 * TranslateMDISysAccel (USER.451)
1499 BOOL
TranslateMDISysAccel(HWND hwndClient
, LPMSG msg
)
1501 WND
* clientWnd
= WIN_FindWndPtr( hwndClient
);
1503 MDICLIENTINFO
*ci
= NULL
;
1506 if( (msg
->message
!= WM_KEYDOWN
&& msg
->message
!= WM_SYSKEYDOWN
) || !clientWnd
)
1509 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1510 wnd
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1512 if( !wnd
) return 0;
1514 if( wnd
->dwStyle
& WS_DISABLED
) return 0;
1516 if ((GetKeyState(VK_CONTROL
) & 0x8000) && !(GetKeyState(VK_MENU
) & 0x8000))
1517 switch( msg
->wParam
)
1521 wParam
= ( GetKeyState(VK_SHIFT
) & 0x8000 )? SC_NEXTWINDOW
: SC_PREVWINDOW
;
1532 dprintf_mdi(stddeb
,"TranslateMDISysAccel: wParam = %04x\n", wParam
);
1534 SendMessage16(ci
->hwndActiveChild
,WM_SYSCOMMAND
, wParam
, (LPARAM
)msg
->wParam
);
1539 /***********************************************************************
1540 * CalcChildScroll (USER.462)
1542 void CalcChildScroll( HWND hwnd
, WORD scroll
)
1544 RECT16 childRect
, clientRect
;
1545 INT vmin
, vmax
, hmin
, hmax
, vpos
, hpos
;
1546 BOOL noscroll
= FALSE
;
1549 if (!(Wnd
= pWnd
= WIN_FindWndPtr( hwnd
))) return;
1550 GetClientRect16( hwnd
, &clientRect
);
1551 SetRectEmpty16( &childRect
);
1553 for ( pWnd
= pWnd
->child
; pWnd
; pWnd
= pWnd
->next
)
1555 UnionRect16( &childRect
, &pWnd
->rectWindow
, &childRect
);
1556 if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1559 UnionRect16( &childRect
, &clientRect
, &childRect
);
1561 /* jump through the hoops to prevent excessive flashing
1564 hmin
= childRect
.left
; hmax
= childRect
.right
- clientRect
.right
;
1565 hpos
= clientRect
.left
- childRect
.left
;
1566 vmin
= childRect
.top
; vmax
= childRect
.bottom
- clientRect
.bottom
;
1567 vpos
= clientRect
.top
- childRect
.top
;
1570 ShowScrollBar(hwnd
, SB_BOTH
, FALSE
);
1575 vpos
= hpos
; vmin
= hmin
; vmax
= hmax
;
1577 SetScrollPos(hwnd
, scroll
, vpos
, FALSE
);
1578 SetScrollRange(hwnd
, scroll
, vmin
, vmax
, TRUE
);
1581 SCROLL_SetNCSbState( Wnd
, vmin
, vmax
, vpos
,
1583 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
1584 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1588 /***********************************************************************
1589 * ScrollChildren (USER.463)
1591 void ScrollChildren(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1593 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1601 if( !wndPtr
) return;
1603 if( uMsg
== WM_HSCROLL
)
1605 GetScrollRange(hWnd
,SB_HORZ
,&minPos
,&maxPos
);
1606 curPos
= GetScrollPos(hWnd
,SB_HORZ
);
1607 length
= (wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
)/2;
1608 shift
= SYSMETRICS_CYHSCROLL
;
1610 else if( uMsg
== WM_VSCROLL
)
1612 GetScrollRange(hWnd
,SB_VERT
,&minPos
,&maxPos
);
1613 curPos
= GetScrollPos(hWnd
,SB_VERT
);
1614 length
= (wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
)/2;
1615 shift
= SYSMETRICS_CXVSCROLL
;
1622 newPos
= curPos
- shift
;
1625 newPos
= curPos
+ shift
;
1628 newPos
= curPos
- length
;
1631 newPos
= curPos
+ length
;
1634 case SB_THUMBPOSITION
:
1635 newPos
= LOWORD(lParam
);
1648 CalcChildScroll(hWnd
,(uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
);
1652 if( newPos
> maxPos
)
1654 else if( newPos
< minPos
)
1657 SetScrollPos(hWnd
, (uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
, newPos
, TRUE
);
1659 if( uMsg
== WM_VSCROLL
)
1660 ScrollWindow(hWnd
,0 ,curPos
- newPos
, NULL
, NULL
);
1662 ScrollWindow(hWnd
,curPos
- newPos
, 0, NULL
, NULL
);