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"
35 static HBITMAP hBmpClose
= 0;
36 static HBITMAP hBmpRestore
= 0;
38 DWORD
SCROLL_SetNCSbState(WND
*,int,int,int,int,int,int);
40 /* ----------------- declarations ----------------- */
41 void MDI_UpdateFrameText(WND
*, HWND
, BOOL
, LPCSTR
);
42 BOOL
MDI_AugmentFrameMenu(MDICLIENTINFO
*, WND
*, HWND
);
43 BOOL
MDI_RestoreFrameMenu(WND
*, HWND
);
45 void ScrollChildren(HWND
, UINT
, WPARAM
, LPARAM
);
46 void CalcChildScroll(HWND
, WORD
);
48 static LONG
MDI_ChildActivate(WND
* ,HWND
);
50 /* -------- Miscellaneous service functions ----------
55 static HWND
MDI_GetChildByID(WND
* wndPtr
,int id
)
57 for (wndPtr
= wndPtr
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
58 if (wndPtr
->wIDmenu
== id
) return wndPtr
->hwndSelf
;
62 static void MDI_PostUpdate(HWND hwnd
, MDICLIENTINFO
* ci
, WORD recalc
)
64 if( !ci
->sbNeedUpdate
)
66 ci
->sbNeedUpdate
= TRUE
;
67 PostMessage( hwnd
, WM_MDICALCCHILDSCROLL
, 0, 0);
69 ci
->sbRecalc
= recalc
;
72 /**********************************************************************
75 #ifdef SUPERFLUOUS_FUNCTIONS
76 static BOOL
MDI_MenuAppendItem(WND
*clientWnd
, HWND hWndChild
)
79 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
80 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
81 int n
= sprintf(buffer
, "%d ",
82 clientInfo
->nActiveChildren
);
84 if( !clientInfo
->hWindowMenu
) return 0;
86 if (wndPtr
->text
) strncpy(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
- 1);
87 return AppendMenu32A( clientInfo
->hWindowMenu
, MF_STRING
,
88 wndPtr
->wIDmenu
, buffer
);
92 /**********************************************************************
95 static BOOL
MDI_MenuModifyItem(WND
* clientWnd
, HWND hWndChild
)
98 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
99 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
100 UINT n
= sprintf(buffer
, "%d ",
101 wndPtr
->wIDmenu
- clientInfo
->idFirstChild
+ 1);
104 if( !clientInfo
->hWindowMenu
) return 0;
106 if (wndPtr
->text
) lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
108 n
= GetMenuState(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
,MF_BYCOMMAND
);
109 bRet
= ModifyMenu32A(clientInfo
->hWindowMenu
, wndPtr
->wIDmenu
,
110 MF_BYCOMMAND
| MF_STRING
, wndPtr
->wIDmenu
, buffer
);
111 CheckMenuItem(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
, n
& MF_CHECKED
);
115 /**********************************************************************
118 static BOOL
MDI_MenuDeleteItem(WND
* clientWnd
, HWND hWndChild
)
121 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
122 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
125 if( !clientInfo
->nActiveChildren
||
126 !clientInfo
->hWindowMenu
) return 0;
128 id
= wndPtr
->wIDmenu
;
129 DeleteMenu(clientInfo
->hWindowMenu
,id
,MF_BYCOMMAND
);
131 /* walk the rest of MDI children to prevent gaps in the id
132 * sequence and in the menu child list
135 for( index
= id
+1; index
<= clientInfo
->nActiveChildren
+
136 clientInfo
->idFirstChild
; index
++ )
138 wndPtr
= WIN_FindWndPtr(MDI_GetChildByID(clientWnd
,index
));
141 dprintf_mdi(stddeb
,"MDIMenuDeleteItem: no window for id=%i\n",index
);
148 n
= sprintf(buffer
, "%d ",index
- clientInfo
->idFirstChild
);
150 lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
153 ModifyMenu32A(clientInfo
->hWindowMenu
,index
,MF_BYCOMMAND
| MF_STRING
,
154 index
- 1 , buffer
);
159 /**********************************************************************
162 * returns "activateable" child or zero
164 HWND
MDI_GetWindow(WND
*clientWnd
, HWND hWnd
, WORD wTo
)
166 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
167 WND
*wndPtr
, *pWnd
, *pWndLast
;
169 if( !hWnd
) hWnd
= clientInfo
->hwndActiveChild
;
171 if( !(wndPtr
= WIN_FindWndPtr(hWnd
)) ) return 0;
178 if (!pWnd
) pWnd
= wndPtr
->parent
->child
;
179 if (pWnd
== wndPtr
) /* not found */
181 if (!wTo
|| !pWndLast
) return 0;
185 /* we are not interested in owned popups */
187 (pWnd
->dwStyle
& WS_VISIBLE
) &&
188 !(pWnd
->dwStyle
& WS_DISABLED
)) /* found one */
194 return pWndLast
? pWndLast
->hwndSelf
: 0;
197 /**********************************************************************
198 * MDI_CalcDefaultChildPos
200 * It seems that default height is 2/3 of client rect
202 void MDI_CalcDefaultChildPos(WND
* w
, WORD n
, LPPOINT16 lpPos
, INT delta
)
204 RECT16 rect
= w
->rectClient
;
205 INT spacing
= GetSystemMetrics(SM_CYCAPTION
) + GetSystemMetrics(SM_CYFRAME
) - 1;
208 if( rect
.bottom
- rect
.top
- delta
>= spacing
)
209 rect
.bottom
-= delta
;
211 nstagger
= (rect
.bottom
- rect
.top
)/(3*spacing
);
212 lpPos
[1].x
= (rect
.right
- rect
.left
- nstagger
*spacing
);
213 lpPos
[1].y
= (rect
.bottom
- rect
.top
- nstagger
*spacing
);
214 lpPos
[0].x
= lpPos
[0].y
= spacing
*(n
%(nstagger
+1));
217 /**********************************************************************
220 HMENU
MDISetMenu(HWND hwnd
, BOOL fRefresh
, HMENU hmenuFrame
, HMENU hmenuWindow
)
222 WND
*w
= WIN_FindWndPtr(hwnd
);
225 dprintf_mdi(stddeb
, "WM_MDISETMENU: %04x %04x %04x %04x\n",
226 hwnd
, fRefresh
, hmenuFrame
, hmenuWindow
);
228 ci
= (MDICLIENTINFO
*) w
->wExtra
;
232 HWND hwndFrame
= GetParent(hwnd
);
233 HMENU oldFrameMenu
= GetMenu(hwndFrame
);
235 if( ci
->hwndChildMaximized
&& hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
236 MDI_RestoreFrameMenu(w
->parent
, ci
->hwndChildMaximized
);
238 if( hmenuWindow
&& hmenuWindow
!=ci
->hWindowMenu
)
240 /* delete menu items from ci->hWindowMenu
241 * and add them to hmenuWindow */
243 INT i
= GetMenuItemCount(ci
->hWindowMenu
) - 1;
244 INT pos
= GetMenuItemCount(hmenuWindow
) + 1;
246 AppendMenu32A( hmenuWindow
, MF_SEPARATOR
, 0, NULL
);
248 if( ci
->nActiveChildren
)
250 INT j
= i
- ci
->nActiveChildren
+ 1;
254 for( ; i
>= j
; i
-- )
256 id
= GetMenuItemID(ci
->hWindowMenu
,i
);
257 state
= GetMenuState(ci
->hWindowMenu
,i
,MF_BYPOSITION
);
259 GetMenuString(ci
->hWindowMenu
, i
, buffer
, 100, MF_BYPOSITION
);
261 DeleteMenu(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
262 InsertMenu32A(hmenuWindow
, pos
, MF_BYPOSITION
| MF_STRING
,
264 CheckMenuItem(hmenuWindow
,pos
, MF_BYPOSITION
| (state
& MF_CHECKED
));
268 /* remove separator */
269 DeleteMenu(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
271 ci
->hWindowMenu
= hmenuWindow
;
274 if( hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
276 SetMenu(hwndFrame
, hmenuFrame
);
277 if( ci
->hwndChildMaximized
)
278 MDI_AugmentFrameMenu(ci
, w
->parent
, ci
->hwndChildMaximized
);
286 /**********************************************************************
289 WORD
MDIIconArrange(HWND parent
)
291 return ArrangeIconicWindows(parent
); /* Any reason why the */
292 /* existing icon arrange */
293 /* can't be used here? */
298 /* ------------------ MDI child window functions ---------------------- */
301 /**********************************************************************
304 HWND
MDICreateChild(WND
*w
, MDICLIENTINFO
*ci
, HWND parent
, LPARAM lParam
)
307 MDICREATESTRUCT16
*cs
= (MDICREATESTRUCT16
*)PTR_SEG_TO_LIN(lParam
);
308 DWORD style
= cs
->style
| (WS_CHILD
| WS_CLIPSIBLINGS
);
309 HWND hwnd
, hwndMax
= 0;
310 WORD wIDmenu
= ci
->idFirstChild
+ ci
->nActiveChildren
;
311 char lpstrDef
[]="junk!";
314 * Create child window
318 dprintf_mdi(stdnimp
,"MDICreateChild: origin %i,%i - dim %i,%i, style %08x\n",
319 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, (unsigned)cs
->style
);
320 /* calculate placement */
321 MDI_CalcDefaultChildPos(w
, ci
->nTotalCreated
++, pos
, 0);
323 if( cs
->cx
== CW_USEDEFAULT16
|| !cs
->cx
)
325 if( cs
->cy
== CW_USEDEFAULT16
|| !cs
->cy
)
328 if( cs
->x
== CW_USEDEFAULT16
)
334 /* restore current maximized child */
335 if( style
& WS_VISIBLE
&& ci
->hwndChildMaximized
)
337 if( style
& WS_MAXIMIZE
)
338 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, FALSE
, 0L );
339 hwndMax
= ci
->hwndChildMaximized
;
340 ShowWindow( hwndMax
, SW_SHOWNOACTIVATE
);
341 if( style
& WS_MAXIMIZE
)
342 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, TRUE
, 0L );
345 /* this menu is needed to set a check mark in MDI_ChildActivate */
346 AppendMenu32A(ci
->hWindowMenu
,MF_STRING
,wIDmenu
, lpstrDef
);
348 ci
->nActiveChildren
++;
350 /* fix window style */
351 if( !(w
->dwStyle
& MDIS_ALLCHILDSTYLES
) )
353 style
&= (WS_CHILD
| WS_CLIPSIBLINGS
| WS_MINIMIZE
| WS_MAXIMIZE
|
354 WS_CLIPCHILDREN
| WS_DISABLED
| WS_VSCROLL
| WS_HSCROLL
);
355 style
|= (WS_VISIBLE
| WS_OVERLAPPEDWINDOW
);
358 hwnd
= CreateWindow16( (LPCSTR
)PTR_SEG_TO_LIN(cs
->szClass
),
359 (LPCSTR
)PTR_SEG_TO_LIN(cs
->szTitle
), style
,
360 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
,
361 (HMENU
)(DWORD
)(WORD
)wIDmenu
, w
->hInstance
,
364 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
368 WND
* wnd
= WIN_FindWndPtr( hwnd
);
370 MDI_MenuModifyItem(w
,hwnd
);
371 if( wnd
->dwStyle
& WS_MINIMIZE
&& ci
->hwndActiveChild
)
372 ShowWindow( hwnd
, SW_SHOWMINNOACTIVE
);
375 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
);
377 /* Set maximized state here in case hwnd didn't receive WM_SIZE
378 * during CreateWindow - bad!
381 if( wnd
->dwStyle
& WS_MAXIMIZE
&& !ci
->hwndChildMaximized
)
383 ci
->hwndChildMaximized
= wnd
->hwndSelf
;
384 MDI_AugmentFrameMenu( ci
, w
->parent
, hwnd
);
385 MDI_UpdateFrameText( w
->parent
, ci
->self
, MDI_REPAINTFRAME
, NULL
);
388 dprintf_mdi(stddeb
, "MDICreateChild: created child - %04x\n",hwnd
);
392 ci
->nActiveChildren
--;
393 DeleteMenu(ci
->hWindowMenu
,wIDmenu
,MF_BYCOMMAND
);
394 if( IsWindow(hwndMax
) )
395 ShowWindow(hwndMax
, SW_SHOWMAXIMIZED
);
401 /**********************************************************************
402 * MDI_ChildGetMinMaxInfo
404 void MDI_ChildGetMinMaxInfo(WND
* clientWnd
, HWND hwnd
, MINMAXINFO16
* lpMinMax
)
406 WND
* childWnd
= WIN_FindWndPtr(hwnd
);
407 RECT16 rect
= clientWnd
->rectClient
;
409 MapWindowPoints16(clientWnd
->parent
->hwndSelf
,
410 ((MDICLIENTINFO
*)clientWnd
->wExtra
)->self
, (LPPOINT16
)&rect
, 2);
411 AdjustWindowRectEx16( &rect
, childWnd
->dwStyle
, 0, childWnd
->dwExStyle
);
413 lpMinMax
->ptMaxSize
.x
= rect
.right
-= rect
.left
;
414 lpMinMax
->ptMaxSize
.y
= rect
.bottom
-= rect
.top
;
416 lpMinMax
->ptMaxPosition
.x
= rect
.left
;
417 lpMinMax
->ptMaxPosition
.y
= rect
.top
;
419 dprintf_mdi(stddeb
,"\tChildMinMaxInfo: max rect (%i,%i - %i, %i)\n",
420 rect
.left
,rect
.top
,rect
.right
,rect
.bottom
);
424 /**********************************************************************
425 * MDI_SwitchActiveChild
427 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
430 * wTo is basically lParam of WM_MDINEXT message or explicit
433 void MDI_SwitchActiveChild(HWND clientHwnd
, HWND childHwnd
, BOOL wTo
)
435 WND
*w
= WIN_FindWndPtr(clientHwnd
);
440 hwndTo
= MDI_GetWindow(w
,childHwnd
,(WORD
)wTo
);
442 ci
= (MDICLIENTINFO
*) w
->wExtra
;
444 dprintf_mdi(stddeb
, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd
,hwndTo
);
446 if ( !hwndTo
) return;
448 hwndPrev
= ci
->hwndActiveChild
;
450 if ( hwndTo
!= hwndPrev
)
454 if( ci
->hwndChildMaximized
)
457 w
->dwStyle
&= ~WS_VISIBLE
;
460 SetWindowPos( hwndTo
, HWND_TOP
, 0, 0, 0, 0,
461 SWP_NOMOVE
| SWP_NOSIZE
);
462 if( !wTo
&& hwndPrev
)
464 SetWindowPos( hwndPrev
, HWND_BOTTOM
, 0, 0, 0, 0,
465 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
469 ShowWindow( clientHwnd
, SW_SHOW
);
474 /**********************************************************************
477 HWND
MDIDestroyChild(WND
*w_parent
, MDICLIENTINFO
*ci
, HWND parent
,
478 HWND child
, BOOL flagDestroy
)
480 WND
*childPtr
= WIN_FindWndPtr(child
);
484 if( child
== ci
->hwndActiveChild
)
486 MDI_SwitchActiveChild(parent
,child
,0);
488 if( child
== ci
->hwndActiveChild
)
490 ShowWindow( child
, SW_HIDE
);
491 if( child
== ci
->hwndChildMaximized
)
493 MDI_RestoreFrameMenu(w_parent
->parent
, child
);
494 ci
->hwndChildMaximized
= 0;
495 MDI_UpdateFrameText(w_parent
->parent
,parent
,TRUE
,NULL
);
498 MDI_ChildActivate(w_parent
,0);
500 MDI_MenuDeleteItem(w_parent
, child
);
503 ci
->nActiveChildren
--;
505 dprintf_mdi(stddeb
,"MDIDestroyChild: child destroyed - %04x\n",child
);
509 MDI_PostUpdate(GetParent(child
), ci
, SB_BOTH
+1);
510 DestroyWindow(child
);
518 /**********************************************************************
521 * Note: hWndChild is NULL when last child is being destroyed
523 LONG
MDI_ChildActivate(WND
*clientPtr
, HWND hWndChild
)
525 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientPtr
->wExtra
;
526 HWND prevActiveWnd
= clientInfo
->hwndActiveChild
;
527 WND
*wndPtr
= WIN_FindWndPtr( hWndChild
);
528 WND
*wndPrev
= WIN_FindWndPtr( prevActiveWnd
);
529 BOOL isActiveFrameWnd
= 0;
531 if( hWndChild
== prevActiveWnd
) return 0L;
534 if( wndPtr
->dwStyle
& WS_DISABLED
) return 0L;
536 dprintf_mdi(stddeb
,"MDI_ChildActivate: %04x\n", hWndChild
);
538 if( GetActiveWindow() == clientPtr
->parent
->hwndSelf
)
539 isActiveFrameWnd
= TRUE
;
541 /* deactivate prev. active child */
544 SendMessage16( prevActiveWnd
, WM_NCACTIVATE
, FALSE
, 0L );
547 SendMessage32A( prevActiveWnd
, WM_MDIACTIVATE
, (WPARAM
)prevActiveWnd
,
551 SendMessage16( prevActiveWnd
, WM_MDIACTIVATE
, FALSE
,
552 MAKELONG(hWndChild
,prevActiveWnd
));
554 /* uncheck menu item */
555 if( clientInfo
->hWindowMenu
)
556 CheckMenuItem( clientInfo
->hWindowMenu
,
557 wndPrev
->wIDmenu
, 0);
561 if( clientInfo
->hwndChildMaximized
)
562 if( clientInfo
->hwndChildMaximized
!= hWndChild
)
565 clientInfo
->hwndActiveChild
= hWndChild
;
566 ShowWindow( hWndChild
, SW_SHOWMAXIMIZED
);
569 ShowWindow( clientInfo
->hwndActiveChild
,
572 clientInfo
->hwndActiveChild
= hWndChild
;
574 /* check if we have any children left */
577 if( isActiveFrameWnd
)
578 SetFocus( clientInfo
->self
);
582 /* check menu item */
583 if( clientInfo
->hWindowMenu
)
584 CheckMenuItem( clientInfo
->hWindowMenu
,
585 wndPtr
->wIDmenu
, MF_CHECKED
);
587 /* bring active child to the top */
588 SetWindowPos( hWndChild
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
590 if( isActiveFrameWnd
)
592 SendMessage16( hWndChild
, WM_NCACTIVATE
, TRUE
, 0L);
593 if( GetFocus() == clientInfo
->self
)
594 SendMessage16( clientInfo
->self
, WM_SETFOCUS
,
595 (WPARAM
)clientInfo
->self
, 0L );
597 SetFocus( clientInfo
->self
);
601 SendMessage32A( hWndChild
, WM_MDIACTIVATE
, (WPARAM
)hWndChild
,
602 (LPARAM
)prevActiveWnd
);
604 SendMessage16( hWndChild
, WM_MDIACTIVATE
, TRUE
,
605 MAKELONG(hWndChild
,prevActiveWnd
));
611 /**********************************************************************
614 * iTotal returns number of children available for tiling or cascading
616 MDIWCL
* MDI_BuildWCL(WND
* clientWnd
, INT16
* iTotal
)
618 MDIWCL
*listTop
,*listNext
;
621 if (!(listTop
= (MDIWCL
*)malloc( sizeof(MDIWCL
) ))) return NULL
;
623 listTop
->hChild
= clientWnd
->child
? clientWnd
->child
->hwndSelf
: 0;
624 listTop
->prev
= NULL
;
627 /* build linked list from top child to bottom */
629 childWnd
= WIN_FindWndPtr( listTop
->hChild
);
630 while( childWnd
&& childWnd
->next
)
632 listNext
= (MDIWCL
*)xmalloc(sizeof(MDIWCL
));
634 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
635 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
636 !(childWnd
->dwStyle
& WS_VISIBLE
) )
642 listNext
->hChild
= childWnd
->next
->hwndSelf
;
643 listNext
->prev
= listTop
;
647 childWnd
= childWnd
->next
;
650 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
651 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
652 !(childWnd
->dwStyle
& WS_VISIBLE
) )
662 /* -------------------- MDI client window functions ------------------- */
664 /**********************************************************************
665 * CreateMDIMenuBitmap
667 HBITMAP
CreateMDIMenuBitmap(void)
669 HDC hDCSrc
= CreateCompatibleDC(0);
670 HDC hDCDest
= CreateCompatibleDC(hDCSrc
);
671 HBITMAP16 hbClose
= LoadBitmap16(0, MAKEINTRESOURCE(OBM_CLOSE
) );
672 HBITMAP16 hbCopy
,hb_src
,hb_dest
;
674 hb_src
= SelectObject(hDCSrc
,hbClose
);
675 hbCopy
= CreateCompatibleBitmap(hDCSrc
,SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
);
676 hb_dest
= SelectObject(hDCDest
,hbCopy
);
678 BitBlt(hDCDest
, 0, 0, SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
,
679 hDCSrc
, SYSMETRICS_CXSIZE
, 0, SRCCOPY
);
681 SelectObject(hDCSrc
,hb_src
);
682 SelectObject(hDCDest
,hb_dest
);
684 DeleteObject(hbClose
);
692 /**********************************************************************
695 LONG
MDICascade(WND
* clientWnd
, MDICLIENTINFO
*ci
)
697 MDIWCL
*listTop
,*listPrev
;
698 INT16 delta
= 0,iToPosition
= 0, n
= 0;
701 if (ci
->hwndChildMaximized
)
702 ShowWindow( ci
->hwndChildMaximized
, SW_NORMAL
);
704 if (ci
->nActiveChildren
== 0) return 0;
706 if (!(listTop
= MDI_BuildWCL(clientWnd
,&iToPosition
))) return 0;
708 if( iToPosition
< ci
->nActiveChildren
)
709 delta
= 2 * SYSMETRICS_CYICONSPACING
+ SYSMETRICS_CYICON
;
711 /* walk list and move windows */
714 dprintf_mdi(stddeb
, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
715 listTop
->hChild
, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
);
717 if( listTop
->hChild
)
719 MDI_CalcDefaultChildPos(clientWnd
, n
++, pos
, delta
);
720 SetWindowPos(listTop
->hChild
, 0, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
,
721 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
724 listPrev
= listTop
->prev
;
729 if( iToPosition
< ci
->nActiveChildren
)
730 ArrangeIconicWindows( clientWnd
->hwndSelf
);
735 /**********************************************************************
739 LONG
MDITile(WND
* wndClient
, MDICLIENTINFO
*ci
,WORD wParam
)
741 MDIWCL
*listTop
,*listPrev
;
748 INT16 iToPosition
= 0;
750 if (ci
->hwndChildMaximized
)
751 ShowWindow(ci
->hwndChildMaximized
, SW_NORMAL
);
753 if (ci
->nActiveChildren
== 0) return 0;
755 listTop
= MDI_BuildWCL(wndClient
, &iToPosition
);
757 dprintf_mdi(stddeb
,"MDITile: %i windows to tile\n",iToPosition
);
759 if( !listTop
) return 0;
764 rect
= wndClient
->rectClient
;
765 rows
= (int) sqrt((double) iToPosition
);
766 columns
= iToPosition
/ rows
;
768 if (wParam
== MDITILE_HORIZONTAL
) /* version >= 3.1 */
771 rows
=columns
; /* exchange r and c */
776 if( iToPosition
!= ci
->nActiveChildren
)
778 y
= rect
.bottom
- 2 * SYSMETRICS_CYICONSPACING
- SYSMETRICS_CYICON
;
779 rect
.bottom
= ( y
- SYSMETRICS_CYICON
< rect
.top
)? rect
.bottom
: y
;
782 ysize
= rect
.bottom
/ rows
;
783 xsize
= rect
.right
/ columns
;
788 for (c
= 1; c
<= columns
; c
++)
792 rows
= iToPosition
- i
;
793 ysize
= rect
.bottom
/ rows
;
797 for (r
= 1; r
<= rows
; r
++, i
++)
799 /* shouldn't happen but... */
803 /* skip iconized childs from tiling */
804 while (!listTop
->hChild
)
806 listPrev
= listTop
->prev
;
810 SetWindowPos(listTop
->hChild
, 0, x
, y
, xsize
, ysize
,
811 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
813 listPrev
= listTop
->prev
;
821 /* free the rest if any */
824 listPrev
= listTop
->prev
;
829 if (iToPosition
< ci
->nActiveChildren
)
830 ArrangeIconicWindows( wndClient
->hwndSelf
);
835 /* ----------------------- Frame window ---------------------------- */
838 /**********************************************************************
839 * MDI_AugmentFrameMenu
841 BOOL
MDI_AugmentFrameMenu(MDICLIENTINFO
* ci
, WND
*frame
, HWND hChild
)
843 WND
* child
= WIN_FindWndPtr(hChild
);
847 dprintf_mdi(stddeb
,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame
,hChild
);
849 if( !frame
->wIDmenu
|| !child
->hSysMenu
) return 0;
851 /* create a copy of sysmenu popup and insert it into frame menu bar */
853 if (!(handle
= SYSRES_LoadResource( SYSRES_MENU_SYSMENU
))) return 0;
854 hSysPopup
= LoadMenuIndirect16( GlobalLock16( handle
) );
855 SYSRES_FreeResource( handle
);
857 dprintf_mdi(stddeb
,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup
,child
->hSysMenu
);
859 if( !InsertMenu32A(frame
->wIDmenu
,0,MF_BYPOSITION
| MF_BITMAP
| MF_POPUP
,
860 hSysPopup
, (LPSTR
)(DWORD
)hBmpClose
))
861 { DestroyMenu(hSysPopup
); return 0; }
863 if( !AppendMenu32A(frame
->wIDmenu
,MF_HELP
| MF_BITMAP
,
864 SC_RESTORE
, (LPSTR
)(DWORD
)hBmpRestore
))
866 RemoveMenu(frame
->wIDmenu
,0,MF_BYPOSITION
);
870 EnableMenuItem(hSysPopup
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
871 EnableMenuItem(hSysPopup
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
872 EnableMenuItem(hSysPopup
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
874 child
->dwStyle
&= ~WS_SYSMENU
;
877 DrawMenuBar(frame
->hwndSelf
);
882 /**********************************************************************
883 * MDI_RestoreFrameMenu
885 BOOL
MDI_RestoreFrameMenu( WND
*frameWnd
, HWND hChild
)
887 WND
* child
= WIN_FindWndPtr(hChild
);
888 INT nItems
= GetMenuItemCount(frameWnd
->wIDmenu
) - 1;
890 dprintf_mdi(stddeb
,"MDI_RestoreFrameMenu: for child %04x\n",hChild
);
892 if( GetMenuItemID(frameWnd
->wIDmenu
,nItems
) != SC_RESTORE
)
895 child
->dwStyle
|= WS_SYSMENU
;
897 RemoveMenu(frameWnd
->wIDmenu
,0,MF_BYPOSITION
);
898 DeleteMenu(frameWnd
->wIDmenu
,nItems
-1,MF_BYPOSITION
);
900 DrawMenuBar(frameWnd
->hwndSelf
);
905 /**********************************************************************
906 * MDI_UpdateFrameText
908 * used when child window is maximized/restored
910 * Note: lpTitle can be NULL
912 void MDI_UpdateFrameText(WND
*frameWnd
, HWND hClient
, BOOL repaint
, LPCSTR lpTitle
)
914 char lpBuffer
[MDI_MAXTITLELENGTH
+1];
915 WND
* clientWnd
= WIN_FindWndPtr(hClient
);
917 MDICLIENTINFO
*ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
919 dprintf_mdi(stddeb
, "MDI: repaint %i, frameText %s\n", repaint
, (lpTitle
)?lpTitle
:"NULL");
921 /* store new "default" title if lpTitle is not NULL */
924 if (ci
->frameTitle
) HeapFree( SystemHeap
, 0, ci
->frameTitle
);
925 ci
->frameTitle
= HEAP_strdupA( SystemHeap
, 0, lpTitle
);
930 WND
* childWnd
= WIN_FindWndPtr( ci
->hwndChildMaximized
);
932 if( childWnd
&& childWnd
->text
)
934 /* combine frame title and child title if possible */
936 LPCSTR lpBracket
= " - [";
937 int i_frame_text_length
= strlen(ci
->frameTitle
);
938 int i_child_text_length
= strlen(childWnd
->text
);
940 lstrcpyn32A( lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
942 if( i_frame_text_length
+ 6 < MDI_MAXTITLELENGTH
)
944 strcat( lpBuffer
, lpBracket
);
946 if( i_frame_text_length
+ i_child_text_length
+ 6 < MDI_MAXTITLELENGTH
)
948 strcat( lpBuffer
, childWnd
->text
);
949 strcat( lpBuffer
, "]" );
953 lstrcpyn32A( lpBuffer
+ i_frame_text_length
+ 4,
955 MDI_MAXTITLELENGTH
- i_frame_text_length
- 5 );
956 strcat( lpBuffer
, "]" );
962 strncpy(lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
963 lpBuffer
[MDI_MAXTITLELENGTH
]='\0';
969 DEFWND_SetText( frameWnd
, lpBuffer
);
970 if( repaint
== MDI_REPAINTFRAME
)
971 SetWindowPos(frameWnd
->hwndSelf
, 0,0,0,0,0, SWP_FRAMECHANGED
|
972 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
976 /* ----------------------------- Interface ---------------------------- */
979 /**********************************************************************
982 * This function is the handler for all MDI requests.
984 LRESULT
MDIClientWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
987 LPCLIENTCREATESTRUCT16 ccs
;
990 WND
*w
= WIN_FindWndPtr(hwnd
);
991 WND
*frameWnd
= w
->parent
;
993 ci
= (MDICLIENTINFO
*) w
->wExtra
;
998 cs
= (LPCREATESTRUCT16
) PTR_SEG_TO_LIN(lParam
);
999 ccs
= (LPCLIENTCREATESTRUCT16
) PTR_SEG_TO_LIN(cs
->lpCreateParams
);
1001 ci
->hWindowMenu
= ccs
->hWindowMenu
;
1002 ci
->idFirstChild
= ccs
->idFirstChild
;
1003 ci
->hwndChildMaximized
= 0;
1004 ci
->nActiveChildren
= 0;
1005 ci
->nTotalCreated
= 0;
1006 ci
->frameTitle
= NULL
;
1007 ci
->sbNeedUpdate
= 0;
1009 w
->dwStyle
|= WS_CLIPCHILDREN
;
1013 hBmpClose
= CreateMDIMenuBitmap();
1014 hBmpRestore
= LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORE
) );
1016 MDI_UpdateFrameText(frameWnd
, hwnd
, MDI_NOFRAMEREPAINT
,frameWnd
->text
);
1018 AppendMenu32A( ccs
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
1020 GetClientRect16(frameWnd
->hwndSelf
, &rect
);
1021 NC_HandleNCCalcSize( w
, &rect
);
1022 w
->rectClient
= rect
;
1024 dprintf_mdi(stddeb
,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd
,ci
->idFirstChild
);
1029 if( ci
->hwndChildMaximized
) MDI_RestoreFrameMenu(w
, frameWnd
->hwndSelf
);
1030 ci
->idFirstChild
= GetMenuItemCount(ci
->hWindowMenu
) - 1;
1031 ci
->nActiveChildren
++; /* to delete a separator */
1033 while( ci
->nActiveChildren
-- )
1034 DeleteMenu(ci
->hWindowMenu
,MF_BYPOSITION
,ci
->idFirstChild
--);
1038 case WM_MDIACTIVATE
:
1039 if( ci
->hwndActiveChild
!= (HWND
)wParam
)
1040 SetWindowPos((HWND
)wParam
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1044 return MDICascade(w
, ci
);
1047 return (LONG
)MDICreateChild(w
, ci
, hwnd
, lParam
);
1050 return (LONG
)MDIDestroyChild(w
, ci
, hwnd
, (HWND
)wParam
, TRUE
);
1052 case WM_MDIGETACTIVE
:
1053 return ((LONG
) ci
->hwndActiveChild
|
1054 ((LONG
) (ci
->hwndChildMaximized
>0) << 16));
1056 case WM_MDIICONARRANGE
:
1057 ci
->sbNeedUpdate
= TRUE
;
1058 MDIIconArrange(hwnd
);
1059 ci
->sbRecalc
= SB_BOTH
+1;
1060 SendMessage16(hwnd
,WM_MDICALCCHILDSCROLL
,0,0L);
1063 case WM_MDIMAXIMIZE
:
1064 ShowWindow((HWND
)wParam
, SW_MAXIMIZE
);
1068 MDI_SwitchActiveChild(hwnd
, (HWND
)wParam
, (lParam
)?1:0);
1072 ShowWindow( (HWND
)wParam
, SW_NORMAL
);
1077 return (LRESULT
)MDISetMenu(hwnd
, FALSE
, (HMENU
)wParam
, (HMENU
)lParam
);
1079 return (LRESULT
)MDISetMenu(hwnd
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1083 ci
->sbNeedUpdate
= TRUE
;
1084 ShowScrollBar(hwnd
,SB_BOTH
,FALSE
);
1085 MDITile(w
, ci
,wParam
);
1086 ci
->sbNeedUpdate
= FALSE
;
1091 ci
->sbNeedUpdate
= TRUE
;
1092 ScrollChildren(hwnd
,message
,wParam
,lParam
);
1093 ci
->sbNeedUpdate
= FALSE
;
1097 if( ci
->hwndActiveChild
)
1099 w
= WIN_FindWndPtr( ci
->hwndActiveChild
);
1100 if( !(w
->dwStyle
& WS_MINIMIZE
) )
1101 SetFocus( ci
->hwndActiveChild
);
1106 if( ci
->hwndActiveChild
)
1107 SendMessage16(ci
->hwndActiveChild
, message
, wParam
, lParam
);
1110 case WM_PARENTNOTIFY
:
1111 if( wParam
== WM_LBUTTONDOWN
)
1113 POINT16 pt
= MAKEPOINT16(lParam
);
1114 HWND child
= ChildWindowFromPoint16(hwnd
, pt
);
1116 dprintf_mdi(stddeb
,"MDIClient: notification from %04x (%i,%i)\n",child
,pt
.x
,pt
.y
);
1118 if( child
&& child
!= hwnd
)
1120 WND
* wnd
= WIN_FindWndPtr( child
);
1122 /* if we got owned popup */
1123 if( wnd
->owner
) child
= wnd
->owner
->hwndSelf
;
1125 if( child
!= ci
->hwndActiveChild
)
1126 SetWindowPos(child
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1132 if( ci
->hwndChildMaximized
)
1134 WND
* child
= WIN_FindWndPtr(ci
->hwndChildMaximized
);
1135 RECT16 rect
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
1137 AdjustWindowRectEx16(&rect
, child
->dwStyle
, 0, child
->dwExStyle
);
1138 MoveWindow(ci
->hwndChildMaximized
, rect
.left
, rect
.top
,
1139 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, 1);
1142 MDI_PostUpdate(hwnd
, ci
, SB_BOTH
+1);
1146 case WM_MDICALCCHILDSCROLL
:
1147 if( ci
->sbNeedUpdate
)
1150 CalcChildScroll(hwnd
, ci
->sbRecalc
-1);
1151 ci
->sbRecalc
= ci
->sbNeedUpdate
= 0;
1156 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1160 /***********************************************************************
1161 * DefFrameProc16 (USER.445)
1163 LRESULT
DefFrameProc16( HWND16 hwnd
, HWND16 hwndMDIClient
, UINT16 message
,
1164 WPARAM16 wParam
, LPARAM lParam
)
1175 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1176 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1178 /* check for possible syscommands for maximized MDI child */
1180 if( wParam
< ci
->idFirstChild
||
1181 wParam
>= ci
->idFirstChild
+ ci
->nActiveChildren
)
1183 if( (wParam
- 0xF000) & 0xF00F ) break;
1194 if( ci
->hwndChildMaximized
)
1195 return SendMessage16( ci
->hwndChildMaximized
, WM_SYSCOMMAND
,
1201 childHwnd
= MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient
),
1204 SendMessage16(hwndMDIClient
, WM_MDIACTIVATE
, (WPARAM
)childHwnd
, 0L);
1209 SendMessage16(hwndMDIClient
, message
, wParam
, lParam
);
1213 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd
), hwndMDIClient
,
1215 (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1219 SetFocus(hwndMDIClient
);
1223 MoveWindow(hwndMDIClient
, 0, 0,
1224 LOWORD(lParam
), HIWORD(lParam
), TRUE
);
1229 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1233 /***********************************************************************
1234 * DefFrameProc32A (USER32.121)
1236 LRESULT
DefFrameProc32A( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1237 WPARAM32 wParam
, LPARAM lParam
)
1244 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1246 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1249 SendMessage32A(hwndMDIClient
, message
, wParam
, lParam
);
1253 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1254 wParam
, (LPARAM
)PTR_SEG_TO_LIN(lParam
) );
1258 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1263 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1267 /***********************************************************************
1268 * DefFrameProc32W (USER32.122)
1270 LRESULT
DefFrameProc32W( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1271 WPARAM32 wParam
, LPARAM lParam
)
1278 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1280 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1283 SendMessage32W(hwndMDIClient
, message
, wParam
, lParam
);
1287 /* FIXME: Unicode */
1288 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1293 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1298 return DefWindowProc32W( hwnd
, message
, wParam
, lParam
);
1302 /***********************************************************************
1303 * DefMDIChildProc16 (USER.447)
1305 LRESULT
DefMDIChildProc16( HWND16 hwnd
, UINT16 message
,
1306 WPARAM16 wParam
, LPARAM lParam
)
1311 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1312 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1317 DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1318 MDI_MenuModifyItem(clientWnd
,hwnd
);
1319 if( ci
->hwndChildMaximized
== hwnd
)
1320 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1321 MDI_REPAINTFRAME
, NULL
);
1325 SendMessage16(ci
->self
,WM_MDIDESTROY
,(WPARAM
)hwnd
,0L);
1329 if( ci
->hwndActiveChild
!= hwnd
)
1330 MDI_ChildActivate(clientWnd
, hwnd
);
1333 case WM_CHILDACTIVATE
:
1334 MDI_ChildActivate(clientWnd
, hwnd
);
1338 dprintf_mdi(stddeb
,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
1339 hwnd
, ci
->hwndActiveChild
);
1346 if( ci
->hwndChildMaximized
== hwnd
) return 0;
1349 if( ci
->hwndChildMaximized
== hwnd
)
1350 return SendMessage16( clientWnd
->parent
->hwndSelf
,
1351 message
, wParam
, lParam
);
1354 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 0);
1357 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 1);
1362 case WM_GETMINMAXINFO
:
1363 MDI_ChildGetMinMaxInfo(clientWnd
, hwnd
, (MINMAXINFO16
*) PTR_SEG_TO_LIN(lParam
));
1367 if( ci
->hwndChildMaximized
)
1368 ci
->sbNeedUpdate
= 0;
1370 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1376 if( ci
->hwndActiveChild
== hwnd
&& wParam
!= SIZE_MAXIMIZED
)
1378 ci
->hwndChildMaximized
= 0;
1380 MDI_RestoreFrameMenu( clientWnd
->parent
, hwnd
);
1381 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1382 MDI_REPAINTFRAME
, NULL
);
1385 if( wParam
== SIZE_MAXIMIZED
)
1387 HWND hMaxChild
= ci
->hwndChildMaximized
;
1389 if( hMaxChild
== hwnd
) break;
1393 SendMessage16( hMaxChild
, WM_SETREDRAW
, FALSE
, 0L );
1395 MDI_RestoreFrameMenu( clientWnd
->parent
, hMaxChild
);
1396 ShowWindow( hMaxChild
, SW_SHOWNOACTIVATE
);
1398 SendMessage16( hMaxChild
, WM_SETREDRAW
, TRUE
, 0L );
1401 dprintf_mdi(stddeb
,"\tMDI: maximizing child %04x\n", hwnd
);
1403 ci
->hwndChildMaximized
= hwnd
; /* !!! */
1405 MDI_AugmentFrameMenu( ci
, clientWnd
->parent
, hwnd
);
1406 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1407 MDI_REPAINTFRAME
, NULL
);
1410 if( wParam
== SIZE_MINIMIZED
)
1412 HWND switchTo
= MDI_GetWindow(clientWnd
, hwnd
, 0);
1415 SendMessage16( switchTo
, WM_CHILDACTIVATE
, 0, 0L);
1418 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1423 /* MDI children don't have menus */
1424 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1425 (WPARAM
)SC_KEYMENU
, (LPARAM
)wParam
);
1429 /* set current menu to child system menu */
1434 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1438 /***********************************************************************
1439 * DefMDIChildProc32A (USER32.123)
1441 LRESULT
DefMDIChildProc32A( HWND32 hwnd
, UINT32 message
,
1442 WPARAM32 wParam
, LPARAM lParam
)
1447 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1448 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1453 DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1454 MDI_MenuModifyItem(clientWnd
,hwnd
);
1455 if( ci
->hwndChildMaximized
== hwnd
)
1456 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1457 MDI_REPAINTFRAME
, NULL
);
1460 case WM_GETMINMAXINFO
:
1463 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32
*)lParam
, &mmi
);
1464 MDI_ChildGetMinMaxInfo( clientWnd
, hwnd
, &mmi
);
1465 STRUCT32_MINMAXINFO16to32( &mmi
, (MINMAXINFO32
*)lParam
);
1471 /* MDI children don't have menus */
1472 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1473 (WPARAM
)SC_KEYMENU
, (LPARAM
)LOWORD(wParam
) );
1478 case WM_CHILDACTIVATE
:
1484 return DefMDIChildProc16( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1486 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1490 /***********************************************************************
1491 * DefMDIChildProc32W (USER32.124)
1493 LRESULT
DefMDIChildProc32W( HWND32 hwnd
, UINT32 message
,
1494 WPARAM32 wParam
, LPARAM lParam
)
1499 clientWnd
= WIN_FindWndPtr(GetParent(hwnd
));
1500 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1505 DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1506 MDI_MenuModifyItem(clientWnd
,hwnd
);
1507 if( ci
->hwndChildMaximized
== hwnd
)
1508 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1509 MDI_REPAINTFRAME
, NULL
);
1512 case WM_GETMINMAXINFO
:
1516 case WM_CHILDACTIVATE
:
1522 return DefMDIChildProc32A( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1524 return DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1528 /**********************************************************************
1529 * TranslateMDISysAccel (USER.451)
1532 BOOL
TranslateMDISysAccel(HWND hwndClient
, LPMSG16 msg
)
1534 WND
* clientWnd
= WIN_FindWndPtr( hwndClient
);
1536 MDICLIENTINFO
*ci
= NULL
;
1539 if( (msg
->message
!= WM_KEYDOWN
&& msg
->message
!= WM_SYSKEYDOWN
) || !clientWnd
)
1542 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1543 wnd
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1545 if( !wnd
) return 0;
1547 if( wnd
->dwStyle
& WS_DISABLED
) return 0;
1549 if ((GetKeyState(VK_CONTROL
) & 0x8000) && !(GetKeyState(VK_MENU
) & 0x8000))
1550 switch( msg
->wParam
)
1554 wParam
= ( GetKeyState(VK_SHIFT
) & 0x8000 )? SC_NEXTWINDOW
: SC_PREVWINDOW
;
1565 dprintf_mdi(stddeb
,"TranslateMDISysAccel: wParam = %04x\n", wParam
);
1567 SendMessage16(ci
->hwndActiveChild
,WM_SYSCOMMAND
, wParam
, (LPARAM
)msg
->wParam
);
1572 /***********************************************************************
1573 * CalcChildScroll (USER.462)
1575 void CalcChildScroll( HWND hwnd
, WORD scroll
)
1577 RECT16 childRect
, clientRect
;
1578 INT vmin
, vmax
, hmin
, hmax
, vpos
, hpos
;
1579 BOOL noscroll
= FALSE
;
1582 if (!(Wnd
= pWnd
= WIN_FindWndPtr( hwnd
))) return;
1583 GetClientRect16( hwnd
, &clientRect
);
1584 SetRectEmpty16( &childRect
);
1586 for ( pWnd
= pWnd
->child
; pWnd
; pWnd
= pWnd
->next
)
1588 UnionRect16( &childRect
, &pWnd
->rectWindow
, &childRect
);
1589 if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1592 UnionRect16( &childRect
, &clientRect
, &childRect
);
1594 /* jump through the hoops to prevent excessive flashing
1597 hmin
= childRect
.left
; hmax
= childRect
.right
- clientRect
.right
;
1598 hpos
= clientRect
.left
- childRect
.left
;
1599 vmin
= childRect
.top
; vmax
= childRect
.bottom
- clientRect
.bottom
;
1600 vpos
= clientRect
.top
- childRect
.top
;
1603 ShowScrollBar(hwnd
, SB_BOTH
, FALSE
);
1608 vpos
= hpos
; vmin
= hmin
; vmax
= hmax
;
1610 SetScrollPos(hwnd
, scroll
, vpos
, FALSE
);
1611 SetScrollRange(hwnd
, scroll
, vmin
, vmax
, TRUE
);
1614 SCROLL_SetNCSbState( Wnd
, vmin
, vmax
, vpos
,
1616 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
1617 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1621 /***********************************************************************
1622 * ScrollChildren (USER.463)
1624 void ScrollChildren(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1626 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1634 if( !wndPtr
) return;
1636 if( uMsg
== WM_HSCROLL
)
1638 GetScrollRange(hWnd
,SB_HORZ
,&minPos
,&maxPos
);
1639 curPos
= GetScrollPos(hWnd
,SB_HORZ
);
1640 length
= (wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
)/2;
1641 shift
= SYSMETRICS_CYHSCROLL
;
1643 else if( uMsg
== WM_VSCROLL
)
1645 GetScrollRange(hWnd
,SB_VERT
,&minPos
,&maxPos
);
1646 curPos
= GetScrollPos(hWnd
,SB_VERT
);
1647 length
= (wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
)/2;
1648 shift
= SYSMETRICS_CXVSCROLL
;
1655 newPos
= curPos
- shift
;
1658 newPos
= curPos
+ shift
;
1661 newPos
= curPos
- length
;
1664 newPos
= curPos
+ length
;
1667 case SB_THUMBPOSITION
:
1668 newPos
= LOWORD(lParam
);
1681 CalcChildScroll(hWnd
,(uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
);
1685 if( newPos
> maxPos
)
1687 else if( newPos
< minPos
)
1690 SetScrollPos(hWnd
, (uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
, newPos
, TRUE
);
1692 if( uMsg
== WM_VSCROLL
)
1693 ScrollWindow(hWnd
,0 ,curPos
- newPos
, NULL
, NULL
);
1695 ScrollWindow(hWnd
,curPos
- newPos
, 0, NULL
, NULL
);