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"
29 #include "sysmetrics.h"
33 #define MDIF_NEEDUPDATE 0x0001
36 static HBITMAP16 hBmpClose
= 0;
37 static HBITMAP16 hBmpRestore
= 0;
39 DWORD
SCROLL_SetNCSbState(WND
*,int,int,int,int,int,int);
41 /* ----------------- declarations ----------------- */
42 static void MDI_UpdateFrameText(WND
*, HWND16
, BOOL32
, LPCSTR
);
43 static BOOL32
MDI_AugmentFrameMenu(MDICLIENTINFO
*, WND
*, HWND16
);
44 static BOOL32
MDI_RestoreFrameMenu(WND
*, HWND16
);
46 static LONG
MDI_ChildActivate(WND
* ,HWND16
);
48 /* -------- Miscellaneous service functions ----------
53 static HWND16
MDI_GetChildByID(WND
* wndPtr
,int id
)
55 for (wndPtr
= wndPtr
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
56 if (wndPtr
->wIDmenu
== id
) return wndPtr
->hwndSelf
;
60 static void MDI_PostUpdate(HWND16 hwnd
, MDICLIENTINFO
* ci
, WORD recalc
)
62 if( !(ci
->mdiFlags
& MDIF_NEEDUPDATE
) )
64 ci
->mdiFlags
|= MDIF_NEEDUPDATE
;
65 PostMessage16( hwnd
, WM_MDICALCCHILDSCROLL
, 0, 0);
67 ci
->sbRecalc
= recalc
;
70 /**********************************************************************
73 #ifdef SUPERFLUOUS_FUNCTIONS
74 static BOOL32
MDI_MenuAppendItem(WND
*clientWnd
, HWND16 hWndChild
)
77 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
78 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
79 int n
= sprintf(buffer
, "%d ",
80 clientInfo
->nActiveChildren
);
82 if( !clientInfo
->hWindowMenu
) return 0;
84 if (wndPtr
->text
) strncpy(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
- 1);
85 return AppendMenu32A( clientInfo
->hWindowMenu
, MF_STRING
,
86 wndPtr
->wIDmenu
, buffer
);
90 /**********************************************************************
93 static BOOL32
MDI_MenuModifyItem(WND
* clientWnd
, HWND16 hWndChild
)
96 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
97 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
98 UINT32 n
= sprintf(buffer
, "%d ",
99 wndPtr
->wIDmenu
- clientInfo
->idFirstChild
+ 1);
102 if( !clientInfo
->hWindowMenu
) return 0;
104 if (wndPtr
->text
) lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
106 n
= GetMenuState32(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
,MF_BYCOMMAND
);
107 bRet
= ModifyMenu32A(clientInfo
->hWindowMenu
, wndPtr
->wIDmenu
,
108 MF_BYCOMMAND
| MF_STRING
, wndPtr
->wIDmenu
, buffer
);
109 CheckMenuItem32(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
, n
& MF_CHECKED
);
113 /**********************************************************************
116 static BOOL32
MDI_MenuDeleteItem(WND
* clientWnd
, HWND16 hWndChild
)
119 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
120 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
121 UINT32 index
= 0,id
,n
;
123 if( !clientInfo
->nActiveChildren
||
124 !clientInfo
->hWindowMenu
) return 0;
126 id
= wndPtr
->wIDmenu
;
127 DeleteMenu32(clientInfo
->hWindowMenu
,id
,MF_BYCOMMAND
);
129 /* walk the rest of MDI children to prevent gaps in the id
130 * sequence and in the menu child list */
132 for( index
= id
+1; index
<= clientInfo
->nActiveChildren
+
133 clientInfo
->idFirstChild
; index
++ )
135 wndPtr
= WIN_FindWndPtr(MDI_GetChildByID(clientWnd
,index
));
138 dprintf_mdi(stddeb
,"MDIMenuDeleteItem: no window for id=%i\n",index
);
145 n
= sprintf(buffer
, "%d ",index
- clientInfo
->idFirstChild
);
147 lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
150 ModifyMenu32A(clientInfo
->hWindowMenu
,index
,MF_BYCOMMAND
| MF_STRING
,
151 index
- 1 , buffer
);
156 /**********************************************************************
159 * returns "activateable" child or zero
161 static HWND16
MDI_GetWindow(WND
*clientWnd
, HWND16 hWnd
, WORD wTo
)
163 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
164 WND
*wndPtr
, *pWnd
, *pWndLast
;
166 if( !hWnd
) hWnd
= clientInfo
->hwndActiveChild
;
168 if( !(wndPtr
= WIN_FindWndPtr(hWnd
)) ) return 0;
175 if (!pWnd
) pWnd
= wndPtr
->parent
->child
;
176 if (pWnd
== wndPtr
) /* not found */
178 if (!wTo
|| !pWndLast
) return 0;
182 if ( !pWnd
->owner
&& (pWnd
->dwStyle
&
183 (WS_VISIBLE
| WS_DISABLED
)) == WS_VISIBLE
)
189 return pWndLast
? pWndLast
->hwndSelf
: 0;
192 /**********************************************************************
193 * MDI_CalcDefaultChildPos
195 * It seems that default height is 2/3 of client rect
197 static void MDI_CalcDefaultChildPos( WND
* w
, WORD n
, LPPOINT16 lpPos
,
200 RECT32 rect
= w
->rectClient
;
201 INT32 spacing
= GetSystemMetrics32(SM_CYCAPTION
) +
202 GetSystemMetrics32(SM_CYFRAME
) - 1;
205 if( rect
.bottom
- rect
.top
- delta
>= spacing
)
206 rect
.bottom
-= delta
;
208 nstagger
= (rect
.bottom
- rect
.top
)/(3*spacing
);
209 lpPos
[1].x
= (rect
.right
- rect
.left
- nstagger
*spacing
);
210 lpPos
[1].y
= (rect
.bottom
- rect
.top
- nstagger
*spacing
);
211 lpPos
[0].x
= lpPos
[0].y
= spacing
*(n
%(nstagger
+1));
214 /**********************************************************************
217 static HMENU16
MDISetMenu(HWND16 hwnd
, BOOL32 fRefresh
, HMENU16 hmenuFrame
,
220 WND
*w
= WIN_FindWndPtr(hwnd
);
223 dprintf_mdi(stddeb
, "WM_MDISETMENU: %04x %04x %04x %04x\n",
224 hwnd
, fRefresh
, hmenuFrame
, hmenuWindow
);
226 ci
= (MDICLIENTINFO
*) w
->wExtra
;
230 HWND16 hwndFrame
= GetParent16(hwnd
);
231 HMENU32 oldFrameMenu
= GetMenu32(hwndFrame
);
233 if( ci
->hwndChildMaximized
&& hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
234 MDI_RestoreFrameMenu(w
->parent
, ci
->hwndChildMaximized
);
236 if( hmenuWindow
&& hmenuWindow
!=ci
->hWindowMenu
)
238 /* delete menu items from ci->hWindowMenu
239 * and add them to hmenuWindow */
241 INT32 i
= GetMenuItemCount32(ci
->hWindowMenu
) - 1;
242 INT32 pos
= GetMenuItemCount32(hmenuWindow
) + 1;
244 AppendMenu32A( hmenuWindow
, MF_SEPARATOR
, 0, NULL
);
246 if( ci
->nActiveChildren
)
248 INT32 j
= i
- ci
->nActiveChildren
+ 1;
252 for( ; i
>= j
; i
-- )
254 id
= GetMenuItemID32(ci
->hWindowMenu
,i
);
255 state
= GetMenuState32(ci
->hWindowMenu
,i
,MF_BYPOSITION
);
257 GetMenuString32A(ci
->hWindowMenu
, i
, buffer
, 100, MF_BYPOSITION
);
259 DeleteMenu32(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
260 InsertMenu32A(hmenuWindow
, pos
, MF_BYPOSITION
| MF_STRING
,
262 CheckMenuItem32(hmenuWindow
,pos
, MF_BYPOSITION
| (state
& MF_CHECKED
));
266 /* remove separator */
267 DeleteMenu32(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
269 ci
->hWindowMenu
= hmenuWindow
;
272 if( hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
274 SetMenu32(hwndFrame
, hmenuFrame
);
275 if( ci
->hwndChildMaximized
)
276 MDI_AugmentFrameMenu(ci
, w
->parent
, ci
->hwndChildMaximized
);
284 /**********************************************************************
287 static WORD
MDIIconArrange(HWND16 parent
)
289 return ArrangeIconicWindows16(parent
); /* Any reason why the */
290 /* existing icon arrange */
291 /* can't be used here? */
296 /* ------------------ MDI child window functions ---------------------- */
299 /**********************************************************************
302 static HWND16
MDICreateChild( WND
*w
, MDICLIENTINFO
*ci
, HWND16 parent
,
303 LPMDICREATESTRUCT16 cs
, LPARAM lParam
)
306 DWORD style
= cs
->style
| (WS_CHILD
| WS_CLIPSIBLINGS
);
307 HWND16 hwnd
, hwndMax
= 0;
308 WORD wIDmenu
= ci
->idFirstChild
+ ci
->nActiveChildren
;
309 char lpstrDef
[]="junk!";
311 dprintf_mdi(stdnimp
,"MDICreateChild: origin %i,%i - dim %i,%i, style %08x\n",
312 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, (unsigned)cs
->style
);
313 /* calculate placement */
314 MDI_CalcDefaultChildPos(w
, ci
->nTotalCreated
++, pos
, 0);
316 if( cs
->cx
== CW_USEDEFAULT16
|| !cs
->cx
)
318 if( cs
->cy
== CW_USEDEFAULT16
|| !cs
->cy
)
321 if( cs
->x
== CW_USEDEFAULT16
)
327 /* restore current maximized child */
328 if( style
& WS_VISIBLE
&& ci
->hwndChildMaximized
)
330 if( style
& WS_MAXIMIZE
)
331 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, FALSE
, 0L );
332 hwndMax
= ci
->hwndChildMaximized
;
333 ShowWindow16( hwndMax
, SW_SHOWNOACTIVATE
);
334 if( style
& WS_MAXIMIZE
)
335 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, TRUE
, 0L );
338 /* this menu is needed to set a check mark in MDI_ChildActivate */
339 AppendMenu32A(ci
->hWindowMenu
,MF_STRING
,wIDmenu
, lpstrDef
);
341 ci
->nActiveChildren
++;
343 /* fix window style */
344 if( !(w
->dwStyle
& MDIS_ALLCHILDSTYLES
) )
346 style
&= (WS_CHILD
| WS_CLIPSIBLINGS
| WS_MINIMIZE
| WS_MAXIMIZE
|
347 WS_CLIPCHILDREN
| WS_DISABLED
| WS_VSCROLL
| WS_HSCROLL
);
348 style
|= (WS_VISIBLE
| WS_OVERLAPPEDWINDOW
);
351 hwnd
= CreateWindow16( (LPCSTR
)PTR_SEG_TO_LIN(cs
->szClass
),
352 (LPCSTR
)PTR_SEG_TO_LIN(cs
->szTitle
), style
,
353 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
,
354 (HMENU16
)wIDmenu
, w
->hInstance
,
357 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
361 WND
* wnd
= WIN_FindWndPtr( hwnd
);
363 MDI_MenuModifyItem(w
,hwnd
);
364 if( wnd
->dwStyle
& WS_MINIMIZE
&& ci
->hwndActiveChild
)
365 ShowWindow16( hwnd
, SW_SHOWMINNOACTIVE
);
368 SetWindowPos32( hwnd
, 0, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
);
370 /* Set maximized state here in case hwnd didn't receive WM_SIZE
371 * during CreateWindow - bad!
374 if( wnd
->dwStyle
& WS_MAXIMIZE
&& !ci
->hwndChildMaximized
)
376 ci
->hwndChildMaximized
= wnd
->hwndSelf
;
377 MDI_AugmentFrameMenu( ci
, w
->parent
, hwnd
);
378 MDI_UpdateFrameText( w
->parent
, ci
->self
, MDI_REPAINTFRAME
, NULL
);
381 dprintf_mdi(stddeb
, "MDICreateChild: created child - %04x\n",hwnd
);
385 ci
->nActiveChildren
--;
386 DeleteMenu32(ci
->hWindowMenu
,wIDmenu
,MF_BYCOMMAND
);
387 if( IsWindow32(hwndMax
) )
388 ShowWindow32(hwndMax
, SW_SHOWMAXIMIZED
);
394 /**********************************************************************
395 * MDI_ChildGetMinMaxInfo
397 static void MDI_ChildGetMinMaxInfo( WND
* clientWnd
, HWND16 hwnd
,
398 MINMAXINFO16
* lpMinMax
)
400 WND
* childWnd
= WIN_FindWndPtr(hwnd
);
401 RECT32 rect
= clientWnd
->rectClient
;
403 MapWindowPoints32(clientWnd
->parent
->hwndSelf
,
404 ((MDICLIENTINFO
*)clientWnd
->wExtra
)->self
,
405 (LPPOINT32
)&rect
, 2);
406 AdjustWindowRectEx32( &rect
, childWnd
->dwStyle
, 0, childWnd
->dwExStyle
);
408 lpMinMax
->ptMaxSize
.x
= rect
.right
-= rect
.left
;
409 lpMinMax
->ptMaxSize
.y
= rect
.bottom
-= rect
.top
;
411 lpMinMax
->ptMaxPosition
.x
= rect
.left
;
412 lpMinMax
->ptMaxPosition
.y
= rect
.top
;
414 dprintf_mdi(stddeb
,"\tChildMinMaxInfo: max rect (%i,%i - %i, %i)\n",
415 rect
.left
,rect
.top
,rect
.right
,rect
.bottom
);
419 /**********************************************************************
420 * MDI_SwitchActiveChild
422 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
425 * wTo is basically lParam of WM_MDINEXT message or explicit
428 static void MDI_SwitchActiveChild( HWND16 clientHwnd
, HWND16 childHwnd
,
431 WND
*w
= WIN_FindWndPtr(clientHwnd
);
436 hwndTo
= MDI_GetWindow(w
,childHwnd
,(WORD
)wTo
);
438 ci
= (MDICLIENTINFO
*) w
->wExtra
;
440 dprintf_mdi(stddeb
, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd
,hwndTo
);
442 if ( !hwndTo
) return;
444 hwndPrev
= ci
->hwndActiveChild
;
446 if ( hwndTo
!= hwndPrev
)
448 BOOL32 bOptimize
= 0;
450 if( ci
->hwndChildMaximized
)
453 w
->dwStyle
&= ~WS_VISIBLE
;
456 SetWindowPos32( hwndTo
, HWND_TOP
, 0, 0, 0, 0,
457 SWP_NOMOVE
| SWP_NOSIZE
);
458 if( !wTo
&& hwndPrev
)
460 SetWindowPos32( hwndPrev
, HWND_BOTTOM
, 0, 0, 0, 0,
461 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
465 ShowWindow16( clientHwnd
, SW_SHOW
);
470 /**********************************************************************
473 static HWND16
MDIDestroyChild( WND
*w_parent
, MDICLIENTINFO
*ci
, HWND16 parent
,
474 HWND16 child
, BOOL32 flagDestroy
)
476 WND
*childPtr
= WIN_FindWndPtr(child
);
480 if( child
== ci
->hwndActiveChild
)
482 MDI_SwitchActiveChild(parent
,child
,0);
484 if( child
== ci
->hwndActiveChild
)
486 ShowWindow16( child
, SW_HIDE
);
487 if( child
== ci
->hwndChildMaximized
)
489 MDI_RestoreFrameMenu(w_parent
->parent
, child
);
490 ci
->hwndChildMaximized
= 0;
491 MDI_UpdateFrameText(w_parent
->parent
,parent
,TRUE
,NULL
);
494 MDI_ChildActivate(w_parent
,0);
496 MDI_MenuDeleteItem(w_parent
, child
);
499 ci
->nActiveChildren
--;
501 dprintf_mdi(stddeb
,"MDIDestroyChild: child destroyed - %04x\n",child
);
505 MDI_PostUpdate(GetParent16(child
), ci
, SB_BOTH
+1);
506 DestroyWindow32(child
);
514 /**********************************************************************
517 * Note: hWndChild is NULL when last child is being destroyed
519 static LONG
MDI_ChildActivate( WND
*clientPtr
, HWND16 hWndChild
)
521 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientPtr
->wExtra
;
522 HWND16 prevActiveWnd
= clientInfo
->hwndActiveChild
;
523 WND
*wndPtr
= WIN_FindWndPtr( hWndChild
);
524 WND
*wndPrev
= WIN_FindWndPtr( prevActiveWnd
);
525 BOOL32 isActiveFrameWnd
= 0;
527 if( hWndChild
== prevActiveWnd
) return 0L;
530 if( wndPtr
->dwStyle
& WS_DISABLED
) return 0L;
532 dprintf_mdi(stddeb
,"MDI_ChildActivate: %04x\n", hWndChild
);
534 if( GetActiveWindow32() == clientPtr
->parent
->hwndSelf
)
535 isActiveFrameWnd
= TRUE
;
537 /* deactivate prev. active child */
540 wndPrev
->dwStyle
|= WS_SYSMENU
;
541 SendMessage16( prevActiveWnd
, WM_NCACTIVATE
, FALSE
, 0L );
544 SendMessage32A( prevActiveWnd
, WM_MDIACTIVATE
, (WPARAM32
)prevActiveWnd
,
548 SendMessage16( prevActiveWnd
, WM_MDIACTIVATE
, FALSE
,
549 MAKELONG(hWndChild
,prevActiveWnd
));
551 /* uncheck menu item */
552 if( clientInfo
->hWindowMenu
)
553 CheckMenuItem32( clientInfo
->hWindowMenu
,
554 wndPrev
->wIDmenu
, 0);
558 if( clientInfo
->hwndChildMaximized
)
559 if( clientInfo
->hwndChildMaximized
!= hWndChild
)
562 clientInfo
->hwndActiveChild
= hWndChild
;
563 ShowWindow16( hWndChild
, SW_SHOWMAXIMIZED
);
566 ShowWindow16( clientInfo
->hwndActiveChild
,
569 clientInfo
->hwndActiveChild
= hWndChild
;
571 /* check if we have any children left */
574 if( isActiveFrameWnd
)
575 SetFocus32( clientInfo
->self
);
579 /* check menu item */
580 if( clientInfo
->hWindowMenu
)
581 CheckMenuItem32( clientInfo
->hWindowMenu
,
582 wndPtr
->wIDmenu
, MF_CHECKED
);
584 /* bring active child to the top */
585 SetWindowPos32( hWndChild
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
587 if( isActiveFrameWnd
)
589 SendMessage16( hWndChild
, WM_NCACTIVATE
, TRUE
, 0L);
590 if( GetFocus32() == clientInfo
->self
)
591 SendMessage16( clientInfo
->self
, WM_SETFOCUS
,
592 (WPARAM16
)clientInfo
->self
, 0L );
594 SetFocus32( clientInfo
->self
);
598 SendMessage32A( hWndChild
, WM_MDIACTIVATE
, (WPARAM32
)hWndChild
,
599 (LPARAM
)prevActiveWnd
);
601 SendMessage16( hWndChild
, WM_MDIACTIVATE
, TRUE
,
602 MAKELONG(hWndChild
,prevActiveWnd
));
608 /* -------------------- MDI client window functions ------------------- */
610 /**********************************************************************
611 * CreateMDIMenuBitmap
613 static HBITMAP16
CreateMDIMenuBitmap(void)
615 HDC32 hDCSrc
= CreateCompatibleDC32(0);
616 HDC32 hDCDest
= CreateCompatibleDC32(hDCSrc
);
617 HBITMAP16 hbClose
= LoadBitmap16(0, MAKEINTRESOURCE(OBM_CLOSE
) );
619 HANDLE16 hobjSrc
, hobjDest
;
621 hobjSrc
= SelectObject32(hDCSrc
, hbClose
);
622 hbCopy
= CreateCompatibleBitmap32(hDCSrc
,SYSMETRICS_CXSIZE
,SYSMETRICS_CYSIZE
);
623 hobjDest
= SelectObject32(hDCDest
, hbCopy
);
625 BitBlt32(hDCDest
, 0, 0, SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
,
626 hDCSrc
, SYSMETRICS_CXSIZE
, 0, SRCCOPY
);
628 SelectObject32(hDCSrc
, hobjSrc
);
629 DeleteObject32(hbClose
);
632 hobjSrc
= SelectObject32( hDCDest
, GetStockObject32(BLACK_PEN
) );
634 MoveToEx32( hDCDest
, SYSMETRICS_CXSIZE
- 1, 0, NULL
);
635 LineTo32( hDCDest
, SYSMETRICS_CXSIZE
- 1, SYSMETRICS_CYSIZE
- 1);
637 SelectObject32(hDCDest
, hobjSrc
);
638 SelectObject32(hDCDest
, hobjDest
);
644 /**********************************************************************
647 static LONG
MDICascade(WND
* clientWnd
, MDICLIENTINFO
*ci
)
652 if (ci
->hwndChildMaximized
)
653 ShowWindow16( ci
->hwndChildMaximized
, SW_NORMAL
);
655 if (ci
->nActiveChildren
== 0) return 0;
657 if ((ppWnd
= WIN_BuildWinArray(clientWnd
, BWA_SKIPHIDDEN
| BWA_SKIPOWNED
|
658 BWA_SKIPICONIC
, &total
)))
660 WND
** heapPtr
= ppWnd
;
663 INT16 delta
= 0, n
= 0;
665 if( total
< ci
->nActiveChildren
)
666 delta
= SYSMETRICS_CYICONSPACING
+ SYSMETRICS_CYICON
;
668 /* walk the list and move windows */
671 dprintf_mdi(stddeb
, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
672 (*ppWnd
)->hwndSelf
, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
);
674 MDI_CalcDefaultChildPos(clientWnd
, n
++, pos
, delta
);
675 SetWindowPos32((*ppWnd
)->hwndSelf
, 0, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
,
676 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
680 HeapFree( SystemHeap
, 0, heapPtr
);
683 if( total
< ci
->nActiveChildren
) ArrangeIconicWindows32( clientWnd
->hwndSelf
);
687 /**********************************************************************
690 static LONG
MDITile(WND
* wndClient
, MDICLIENTINFO
*ci
,WORD wParam
)
695 if (ci
->hwndChildMaximized
)
696 ShowWindow16(ci
->hwndChildMaximized
, SW_NORMAL
);
698 if (ci
->nActiveChildren
== 0) return 0;
700 ppWnd
= WIN_BuildWinArray(wndClient
, BWA_SKIPHIDDEN
| BWA_SKIPOWNED
| BWA_SKIPICONIC
|
701 ((wParam
& MDITILE_SKIPDISABLED
)? BWA_SKIPDISABLED
: 0), &total
);
703 dprintf_mdi(stddeb
,"MDITile: %u windows to tile\n", total
);
707 WND
** heapPtr
= ppWnd
;
712 int x
, y
, xsize
, ysize
;
713 int rows
, columns
, r
, c
, i
;
715 rect
= wndClient
->rectClient
;
716 rows
= (int) sqrt((double)total
);
717 columns
= total
/ rows
;
719 if( wParam
& MDITILE_HORIZONTAL
) /* version >= 3.1 */
722 rows
= columns
; /* exchange r and c */
726 if( total
!= ci
->nActiveChildren
)
728 y
= rect
.bottom
- 2 * SYSMETRICS_CYICONSPACING
- SYSMETRICS_CYICON
;
729 rect
.bottom
= ( y
- SYSMETRICS_CYICON
< rect
.top
)? rect
.bottom
: y
;
732 ysize
= rect
.bottom
/ rows
;
733 xsize
= rect
.right
/ columns
;
735 for (x
= i
= 0, c
= 1; c
<= columns
&& *ppWnd
; c
++)
740 ysize
= rect
.bottom
/ rows
;
744 for (r
= 1; r
<= rows
&& *ppWnd
; r
++, i
++)
746 SetWindowPos32((*ppWnd
)->hwndSelf
, 0, x
, y
, xsize
, ysize
,
747 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
754 HeapFree( SystemHeap
, 0, heapPtr
);
757 if( total
< ci
->nActiveChildren
) ArrangeIconicWindows32( wndClient
->hwndSelf
);
761 /* ----------------------- Frame window ---------------------------- */
764 /**********************************************************************
765 * MDI_AugmentFrameMenu
767 static BOOL32
MDI_AugmentFrameMenu( MDICLIENTINFO
* ci
, WND
*frame
,
770 WND
* child
= WIN_FindWndPtr(hChild
);
771 HMENU16 hSysPopup
= 0;
773 dprintf_mdi(stddeb
,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame
,hChild
);
775 if( !frame
->wIDmenu
|| !child
->hSysMenu
) return 0;
777 /* create a copy of sysmenu popup and insert it into frame menu bar */
779 if (!(hSysPopup
= LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU
))))
782 dprintf_mdi(stddeb
,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup
,child
->hSysMenu
);
784 if( !InsertMenu32A(frame
->wIDmenu
,0,MF_BYPOSITION
| MF_BITMAP
| MF_POPUP
,
785 hSysPopup
, (LPSTR
)(DWORD
)hBmpClose
))
786 { DestroyMenu32(hSysPopup
); return 0; }
788 if( !AppendMenu32A(frame
->wIDmenu
,MF_HELP
| MF_BITMAP
,
789 SC_RESTORE
, (LPSTR
)(DWORD
)hBmpRestore
))
791 RemoveMenu32(frame
->wIDmenu
,0,MF_BYPOSITION
);
795 EnableMenuItem32(hSysPopup
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
796 EnableMenuItem32(hSysPopup
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
797 EnableMenuItem32(hSysPopup
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
800 DrawMenuBar32(frame
->hwndSelf
);
805 /**********************************************************************
806 * MDI_RestoreFrameMenu
808 static BOOL32
MDI_RestoreFrameMenu( WND
*frameWnd
, HWND16 hChild
)
810 INT32 nItems
= GetMenuItemCount32(frameWnd
->wIDmenu
) - 1;
812 dprintf_mdi(stddeb
,"MDI_RestoreFrameMenu: for child %04x\n",hChild
);
814 if( GetMenuItemID32(frameWnd
->wIDmenu
,nItems
) != SC_RESTORE
)
818 RemoveMenu32(frameWnd
->wIDmenu
,0,MF_BYPOSITION
);
819 DeleteMenu32(frameWnd
->wIDmenu
,nItems
-1,MF_BYPOSITION
);
821 DrawMenuBar32(frameWnd
->hwndSelf
);
826 /**********************************************************************
827 * MDI_UpdateFrameText
829 * used when child window is maximized/restored
831 * Note: lpTitle can be NULL
833 static void MDI_UpdateFrameText( WND
*frameWnd
, HWND16 hClient
,
834 BOOL32 repaint
, LPCSTR lpTitle
)
836 char lpBuffer
[MDI_MAXTITLELENGTH
+1];
837 WND
* clientWnd
= WIN_FindWndPtr(hClient
);
839 MDICLIENTINFO
*ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
841 dprintf_mdi(stddeb
, "MDI: repaint %i, frameText %s\n", repaint
, (lpTitle
)?lpTitle
:"NULL");
843 /* store new "default" title if lpTitle is not NULL */
846 if (ci
->frameTitle
) HeapFree( SystemHeap
, 0, ci
->frameTitle
);
847 ci
->frameTitle
= HEAP_strdupA( SystemHeap
, 0, lpTitle
);
852 WND
* childWnd
= WIN_FindWndPtr( ci
->hwndChildMaximized
);
854 if( childWnd
&& childWnd
->text
)
856 /* combine frame title and child title if possible */
858 LPCSTR lpBracket
= " - [";
859 int i_frame_text_length
= strlen(ci
->frameTitle
);
860 int i_child_text_length
= strlen(childWnd
->text
);
862 lstrcpyn32A( lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
864 if( i_frame_text_length
+ 6 < MDI_MAXTITLELENGTH
)
866 strcat( lpBuffer
, lpBracket
);
868 if( i_frame_text_length
+ i_child_text_length
+ 6 < MDI_MAXTITLELENGTH
)
870 strcat( lpBuffer
, childWnd
->text
);
871 strcat( lpBuffer
, "]" );
875 lstrcpyn32A( lpBuffer
+ i_frame_text_length
+ 4,
877 MDI_MAXTITLELENGTH
- i_frame_text_length
- 5 );
878 strcat( lpBuffer
, "]" );
884 strncpy(lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
885 lpBuffer
[MDI_MAXTITLELENGTH
]='\0';
891 DEFWND_SetText( frameWnd
, lpBuffer
);
892 if( repaint
== MDI_REPAINTFRAME
)
893 SetWindowPos32(frameWnd
->hwndSelf
, 0,0,0,0,0, SWP_FRAMECHANGED
|
894 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
898 /* ----------------------------- Interface ---------------------------- */
901 /**********************************************************************
904 * This function is the handler for all MDI requests.
906 LRESULT WINAPI
MDIClientWndProc(HWND16 hwnd
, UINT16 message
, WPARAM16 wParam
,
912 WND
*w
= WIN_FindWndPtr(hwnd
);
913 WND
*frameWnd
= w
->parent
;
916 ci
= (MDICLIENTINFO
*) w
->wExtra
;
922 cs
= (LPCREATESTRUCT16
) PTR_SEG_TO_LIN(lParam
);
924 /* Translation layer doesn't know what's in the cs->lpCreateParams
925 * so we have to keep track of what environment we're in. */
927 if( w
->flags
& WIN_ISWIN32
)
929 #define ccs ((LPCLIENTCREATESTRUCT32)cs->lpCreateParams)
930 ci
->hWindowMenu
= ccs
->hWindowMenu
;
931 ci
->idFirstChild
= ccs
->idFirstChild
;
936 LPCLIENTCREATESTRUCT16 ccs
= (LPCLIENTCREATESTRUCT16
)
937 PTR_SEG_TO_LIN(cs
->lpCreateParams
);
938 ci
->hWindowMenu
= ccs
->hWindowMenu
;
939 ci
->idFirstChild
= ccs
->idFirstChild
;
942 ci
->hwndChildMaximized
= 0;
943 ci
->nActiveChildren
= 0;
944 ci
->nTotalCreated
= 0;
945 ci
->frameTitle
= NULL
;
948 w
->dwStyle
|= WS_CLIPCHILDREN
;
952 hBmpClose
= CreateMDIMenuBitmap();
953 hBmpRestore
= LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORE
) );
955 MDI_UpdateFrameText(frameWnd
, hwnd
, MDI_NOFRAMEREPAINT
,frameWnd
->text
);
957 AppendMenu32A( ci
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
959 GetClientRect32(frameWnd
->hwndSelf
, &rect
);
960 NC_HandleNCCalcSize( w
, &rect
);
961 w
->rectClient
= rect
;
963 dprintf_mdi(stddeb
,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd
,ci
->idFirstChild
);
968 if( ci
->hwndChildMaximized
) MDI_RestoreFrameMenu(w
, frameWnd
->hwndSelf
);
969 if((nItems
= GetMenuItemCount32(ci
->hWindowMenu
)) > 0) {
970 ci
->idFirstChild
= nItems
- 1;
971 ci
->nActiveChildren
++; /* to delete a separator */
972 while( ci
->nActiveChildren
-- )
973 DeleteMenu32(ci
->hWindowMenu
,MF_BYPOSITION
,ci
->idFirstChild
--);
978 if( ci
->hwndActiveChild
!= (HWND16
)wParam
)
979 SetWindowPos32((HWND32
)wParam
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
983 return MDICascade(w
, ci
);
988 MDICREATESTRUCT16
* cs
= (MDICREATESTRUCT16
*) PTR_SEG_TO_LIN(lParam
);
989 return (LONG
)MDICreateChild(w
, ci
, hwnd
, cs
, lParam
);
994 return (LONG
)MDIDestroyChild(w
, ci
, hwnd
, (HWND32
)wParam
, TRUE
);
996 case WM_MDIGETACTIVE
:
997 return ((LONG
) ci
->hwndActiveChild
|
998 ((LONG
) (ci
->hwndChildMaximized
>0) << 16));
1000 case WM_MDIICONARRANGE
:
1001 ci
->mdiFlags
|= MDIF_NEEDUPDATE
;
1002 MDIIconArrange(hwnd
);
1003 ci
->sbRecalc
= SB_BOTH
+1;
1004 SendMessage16(hwnd
,WM_MDICALCCHILDSCROLL
,0,0L);
1007 case WM_MDIMAXIMIZE
:
1008 ShowWindow16((HWND16
)wParam
, SW_MAXIMIZE
);
1012 MDI_SwitchActiveChild(hwnd
, (HWND16
)wParam
, (lParam
)?1:0);
1016 ShowWindow16( (HWND16
)wParam
, SW_NORMAL
);
1021 return (LRESULT
)MDISetMenu(hwnd
, FALSE
, (HMENU16
)wParam
, (HMENU16
)lParam
);
1023 return (LRESULT
)MDISetMenu(hwnd
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1027 ci
->mdiFlags
|= MDIF_NEEDUPDATE
;
1028 ShowScrollBar32(hwnd
,SB_BOTH
,FALSE
);
1029 MDITile(w
, ci
,wParam
);
1030 ci
->mdiFlags
&= ~MDIF_NEEDUPDATE
;
1035 ci
->mdiFlags
|= MDIF_NEEDUPDATE
;
1036 ScrollChildren32(hwnd
,message
,wParam
,lParam
);
1037 ci
->mdiFlags
&= ~MDIF_NEEDUPDATE
;
1041 if( ci
->hwndActiveChild
)
1043 w
= WIN_FindWndPtr( ci
->hwndActiveChild
);
1044 if( !(w
->dwStyle
& WS_MINIMIZE
) )
1045 SetFocus32( ci
->hwndActiveChild
);
1050 if( ci
->hwndActiveChild
)
1051 SendMessage16(ci
->hwndActiveChild
, message
, wParam
, lParam
);
1054 case WM_PARENTNOTIFY
:
1055 if( wParam
== WM_LBUTTONDOWN
)
1057 POINT16 pt
= MAKEPOINT16(lParam
);
1058 HWND16 child
= ChildWindowFromPoint16(hwnd
, pt
);
1060 dprintf_mdi(stddeb
,"MDIClient: notification from %04x (%i,%i)\n",child
,pt
.x
,pt
.y
);
1062 if( child
&& child
!= hwnd
&&
1063 child
!= ci
->hwndActiveChild
)
1064 SetWindowPos32(child
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1069 if( ci
->hwndChildMaximized
)
1071 WND
* child
= WIN_FindWndPtr(ci
->hwndChildMaximized
);
1072 RECT16 rect
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
1074 AdjustWindowRectEx16(&rect
, child
->dwStyle
, 0, child
->dwExStyle
);
1075 MoveWindow16(ci
->hwndChildMaximized
, rect
.left
, rect
.top
,
1076 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, 1);
1079 MDI_PostUpdate(hwnd
, ci
, SB_BOTH
+1);
1083 case WM_MDICALCCHILDSCROLL
:
1084 if( (ci
->mdiFlags
& MDIF_NEEDUPDATE
) && ci
->sbRecalc
)
1086 CalcChildScroll(hwnd
, ci
->sbRecalc
-1);
1088 ci
->mdiFlags
&= ~MDIF_NEEDUPDATE
;
1093 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1097 /***********************************************************************
1098 * DefFrameProc16 (USER.445)
1100 LRESULT WINAPI
DefFrameProc16( HWND16 hwnd
, HWND16 hwndMDIClient
,
1101 UINT16 message
, WPARAM16 wParam
, LPARAM lParam
)
1112 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1113 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1115 /* check for possible syscommands for maximized MDI child */
1118 wParam
< ci
->idFirstChild
||
1119 wParam
>= ci
->idFirstChild
+ ci
->nActiveChildren
1121 if( (wParam
- 0xF000) & 0xF00F ) break;
1132 if( ci
->hwndChildMaximized
)
1133 return SendMessage16( ci
->hwndChildMaximized
, WM_SYSCOMMAND
,
1139 childHwnd
= MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient
),
1142 SendMessage16(hwndMDIClient
, WM_MDIACTIVATE
,
1143 (WPARAM16
)childHwnd
, 0L);
1148 SendMessage16(hwndMDIClient
, message
, wParam
, lParam
);
1152 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd
), hwndMDIClient
,
1154 (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1158 SetFocus32(hwndMDIClient
);
1162 MoveWindow16(hwndMDIClient
, 0, 0,
1163 LOWORD(lParam
), HIWORD(lParam
), TRUE
);
1168 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1169 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1171 if( !(wndPtr
->parent
->dwStyle
& WS_MINIMIZE
)
1172 && ci
->hwndActiveChild
&& !ci
->hwndChildMaximized
)
1174 /* control menu is between the frame system menu and
1175 * the first entry of menu bar */
1177 if( (wParam
== VK_LEFT
&&
1178 wndPtr
->parent
->wIDmenu
== LOWORD(lParam
)) ||
1179 (wParam
== VK_RIGHT
&&
1180 GetSubMenu16(wndPtr
->parent
->hSysMenu
, 0) == LOWORD(lParam
)) )
1182 wndPtr
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1183 return MAKELONG( GetSubMenu16(wndPtr
->hSysMenu
, 0),
1184 ci
->hwndActiveChild
);
1191 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1195 /***********************************************************************
1196 * DefFrameProc32A (USER32.121)
1198 LRESULT WINAPI
DefFrameProc32A( HWND32 hwnd
, HWND32 hwndMDIClient
,
1199 UINT32 message
, WPARAM32 wParam
, LPARAM lParam
)
1206 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1208 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1211 SendMessage32A(hwndMDIClient
, message
, wParam
, lParam
);
1216 LPSTR segstr
= SEGPTR_STRDUP((LPSTR
)lParam
);
1218 ret
= DefFrameProc16(hwnd
, hwndMDIClient
, message
,
1219 wParam
, (LPARAM
)SEGPTR_GET(segstr
) );
1220 SEGPTR_FREE(segstr
);
1226 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1231 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1235 /***********************************************************************
1236 * DefFrameProc32W (USER32.122)
1238 LRESULT WINAPI
DefFrameProc32W( HWND32 hwnd
, HWND32 hwndMDIClient
,
1239 UINT32 message
, WPARAM32 wParam
, LPARAM lParam
)
1246 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1248 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1251 SendMessage32W(hwndMDIClient
, message
, wParam
, lParam
);
1255 LPSTR txt
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lParam
);
1256 LRESULT ret
= DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1257 wParam
, (DWORD
)txt
);
1258 HeapFree(GetProcessHeap(),0,txt
);
1263 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1268 return DefWindowProc32W( hwnd
, message
, wParam
, lParam
);
1272 /***********************************************************************
1273 * DefMDIChildProc16 (USER.447)
1275 LRESULT WINAPI
DefMDIChildProc16( HWND16 hwnd
, UINT16 message
,
1276 WPARAM16 wParam
, LPARAM lParam
)
1281 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1282 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1287 DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1288 MDI_MenuModifyItem(clientWnd
,hwnd
);
1289 if( ci
->hwndChildMaximized
== hwnd
)
1290 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1291 MDI_REPAINTFRAME
, NULL
);
1295 SendMessage16(ci
->self
,WM_MDIDESTROY
,(WPARAM16
)hwnd
,0L);
1299 if( ci
->hwndActiveChild
!= hwnd
)
1300 MDI_ChildActivate(clientWnd
, hwnd
);
1303 case WM_CHILDACTIVATE
:
1304 MDI_ChildActivate(clientWnd
, hwnd
);
1308 dprintf_mdi(stddeb
,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
1309 hwnd
, ci
->hwndActiveChild
);
1316 if( ci
->hwndChildMaximized
== hwnd
) return 0;
1320 WIN_FindWndPtr(hwnd
)->dwStyle
|= WS_SYSMENU
;
1323 if( ci
->hwndChildMaximized
== hwnd
)
1324 return SendMessage16( clientWnd
->parent
->hwndSelf
,
1325 message
, wParam
, lParam
);
1326 WIN_FindWndPtr(hwnd
)->dwStyle
&= ~WS_SYSMENU
;
1329 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 0);
1332 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 1);
1337 case WM_GETMINMAXINFO
:
1338 MDI_ChildGetMinMaxInfo(clientWnd
, hwnd
, (MINMAXINFO16
*) PTR_SEG_TO_LIN(lParam
));
1342 if( ci
->hwndChildMaximized
) ci
->mdiFlags
&= ~MDIF_NEEDUPDATE
;
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 HWND16 hMaxChild
= ci
->hwndChildMaximized
;
1363 if( hMaxChild
== hwnd
) break;
1367 SendMessage16( hMaxChild
, WM_SETREDRAW
, FALSE
, 0L );
1369 MDI_RestoreFrameMenu( clientWnd
->parent
, hMaxChild
);
1370 ShowWindow16( hMaxChild
, SW_SHOWNOACTIVATE
);
1372 SendMessage16( hMaxChild
, WM_SETREDRAW
, TRUE
, 0L );
1375 dprintf_mdi(stddeb
,"\tMDI: maximizing child %04x\n", hwnd
);
1377 ci
->hwndChildMaximized
= hwnd
; /* !!! */
1379 MDI_AugmentFrameMenu( ci
, clientWnd
->parent
, hwnd
);
1380 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1381 MDI_REPAINTFRAME
, NULL
);
1384 if( wParam
== SIZE_MINIMIZED
)
1386 HWND16 switchTo
= MDI_GetWindow(clientWnd
, hwnd
, 0);
1389 SendMessage16( switchTo
, WM_CHILDACTIVATE
, 0, 0L);
1392 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1397 /* MDI children don't have menu bars */
1398 PostMessage16( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1399 (WPARAM16
)SC_KEYMENU
, (LPARAM
)wParam
);
1404 if( wParam
== VK_LEFT
) /* switch to frame system menu */
1405 return MAKELONG( GetSubMenu16(clientWnd
->parent
->hSysMenu
, 0),
1406 clientWnd
->parent
->hwndSelf
);
1407 if( wParam
== VK_RIGHT
) /* to frame menu bar */
1408 return MAKELONG( clientWnd
->parent
->wIDmenu
,
1409 clientWnd
->parent
->hwndSelf
);
1414 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1418 /***********************************************************************
1419 * DefMDIChildProc32A (USER32.123)
1421 LRESULT WINAPI
DefMDIChildProc32A( HWND32 hwnd
, UINT32 message
,
1422 WPARAM32 wParam
, LPARAM lParam
)
1427 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1428 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1433 DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1434 MDI_MenuModifyItem(clientWnd
,hwnd
);
1435 if( ci
->hwndChildMaximized
== hwnd
)
1436 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1437 MDI_REPAINTFRAME
, NULL
);
1440 case WM_GETMINMAXINFO
:
1443 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32
*)lParam
, &mmi
);
1444 MDI_ChildGetMinMaxInfo( clientWnd
, hwnd
, &mmi
);
1445 STRUCT32_MINMAXINFO16to32( &mmi
, (MINMAXINFO32
*)lParam
);
1451 /* MDI children don't have menu bars */
1452 PostMessage16( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1453 (WPARAM16
)SC_KEYMENU
, (LPARAM
)LOWORD(wParam
) );
1458 case WM_CHILDACTIVATE
:
1464 return DefMDIChildProc16( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1466 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1470 /***********************************************************************
1471 * DefMDIChildProc32W (USER32.124)
1473 LRESULT WINAPI
DefMDIChildProc32W( HWND32 hwnd
, UINT32 message
,
1474 WPARAM32 wParam
, LPARAM lParam
)
1479 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1480 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1485 DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1486 MDI_MenuModifyItem(clientWnd
,hwnd
);
1487 if( ci
->hwndChildMaximized
== hwnd
)
1488 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1489 MDI_REPAINTFRAME
, NULL
);
1492 case WM_GETMINMAXINFO
:
1496 case WM_CHILDACTIVATE
:
1502 return DefMDIChildProc32A( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1504 return DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1508 /**********************************************************************
1509 * CreateMDIWindowA (USER32.78)
1512 /**********************************************************************
1513 * CreateMDIWindowW (USER32.79)
1516 /**********************************************************************
1517 * TranslateMDISysAccel32 (USER32.554)
1519 BOOL32 WINAPI
TranslateMDISysAccel32( HWND32 hwndClient
, LPMSG32 msg
)
1523 STRUCT32_MSG32to16(msg
,&msg16
);
1524 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1525 return TranslateMDISysAccel16(hwndClient
,&msg16
);
1529 /**********************************************************************
1530 * TranslateMDISysAccel16 (USER.451)
1532 BOOL16 WINAPI
TranslateMDISysAccel16( HWND16 hwndClient
, LPMSG16 msg
)
1534 WND
* clientWnd
= WIN_FindWndPtr( hwndClient
);
1536 if( clientWnd
&& (msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_SYSKEYDOWN
))
1538 MDICLIENTINFO
*ci
= NULL
;
1541 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1542 wnd
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1543 if( wnd
&& !(wnd
->dwStyle
& WS_DISABLED
) )
1545 WPARAM16 wParam
= 0;
1547 /* translate if the Ctrl key is down and Alt not. */
1549 if( (GetKeyState32(VK_CONTROL
) & 0x8000) &&
1550 !(GetKeyState32(VK_MENU
) & 0x8000))
1552 switch( msg
->wParam
)
1556 wParam
= ( GetKeyState32(VK_SHIFT
) & 0x8000 )
1557 ? SC_NEXTWINDOW
: SC_PREVWINDOW
;
1566 dprintf_mdi(stddeb
,"TranslateMDISysAccel: wParam = %04x\n", wParam
);
1567 SendMessage16( ci
->hwndActiveChild
, WM_SYSCOMMAND
,
1568 wParam
, (LPARAM
)msg
->wParam
);
1573 return 0; /* failure */
1577 /***********************************************************************
1578 * CalcChildScroll (USER.462)
1580 void WINAPI
CalcChildScroll( HWND16 hwnd
, WORD scroll
)
1582 RECT32 childRect
, clientRect
;
1583 INT32 vmin
, vmax
, hmin
, hmax
, vpos
, hpos
;
1584 BOOL32 noscroll
= FALSE
;
1587 if (!(Wnd
= pWnd
= WIN_FindWndPtr( hwnd
))) return;
1588 GetClientRect32( hwnd
, &clientRect
);
1589 SetRectEmpty32( &childRect
);
1591 for ( pWnd
= pWnd
->child
; pWnd
; pWnd
= pWnd
->next
)
1593 UnionRect32( &childRect
, &pWnd
->rectWindow
, &childRect
);
1594 if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1597 UnionRect32( &childRect
, &clientRect
, &childRect
);
1599 /* jump through the hoops to prevent excessive flashing
1602 hmin
= childRect
.left
; hmax
= childRect
.right
- clientRect
.right
;
1603 hpos
= clientRect
.left
- childRect
.left
;
1604 vmin
= childRect
.top
; vmax
= childRect
.bottom
- clientRect
.bottom
;
1605 vpos
= clientRect
.top
- childRect
.top
;
1608 ShowScrollBar32(hwnd
, SB_BOTH
, FALSE
);
1613 vpos
= hpos
; vmin
= hmin
; vmax
= hmax
;
1615 SetScrollPos32(hwnd
, scroll
, vpos
, FALSE
);
1616 SetScrollRange32(hwnd
, scroll
, vmin
, vmax
, TRUE
);
1619 SCROLL_SetNCSbState( Wnd
, vmin
, vmax
, vpos
,
1621 SetWindowPos32(hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
1622 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1627 /***********************************************************************
1628 * ScrollChildren16 (USER.463)
1630 void WINAPI
ScrollChildren16(HWND16 hWnd
, UINT16 uMsg
, WPARAM16 wParam
, LPARAM lParam
)
1632 return ScrollChildren32( hWnd
, uMsg
, wParam
, lParam
);
1636 /***********************************************************************
1637 * ScrollChildren32 (USER32.447)
1639 void WINAPI
ScrollChildren32(HWND32 hWnd
, UINT32 uMsg
, WPARAM32 wParam
,
1642 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1644 INT32 curPos
, length
, minPos
, maxPos
, shift
;
1646 if( !wndPtr
) return;
1648 if( uMsg
== WM_HSCROLL
)
1650 GetScrollRange32(hWnd
,SB_HORZ
,&minPos
,&maxPos
);
1651 curPos
= GetScrollPos32(hWnd
,SB_HORZ
);
1652 length
= (wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
)/2;
1653 shift
= SYSMETRICS_CYHSCROLL
;
1655 else if( uMsg
== WM_VSCROLL
)
1657 GetScrollRange32(hWnd
,SB_VERT
,&minPos
,&maxPos
);
1658 curPos
= GetScrollPos32(hWnd
,SB_VERT
);
1659 length
= (wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
)/2;
1660 shift
= SYSMETRICS_CXVSCROLL
;
1667 newPos
= curPos
- shift
;
1670 newPos
= curPos
+ shift
;
1673 newPos
= curPos
- length
;
1676 newPos
= curPos
+ length
;
1679 case SB_THUMBPOSITION
:
1680 newPos
= LOWORD(lParam
);
1693 CalcChildScroll(hWnd
,(uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
);
1697 if( newPos
> maxPos
)
1699 else if( newPos
< minPos
)
1702 SetScrollPos32(hWnd
, (uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
, newPos
, TRUE
);
1704 if( uMsg
== WM_VSCROLL
)
1705 ScrollWindowEx32(hWnd
,0 ,curPos
- newPos
, NULL
, NULL
, 0, NULL
,
1706 SW_INVALIDATE
| SW_ERASE
| SW_SCROLLCHILDREN
);
1708 ScrollWindowEx32(hWnd
,curPos
- newPos
, 0, NULL
, NULL
, 0, NULL
,
1709 SW_INVALIDATE
| SW_ERASE
| SW_SCROLLCHILDREN
);