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"
34 static HBITMAP16 hBmpClose
= 0;
35 static HBITMAP16 hBmpRestore
= 0;
37 DWORD
SCROLL_SetNCSbState(WND
*,int,int,int,int,int,int);
39 /* ----------------- declarations ----------------- */
40 static void MDI_UpdateFrameText(WND
*, HWND16
, BOOL32
, LPCSTR
);
41 static BOOL32
MDI_AugmentFrameMenu(MDICLIENTINFO
*, WND
*, HWND16
);
42 static BOOL32
MDI_RestoreFrameMenu(WND
*, HWND16
);
44 static LONG
MDI_ChildActivate(WND
* ,HWND16
);
46 /* -------- Miscellaneous service functions ----------
51 static HWND16
MDI_GetChildByID(WND
* wndPtr
,int id
)
53 for (wndPtr
= wndPtr
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
54 if (wndPtr
->wIDmenu
== id
) return wndPtr
->hwndSelf
;
58 static void MDI_PostUpdate(HWND16 hwnd
, MDICLIENTINFO
* ci
, WORD recalc
)
60 if( !ci
->sbNeedUpdate
)
62 ci
->sbNeedUpdate
= TRUE
;
63 PostMessage( hwnd
, WM_MDICALCCHILDSCROLL
, 0, 0);
65 ci
->sbRecalc
= recalc
;
68 /**********************************************************************
71 #ifdef SUPERFLUOUS_FUNCTIONS
72 static BOOL
MDI_MenuAppendItem(WND
*clientWnd
, HWND16 hWndChild
)
75 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
76 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
77 int n
= sprintf(buffer
, "%d ",
78 clientInfo
->nActiveChildren
);
80 if( !clientInfo
->hWindowMenu
) return 0;
82 if (wndPtr
->text
) strncpy(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
- 1);
83 return AppendMenu32A( clientInfo
->hWindowMenu
, MF_STRING
,
84 wndPtr
->wIDmenu
, buffer
);
88 /**********************************************************************
91 static BOOL
MDI_MenuModifyItem(WND
* clientWnd
, HWND16 hWndChild
)
94 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
95 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
96 UINT n
= sprintf(buffer
, "%d ",
97 wndPtr
->wIDmenu
- clientInfo
->idFirstChild
+ 1);
100 if( !clientInfo
->hWindowMenu
) return 0;
102 if (wndPtr
->text
) lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
104 n
= GetMenuState32(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
,MF_BYCOMMAND
);
105 bRet
= ModifyMenu32A(clientInfo
->hWindowMenu
, wndPtr
->wIDmenu
,
106 MF_BYCOMMAND
| MF_STRING
, wndPtr
->wIDmenu
, buffer
);
107 CheckMenuItem32(clientInfo
->hWindowMenu
,wndPtr
->wIDmenu
, n
& MF_CHECKED
);
111 /**********************************************************************
114 static BOOL
MDI_MenuDeleteItem(WND
* clientWnd
, HWND16 hWndChild
)
117 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
118 WND
*wndPtr
= WIN_FindWndPtr(hWndChild
);
121 if( !clientInfo
->nActiveChildren
||
122 !clientInfo
->hWindowMenu
) return 0;
124 id
= wndPtr
->wIDmenu
;
125 DeleteMenu32(clientInfo
->hWindowMenu
,id
,MF_BYCOMMAND
);
127 /* walk the rest of MDI children to prevent gaps in the id
128 * sequence and in the menu child list */
130 for( index
= id
+1; index
<= clientInfo
->nActiveChildren
+
131 clientInfo
->idFirstChild
; index
++ )
133 wndPtr
= WIN_FindWndPtr(MDI_GetChildByID(clientWnd
,index
));
136 dprintf_mdi(stddeb
,"MDIMenuDeleteItem: no window for id=%i\n",index
);
143 n
= sprintf(buffer
, "%d ",index
- clientInfo
->idFirstChild
);
145 lstrcpyn32A(buffer
+ n
, wndPtr
->text
, sizeof(buffer
) - n
);
148 ModifyMenu32A(clientInfo
->hWindowMenu
,index
,MF_BYCOMMAND
| MF_STRING
,
149 index
- 1 , buffer
);
154 /**********************************************************************
157 * returns "activateable" child or zero
159 static HWND16
MDI_GetWindow(WND
*clientWnd
, HWND16 hWnd
, WORD wTo
)
161 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientWnd
->wExtra
;
162 WND
*wndPtr
, *pWnd
, *pWndLast
;
164 if( !hWnd
) hWnd
= clientInfo
->hwndActiveChild
;
166 if( !(wndPtr
= WIN_FindWndPtr(hWnd
)) ) return 0;
173 if (!pWnd
) pWnd
= wndPtr
->parent
->child
;
174 if (pWnd
== wndPtr
) /* not found */
176 if (!wTo
|| !pWndLast
) return 0;
180 /* we are not interested in owned popups */
182 (pWnd
->dwStyle
& WS_VISIBLE
) &&
183 !(pWnd
->dwStyle
& WS_DISABLED
)) /* found one */
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
, INT delta
)
199 RECT16 rect
= w
->rectClient
;
200 INT spacing
= GetSystemMetrics32(SM_CYCAPTION
) +
201 GetSystemMetrics32(SM_CYFRAME
) - 1;
204 if( rect
.bottom
- rect
.top
- delta
>= spacing
)
205 rect
.bottom
-= delta
;
207 nstagger
= (rect
.bottom
- rect
.top
)/(3*spacing
);
208 lpPos
[1].x
= (rect
.right
- rect
.left
- nstagger
*spacing
);
209 lpPos
[1].y
= (rect
.bottom
- rect
.top
- nstagger
*spacing
);
210 lpPos
[0].x
= lpPos
[0].y
= spacing
*(n
%(nstagger
+1));
213 /**********************************************************************
216 static HMENU16
MDISetMenu(HWND16 hwnd
, BOOL32 fRefresh
, HMENU16 hmenuFrame
,
219 WND
*w
= WIN_FindWndPtr(hwnd
);
222 dprintf_mdi(stddeb
, "WM_MDISETMENU: %04x %04x %04x %04x\n",
223 hwnd
, fRefresh
, hmenuFrame
, hmenuWindow
);
225 ci
= (MDICLIENTINFO
*) w
->wExtra
;
229 HWND16 hwndFrame
= GetParent16(hwnd
);
230 HMENU32 oldFrameMenu
= GetMenu32(hwndFrame
);
232 if( ci
->hwndChildMaximized
&& hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
233 MDI_RestoreFrameMenu(w
->parent
, ci
->hwndChildMaximized
);
235 if( hmenuWindow
&& hmenuWindow
!=ci
->hWindowMenu
)
237 /* delete menu items from ci->hWindowMenu
238 * and add them to hmenuWindow */
240 INT32 i
= GetMenuItemCount32(ci
->hWindowMenu
) - 1;
241 INT32 pos
= GetMenuItemCount32(hmenuWindow
) + 1;
243 AppendMenu32A( hmenuWindow
, MF_SEPARATOR
, 0, NULL
);
245 if( ci
->nActiveChildren
)
247 INT j
= i
- ci
->nActiveChildren
+ 1;
251 for( ; i
>= j
; i
-- )
253 id
= GetMenuItemID32(ci
->hWindowMenu
,i
);
254 state
= GetMenuState32(ci
->hWindowMenu
,i
,MF_BYPOSITION
);
256 GetMenuString32A(ci
->hWindowMenu
, i
, buffer
, 100, MF_BYPOSITION
);
258 DeleteMenu32(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
259 InsertMenu32A(hmenuWindow
, pos
, MF_BYPOSITION
| MF_STRING
,
261 CheckMenuItem32(hmenuWindow
,pos
, MF_BYPOSITION
| (state
& MF_CHECKED
));
265 /* remove separator */
266 DeleteMenu32(ci
->hWindowMenu
, i
, MF_BYPOSITION
);
268 ci
->hWindowMenu
= hmenuWindow
;
271 if( hmenuFrame
&& hmenuFrame
!=oldFrameMenu
)
273 SetMenu32(hwndFrame
, hmenuFrame
);
274 if( ci
->hwndChildMaximized
)
275 MDI_AugmentFrameMenu(ci
, w
->parent
, ci
->hwndChildMaximized
);
283 /**********************************************************************
286 static WORD
MDIIconArrange(HWND16 parent
)
288 return ArrangeIconicWindows16(parent
); /* Any reason why the */
289 /* existing icon arrange */
290 /* can't be used here? */
295 /* ------------------ MDI child window functions ---------------------- */
298 /**********************************************************************
301 static HWND16
MDICreateChild( WND
*w
, MDICLIENTINFO
*ci
, HWND16 parent
,
302 LPMDICREATESTRUCT16 cs
, LPARAM lParam
)
305 DWORD style
= cs
->style
| (WS_CHILD
| WS_CLIPSIBLINGS
);
306 HWND16 hwnd
, hwndMax
= 0;
307 WORD wIDmenu
= ci
->idFirstChild
+ ci
->nActiveChildren
;
308 char lpstrDef
[]="junk!";
310 dprintf_mdi(stdnimp
,"MDICreateChild: origin %i,%i - dim %i,%i, style %08x\n",
311 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, (unsigned)cs
->style
);
312 /* calculate placement */
313 MDI_CalcDefaultChildPos(w
, ci
->nTotalCreated
++, pos
, 0);
315 if( cs
->cx
== CW_USEDEFAULT16
|| !cs
->cx
)
317 if( cs
->cy
== CW_USEDEFAULT16
|| !cs
->cy
)
320 if( cs
->x
== CW_USEDEFAULT16
)
326 /* restore current maximized child */
327 if( style
& WS_VISIBLE
&& ci
->hwndChildMaximized
)
329 if( style
& WS_MAXIMIZE
)
330 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, FALSE
, 0L );
331 hwndMax
= ci
->hwndChildMaximized
;
332 ShowWindow16( hwndMax
, SW_SHOWNOACTIVATE
);
333 if( style
& WS_MAXIMIZE
)
334 SendMessage16(w
->hwndSelf
, WM_SETREDRAW
, TRUE
, 0L );
337 /* this menu is needed to set a check mark in MDI_ChildActivate */
338 AppendMenu32A(ci
->hWindowMenu
,MF_STRING
,wIDmenu
, lpstrDef
);
340 ci
->nActiveChildren
++;
342 /* fix window style */
343 if( !(w
->dwStyle
& MDIS_ALLCHILDSTYLES
) )
345 style
&= (WS_CHILD
| WS_CLIPSIBLINGS
| WS_MINIMIZE
| WS_MAXIMIZE
|
346 WS_CLIPCHILDREN
| WS_DISABLED
| WS_VSCROLL
| WS_HSCROLL
);
347 style
|= (WS_VISIBLE
| WS_OVERLAPPEDWINDOW
);
350 hwnd
= CreateWindow16( (LPCSTR
)PTR_SEG_TO_LIN(cs
->szClass
),
351 (LPCSTR
)PTR_SEG_TO_LIN(cs
->szTitle
), style
,
352 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
,
353 (HMENU16
)wIDmenu
, w
->hInstance
,
356 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
360 WND
* wnd
= WIN_FindWndPtr( hwnd
);
362 MDI_MenuModifyItem(w
,hwnd
);
363 if( wnd
->dwStyle
& WS_MINIMIZE
&& ci
->hwndActiveChild
)
364 ShowWindow16( hwnd
, SW_SHOWMINNOACTIVE
);
367 SetWindowPos32( hwnd
, 0, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
);
369 /* Set maximized state here in case hwnd didn't receive WM_SIZE
370 * during CreateWindow - bad!
373 if( wnd
->dwStyle
& WS_MAXIMIZE
&& !ci
->hwndChildMaximized
)
375 ci
->hwndChildMaximized
= wnd
->hwndSelf
;
376 MDI_AugmentFrameMenu( ci
, w
->parent
, hwnd
);
377 MDI_UpdateFrameText( w
->parent
, ci
->self
, MDI_REPAINTFRAME
, NULL
);
380 dprintf_mdi(stddeb
, "MDICreateChild: created child - %04x\n",hwnd
);
384 ci
->nActiveChildren
--;
385 DeleteMenu32(ci
->hWindowMenu
,wIDmenu
,MF_BYCOMMAND
);
386 if( IsWindow(hwndMax
) )
387 ShowWindow16(hwndMax
, SW_SHOWMAXIMIZED
);
393 /**********************************************************************
394 * MDI_ChildGetMinMaxInfo
396 static void MDI_ChildGetMinMaxInfo( WND
* clientWnd
, HWND16 hwnd
,
397 MINMAXINFO16
* lpMinMax
)
399 WND
* childWnd
= WIN_FindWndPtr(hwnd
);
400 RECT16 rect
= clientWnd
->rectClient
;
402 MapWindowPoints16(clientWnd
->parent
->hwndSelf
,
403 ((MDICLIENTINFO
*)clientWnd
->wExtra
)->self
, (LPPOINT16
)&rect
, 2);
404 AdjustWindowRectEx16( &rect
, childWnd
->dwStyle
, 0, childWnd
->dwExStyle
);
406 lpMinMax
->ptMaxSize
.x
= rect
.right
-= rect
.left
;
407 lpMinMax
->ptMaxSize
.y
= rect
.bottom
-= rect
.top
;
409 lpMinMax
->ptMaxPosition
.x
= rect
.left
;
410 lpMinMax
->ptMaxPosition
.y
= rect
.top
;
412 dprintf_mdi(stddeb
,"\tChildMinMaxInfo: max rect (%i,%i - %i, %i)\n",
413 rect
.left
,rect
.top
,rect
.right
,rect
.bottom
);
417 /**********************************************************************
418 * MDI_SwitchActiveChild
420 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
423 * wTo is basically lParam of WM_MDINEXT message or explicit
426 static void MDI_SwitchActiveChild( HWND16 clientHwnd
, HWND16 childHwnd
,
429 WND
*w
= WIN_FindWndPtr(clientHwnd
);
434 hwndTo
= MDI_GetWindow(w
,childHwnd
,(WORD
)wTo
);
436 ci
= (MDICLIENTINFO
*) w
->wExtra
;
438 dprintf_mdi(stddeb
, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd
,hwndTo
);
440 if ( !hwndTo
) return;
442 hwndPrev
= ci
->hwndActiveChild
;
444 if ( hwndTo
!= hwndPrev
)
448 if( ci
->hwndChildMaximized
)
451 w
->dwStyle
&= ~WS_VISIBLE
;
454 SetWindowPos32( hwndTo
, HWND_TOP
, 0, 0, 0, 0,
455 SWP_NOMOVE
| SWP_NOSIZE
);
456 if( !wTo
&& hwndPrev
)
458 SetWindowPos32( hwndPrev
, HWND_BOTTOM
, 0, 0, 0, 0,
459 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
463 ShowWindow16( clientHwnd
, SW_SHOW
);
468 /**********************************************************************
471 static HWND16
MDIDestroyChild( WND
*w_parent
, MDICLIENTINFO
*ci
, HWND16 parent
,
472 HWND16 child
, BOOL32 flagDestroy
)
474 WND
*childPtr
= WIN_FindWndPtr(child
);
478 if( child
== ci
->hwndActiveChild
)
480 MDI_SwitchActiveChild(parent
,child
,0);
482 if( child
== ci
->hwndActiveChild
)
484 ShowWindow16( child
, SW_HIDE
);
485 if( child
== ci
->hwndChildMaximized
)
487 MDI_RestoreFrameMenu(w_parent
->parent
, child
);
488 ci
->hwndChildMaximized
= 0;
489 MDI_UpdateFrameText(w_parent
->parent
,parent
,TRUE
,NULL
);
492 MDI_ChildActivate(w_parent
,0);
494 MDI_MenuDeleteItem(w_parent
, child
);
497 ci
->nActiveChildren
--;
499 dprintf_mdi(stddeb
,"MDIDestroyChild: child destroyed - %04x\n",child
);
503 MDI_PostUpdate(GetParent16(child
), ci
, SB_BOTH
+1);
504 DestroyWindow32(child
);
512 /**********************************************************************
515 * Note: hWndChild is NULL when last child is being destroyed
517 static LONG
MDI_ChildActivate( WND
*clientPtr
, HWND16 hWndChild
)
519 MDICLIENTINFO
*clientInfo
= (MDICLIENTINFO
*)clientPtr
->wExtra
;
520 HWND16 prevActiveWnd
= clientInfo
->hwndActiveChild
;
521 WND
*wndPtr
= WIN_FindWndPtr( hWndChild
);
522 WND
*wndPrev
= WIN_FindWndPtr( prevActiveWnd
);
523 BOOL isActiveFrameWnd
= 0;
525 if( hWndChild
== prevActiveWnd
) return 0L;
528 if( wndPtr
->dwStyle
& WS_DISABLED
) return 0L;
530 dprintf_mdi(stddeb
,"MDI_ChildActivate: %04x\n", hWndChild
);
532 if( GetActiveWindow32() == clientPtr
->parent
->hwndSelf
)
533 isActiveFrameWnd
= TRUE
;
535 /* deactivate prev. active child */
538 wndPrev
->dwStyle
|= WS_SYSMENU
;
539 SendMessage16( prevActiveWnd
, WM_NCACTIVATE
, FALSE
, 0L );
542 SendMessage32A( prevActiveWnd
, WM_MDIACTIVATE
, (WPARAM32
)prevActiveWnd
,
546 SendMessage16( prevActiveWnd
, WM_MDIACTIVATE
, FALSE
,
547 MAKELONG(hWndChild
,prevActiveWnd
));
549 /* uncheck menu item */
550 if( clientInfo
->hWindowMenu
)
551 CheckMenuItem32( clientInfo
->hWindowMenu
,
552 wndPrev
->wIDmenu
, 0);
556 if( clientInfo
->hwndChildMaximized
)
557 if( clientInfo
->hwndChildMaximized
!= hWndChild
)
560 clientInfo
->hwndActiveChild
= hWndChild
;
561 ShowWindow16( hWndChild
, SW_SHOWMAXIMIZED
);
564 ShowWindow16( clientInfo
->hwndActiveChild
,
567 clientInfo
->hwndActiveChild
= hWndChild
;
569 /* check if we have any children left */
572 if( isActiveFrameWnd
)
573 SetFocus32( clientInfo
->self
);
577 /* check menu item */
578 if( clientInfo
->hWindowMenu
)
579 CheckMenuItem32( clientInfo
->hWindowMenu
,
580 wndPtr
->wIDmenu
, MF_CHECKED
);
582 /* bring active child to the top */
583 SetWindowPos32( hWndChild
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
585 if( isActiveFrameWnd
)
587 SendMessage16( hWndChild
, WM_NCACTIVATE
, TRUE
, 0L);
588 if( GetFocus32() == clientInfo
->self
)
589 SendMessage16( clientInfo
->self
, WM_SETFOCUS
,
590 (WPARAM16
)clientInfo
->self
, 0L );
592 SetFocus32( clientInfo
->self
);
596 SendMessage32A( hWndChild
, WM_MDIACTIVATE
, (WPARAM32
)hWndChild
,
597 (LPARAM
)prevActiveWnd
);
599 SendMessage16( hWndChild
, WM_MDIACTIVATE
, TRUE
,
600 MAKELONG(hWndChild
,prevActiveWnd
));
606 /**********************************************************************
609 * iTotal returns number of children available for tiling or cascading
611 static MDIWCL
* MDI_BuildWCL(WND
* clientWnd
, INT16
* iTotal
)
613 MDIWCL
*listTop
,*listNext
;
616 if (!(listTop
= (MDIWCL
*)malloc( sizeof(MDIWCL
) ))) return NULL
;
618 listTop
->hChild
= clientWnd
->child
? clientWnd
->child
->hwndSelf
: 0;
619 listTop
->prev
= NULL
;
622 /* build linked list from top child to bottom */
624 childWnd
= WIN_FindWndPtr( listTop
->hChild
);
625 while( childWnd
&& childWnd
->next
)
627 listNext
= (MDIWCL
*)xmalloc(sizeof(MDIWCL
));
629 /* FIXME: pay attention to MDITILE_SKIPDISABLED
630 * when WIN_ISWIN32 is set.
632 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
633 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
634 !(childWnd
->dwStyle
& WS_VISIBLE
) )
640 listNext
->hChild
= childWnd
->next
->hwndSelf
;
641 listNext
->prev
= listTop
;
645 childWnd
= childWnd
->next
;
648 if( (childWnd
->dwStyle
& WS_DISABLED
) ||
649 (childWnd
->dwStyle
& WS_MINIMIZE
) ||
650 !(childWnd
->dwStyle
& WS_VISIBLE
) )
660 /* -------------------- MDI client window functions ------------------- */
662 /**********************************************************************
663 * CreateMDIMenuBitmap
665 static HBITMAP16
CreateMDIMenuBitmap(void)
667 HDC32 hDCSrc
= CreateCompatibleDC32(0);
668 HDC32 hDCDest
= CreateCompatibleDC32(hDCSrc
);
669 HBITMAP16 hbClose
= LoadBitmap16(0, MAKEINTRESOURCE(OBM_CLOSE
) );
670 HBITMAP16 hbCopy
,hb_src
,hb_dest
;
672 hb_src
= SelectObject32(hDCSrc
,hbClose
);
673 hbCopy
= CreateCompatibleBitmap(hDCSrc
,SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
);
674 hb_dest
= SelectObject32(hDCDest
,hbCopy
);
676 BitBlt32(hDCDest
, 0, 0, SYSMETRICS_CXSIZE
, SYSMETRICS_CYSIZE
,
677 hDCSrc
, SYSMETRICS_CXSIZE
, 0, SRCCOPY
);
679 SelectObject32(hDCSrc
,hb_src
);
680 SelectObject32(hDCDest
,hb_dest
);
682 DeleteObject32(hbClose
);
690 /**********************************************************************
693 static LONG
MDICascade(WND
* clientWnd
, MDICLIENTINFO
*ci
)
695 MDIWCL
*listTop
,*listPrev
;
696 INT16 delta
= 0,iToPosition
= 0, n
= 0;
699 if (ci
->hwndChildMaximized
)
700 ShowWindow16( ci
->hwndChildMaximized
, SW_NORMAL
);
702 if (ci
->nActiveChildren
== 0) return 0;
704 if (!(listTop
= MDI_BuildWCL(clientWnd
,&iToPosition
))) return 0;
706 if( iToPosition
< ci
->nActiveChildren
)
707 delta
= 2 * SYSMETRICS_CYICONSPACING
+ SYSMETRICS_CYICON
;
709 /* walk list and move windows */
712 dprintf_mdi(stddeb
, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
713 listTop
->hChild
, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
);
715 if( listTop
->hChild
)
717 MDI_CalcDefaultChildPos(clientWnd
, n
++, pos
, delta
);
718 SetWindowPos32(listTop
->hChild
, 0, pos
[0].x
, pos
[0].y
, pos
[1].x
, pos
[1].y
,
719 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
722 listPrev
= listTop
->prev
;
727 if( iToPosition
< ci
->nActiveChildren
)
728 ArrangeIconicWindows32( clientWnd
->hwndSelf
);
733 /**********************************************************************
737 static LONG
MDITile(WND
* wndClient
, MDICLIENTINFO
*ci
,WORD wParam
)
739 MDIWCL
*listTop
,*listPrev
;
746 INT16 iToPosition
= 0;
748 if (ci
->hwndChildMaximized
)
749 ShowWindow16(ci
->hwndChildMaximized
, SW_NORMAL
);
751 if (ci
->nActiveChildren
== 0) return 0;
753 listTop
= MDI_BuildWCL(wndClient
, &iToPosition
);
755 dprintf_mdi(stddeb
,"MDITile: %i windows to tile\n",iToPosition
);
757 if( !listTop
) return 0;
762 rect
= wndClient
->rectClient
;
763 rows
= (int) sqrt((double) iToPosition
);
764 columns
= iToPosition
/ rows
;
766 if (wParam
== MDITILE_HORIZONTAL
) /* version >= 3.1 */
769 rows
=columns
; /* exchange r and c */
774 if( iToPosition
!= ci
->nActiveChildren
)
776 y
= rect
.bottom
- 2 * SYSMETRICS_CYICONSPACING
- SYSMETRICS_CYICON
;
777 rect
.bottom
= ( y
- SYSMETRICS_CYICON
< rect
.top
)? rect
.bottom
: y
;
780 ysize
= rect
.bottom
/ rows
;
781 xsize
= rect
.right
/ columns
;
786 for (c
= 1; c
<= columns
; c
++)
790 rows
= iToPosition
- i
;
791 ysize
= rect
.bottom
/ rows
;
795 for (r
= 1; r
<= rows
; r
++, i
++)
797 /* shouldn't happen but... */
801 /* skip iconized childs from tiling */
802 while (!listTop
->hChild
)
804 listPrev
= listTop
->prev
;
808 SetWindowPos32(listTop
->hChild
, 0, x
, y
, xsize
, ysize
,
809 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
811 listPrev
= listTop
->prev
;
819 /* free the rest if any */
822 listPrev
= listTop
->prev
;
827 if (iToPosition
< ci
->nActiveChildren
)
828 ArrangeIconicWindows32( wndClient
->hwndSelf
);
833 /* ----------------------- Frame window ---------------------------- */
836 /**********************************************************************
837 * MDI_AugmentFrameMenu
839 static BOOL32
MDI_AugmentFrameMenu( MDICLIENTINFO
* ci
, WND
*frame
,
842 WND
* child
= WIN_FindWndPtr(hChild
);
843 HMENU16 hSysPopup
= 0;
845 dprintf_mdi(stddeb
,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame
,hChild
);
847 if( !frame
->wIDmenu
|| !child
->hSysMenu
) return 0;
849 /* create a copy of sysmenu popup and insert it into frame menu bar */
851 if (!(hSysPopup
= LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU
))))
854 dprintf_mdi(stddeb
,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup
,child
->hSysMenu
);
856 if( !InsertMenu32A(frame
->wIDmenu
,0,MF_BYPOSITION
| MF_BITMAP
| MF_POPUP
,
857 hSysPopup
, (LPSTR
)(DWORD
)hBmpClose
))
858 { DestroyMenu32(hSysPopup
); return 0; }
860 if( !AppendMenu32A(frame
->wIDmenu
,MF_HELP
| MF_BITMAP
,
861 SC_RESTORE
, (LPSTR
)(DWORD
)hBmpRestore
))
863 RemoveMenu32(frame
->wIDmenu
,0,MF_BYPOSITION
);
867 EnableMenuItem32(hSysPopup
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
868 EnableMenuItem32(hSysPopup
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
869 EnableMenuItem32(hSysPopup
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
872 DrawMenuBar32(frame
->hwndSelf
);
877 /**********************************************************************
878 * MDI_RestoreFrameMenu
880 static BOOL32
MDI_RestoreFrameMenu( WND
*frameWnd
, HWND16 hChild
)
882 INT32 nItems
= GetMenuItemCount32(frameWnd
->wIDmenu
) - 1;
884 dprintf_mdi(stddeb
,"MDI_RestoreFrameMenu: for child %04x\n",hChild
);
886 if( GetMenuItemID32(frameWnd
->wIDmenu
,nItems
) != SC_RESTORE
)
890 RemoveMenu32(frameWnd
->wIDmenu
,0,MF_BYPOSITION
);
891 DeleteMenu32(frameWnd
->wIDmenu
,nItems
-1,MF_BYPOSITION
);
893 DrawMenuBar32(frameWnd
->hwndSelf
);
898 /**********************************************************************
899 * MDI_UpdateFrameText
901 * used when child window is maximized/restored
903 * Note: lpTitle can be NULL
905 static void MDI_UpdateFrameText( WND
*frameWnd
, HWND16 hClient
,
906 BOOL32 repaint
, LPCSTR lpTitle
)
908 char lpBuffer
[MDI_MAXTITLELENGTH
+1];
909 WND
* clientWnd
= WIN_FindWndPtr(hClient
);
911 MDICLIENTINFO
*ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
913 dprintf_mdi(stddeb
, "MDI: repaint %i, frameText %s\n", repaint
, (lpTitle
)?lpTitle
:"NULL");
915 /* store new "default" title if lpTitle is not NULL */
918 if (ci
->frameTitle
) HeapFree( SystemHeap
, 0, ci
->frameTitle
);
919 ci
->frameTitle
= HEAP_strdupA( SystemHeap
, 0, lpTitle
);
924 WND
* childWnd
= WIN_FindWndPtr( ci
->hwndChildMaximized
);
926 if( childWnd
&& childWnd
->text
)
928 /* combine frame title and child title if possible */
930 LPCSTR lpBracket
= " - [";
931 int i_frame_text_length
= strlen(ci
->frameTitle
);
932 int i_child_text_length
= strlen(childWnd
->text
);
934 lstrcpyn32A( lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
936 if( i_frame_text_length
+ 6 < MDI_MAXTITLELENGTH
)
938 strcat( lpBuffer
, lpBracket
);
940 if( i_frame_text_length
+ i_child_text_length
+ 6 < MDI_MAXTITLELENGTH
)
942 strcat( lpBuffer
, childWnd
->text
);
943 strcat( lpBuffer
, "]" );
947 lstrcpyn32A( lpBuffer
+ i_frame_text_length
+ 4,
949 MDI_MAXTITLELENGTH
- i_frame_text_length
- 5 );
950 strcat( lpBuffer
, "]" );
956 strncpy(lpBuffer
, ci
->frameTitle
, MDI_MAXTITLELENGTH
);
957 lpBuffer
[MDI_MAXTITLELENGTH
]='\0';
963 DEFWND_SetText( frameWnd
, lpBuffer
);
964 if( repaint
== MDI_REPAINTFRAME
)
965 SetWindowPos32(frameWnd
->hwndSelf
, 0,0,0,0,0, SWP_FRAMECHANGED
|
966 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
970 /* ----------------------------- Interface ---------------------------- */
973 /**********************************************************************
976 * This function is the handler for all MDI requests.
978 LRESULT
MDIClientWndProc(HWND16 hwnd
, UINT message
, WPARAM16 wParam
, LPARAM lParam
)
981 LPCLIENTCREATESTRUCT16 ccs
;
984 WND
*w
= WIN_FindWndPtr(hwnd
);
985 WND
*frameWnd
= w
->parent
;
988 ci
= (MDICLIENTINFO
*) w
->wExtra
;
994 cs
= (LPCREATESTRUCT16
) PTR_SEG_TO_LIN(lParam
);
996 /* Translation layer doesn't know what's in the cs->lpCreateParams
997 * so we have to keep track of what environment we're in. */
999 if( w
->flags
& WIN_ISWIN32
)
1000 ccs
= (LPCLIENTCREATESTRUCT16
) cs
->lpCreateParams
;
1002 ccs
= (LPCLIENTCREATESTRUCT16
) PTR_SEG_TO_LIN(cs
->lpCreateParams
);
1004 ci
->hWindowMenu
= ccs
->hWindowMenu
;
1005 ci
->idFirstChild
= ccs
->idFirstChild
;
1006 ci
->hwndChildMaximized
= 0;
1007 ci
->nActiveChildren
= 0;
1008 ci
->nTotalCreated
= 0;
1009 ci
->frameTitle
= NULL
;
1010 ci
->sbNeedUpdate
= 0;
1012 w
->dwStyle
|= WS_CLIPCHILDREN
;
1016 hBmpClose
= CreateMDIMenuBitmap();
1017 hBmpRestore
= LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORE
) );
1019 MDI_UpdateFrameText(frameWnd
, hwnd
, MDI_NOFRAMEREPAINT
,frameWnd
->text
);
1021 AppendMenu32A( ccs
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
1023 GetClientRect16(frameWnd
->hwndSelf
, &rect
);
1024 NC_HandleNCCalcSize( w
, &rect
);
1025 w
->rectClient
= rect
;
1027 dprintf_mdi(stddeb
,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd
,ci
->idFirstChild
);
1032 if( ci
->hwndChildMaximized
) MDI_RestoreFrameMenu(w
, frameWnd
->hwndSelf
);
1033 if((nItems
= GetMenuItemCount32(ci
->hWindowMenu
)) > 0) {
1034 ci
->idFirstChild
= nItems
- 1;
1035 ci
->nActiveChildren
++; /* to delete a separator */
1036 while( ci
->nActiveChildren
-- )
1037 DeleteMenu32(ci
->hWindowMenu
,MF_BYPOSITION
,ci
->idFirstChild
--);
1041 case WM_MDIACTIVATE
:
1042 if( ci
->hwndActiveChild
!= (HWND16
)wParam
)
1043 SetWindowPos32((HWND32
)wParam
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1047 return MDICascade(w
, ci
);
1052 MDICREATESTRUCT16
* cs
= (MDICREATESTRUCT16
*) PTR_SEG_TO_LIN(lParam
);
1053 return (LONG
)MDICreateChild(w
, ci
, hwnd
, cs
, lParam
);
1058 return (LONG
)MDIDestroyChild(w
, ci
, hwnd
, (HWND32
)wParam
, TRUE
);
1060 case WM_MDIGETACTIVE
:
1061 return ((LONG
) ci
->hwndActiveChild
|
1062 ((LONG
) (ci
->hwndChildMaximized
>0) << 16));
1064 case WM_MDIICONARRANGE
:
1065 ci
->sbNeedUpdate
= TRUE
;
1066 MDIIconArrange(hwnd
);
1067 ci
->sbRecalc
= SB_BOTH
+1;
1068 SendMessage16(hwnd
,WM_MDICALCCHILDSCROLL
,0,0L);
1071 case WM_MDIMAXIMIZE
:
1072 ShowWindow16((HWND16
)wParam
, SW_MAXIMIZE
);
1076 MDI_SwitchActiveChild(hwnd
, (HWND16
)wParam
, (lParam
)?1:0);
1080 ShowWindow16( (HWND16
)wParam
, SW_NORMAL
);
1085 return (LRESULT
)MDISetMenu(hwnd
, FALSE
, (HMENU16
)wParam
, (HMENU16
)lParam
);
1087 return (LRESULT
)MDISetMenu(hwnd
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1091 ci
->sbNeedUpdate
= TRUE
;
1092 ShowScrollBar32(hwnd
,SB_BOTH
,FALSE
);
1093 MDITile(w
, ci
,wParam
);
1094 ci
->sbNeedUpdate
= FALSE
;
1099 ci
->sbNeedUpdate
= TRUE
;
1100 ScrollChildren32(hwnd
,message
,wParam
,lParam
);
1101 ci
->sbNeedUpdate
= FALSE
;
1105 if( ci
->hwndActiveChild
)
1107 w
= WIN_FindWndPtr( ci
->hwndActiveChild
);
1108 if( !(w
->dwStyle
& WS_MINIMIZE
) )
1109 SetFocus32( ci
->hwndActiveChild
);
1114 if( ci
->hwndActiveChild
)
1115 SendMessage16(ci
->hwndActiveChild
, message
, wParam
, lParam
);
1118 case WM_PARENTNOTIFY
:
1119 if( wParam
== WM_LBUTTONDOWN
)
1121 POINT16 pt
= MAKEPOINT16(lParam
);
1122 HWND16 child
= ChildWindowFromPoint16(hwnd
, pt
);
1124 dprintf_mdi(stddeb
,"MDIClient: notification from %04x (%i,%i)\n",child
,pt
.x
,pt
.y
);
1126 if( child
&& child
!= hwnd
&&
1127 child
!= ci
->hwndActiveChild
)
1128 SetWindowPos32(child
, 0,0,0,0,0, SWP_NOSIZE
| SWP_NOMOVE
);
1133 if( ci
->hwndChildMaximized
)
1135 WND
* child
= WIN_FindWndPtr(ci
->hwndChildMaximized
);
1136 RECT16 rect
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
1138 AdjustWindowRectEx16(&rect
, child
->dwStyle
, 0, child
->dwExStyle
);
1139 MoveWindow16(ci
->hwndChildMaximized
, rect
.left
, rect
.top
,
1140 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, 1);
1143 MDI_PostUpdate(hwnd
, ci
, SB_BOTH
+1);
1147 case WM_MDICALCCHILDSCROLL
:
1148 if( ci
->sbNeedUpdate
)
1151 CalcChildScroll(hwnd
, ci
->sbRecalc
-1);
1152 ci
->sbRecalc
= ci
->sbNeedUpdate
= 0;
1157 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1161 /***********************************************************************
1162 * DefFrameProc16 (USER.445)
1164 LRESULT
DefFrameProc16( HWND16 hwnd
, HWND16 hwndMDIClient
, UINT16 message
,
1165 WPARAM16 wParam
, LPARAM lParam
)
1176 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1177 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1179 /* check for possible syscommands for maximized MDI child */
1182 wParam
< ci
->idFirstChild
||
1183 wParam
>= ci
->idFirstChild
+ ci
->nActiveChildren
1185 if( (wParam
- 0xF000) & 0xF00F ) break;
1196 if( ci
->hwndChildMaximized
)
1197 return SendMessage16( ci
->hwndChildMaximized
, WM_SYSCOMMAND
,
1203 childHwnd
= MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient
),
1206 SendMessage16(hwndMDIClient
, WM_MDIACTIVATE
,
1207 (WPARAM16
)childHwnd
, 0L);
1212 SendMessage16(hwndMDIClient
, message
, wParam
, lParam
);
1216 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd
), hwndMDIClient
,
1218 (LPCSTR
)PTR_SEG_TO_LIN(lParam
));
1222 SetFocus32(hwndMDIClient
);
1226 MoveWindow16(hwndMDIClient
, 0, 0,
1227 LOWORD(lParam
), HIWORD(lParam
), TRUE
);
1232 wndPtr
= WIN_FindWndPtr(hwndMDIClient
);
1233 ci
= (MDICLIENTINFO
*)wndPtr
->wExtra
;
1235 if( !(wndPtr
->parent
->dwStyle
& WS_MINIMIZE
)
1236 && ci
->hwndActiveChild
&& !ci
->hwndChildMaximized
)
1238 /* control menu is between the frame system menu and
1239 * the first entry of menu bar */
1241 if( wParam
== VK_LEFT
)
1242 { if( wndPtr
->parent
->wIDmenu
!= LOWORD(lParam
) ) break; }
1243 else if( wParam
== VK_RIGHT
)
1244 { if( GetSystemMenu16( wndPtr
->parent
->hwndSelf
, 0)
1245 != LOWORD(lParam
) ) break; }
1248 return MAKELONG( GetSystemMenu16(ci
->hwndActiveChild
, 0),
1249 ci
->hwndActiveChild
);
1255 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1259 /***********************************************************************
1260 * DefFrameProc32A (USER32.121)
1262 LRESULT
DefFrameProc32A( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1263 WPARAM32 wParam
, LPARAM lParam
)
1270 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1272 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1275 SendMessage32A(hwndMDIClient
, message
, wParam
, lParam
);
1280 LPSTR segstr
= SEGPTR_STRDUP((LPSTR
)lParam
);
1282 ret
= DefFrameProc16(hwnd
, hwndMDIClient
, message
,
1283 wParam
, (LPARAM
)SEGPTR_GET(segstr
) );
1284 SEGPTR_FREE(segstr
);
1290 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1295 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1299 /***********************************************************************
1300 * DefFrameProc32W (USER32.122)
1302 LRESULT
DefFrameProc32W( HWND32 hwnd
, HWND32 hwndMDIClient
, UINT32 message
,
1303 WPARAM32 wParam
, LPARAM lParam
)
1310 return DefFrameProc16( hwnd
, hwndMDIClient
, message
,
1312 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ) );
1315 SendMessage32W(hwndMDIClient
, message
, wParam
, lParam
);
1319 LPSTR txt
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lParam
);
1320 LRESULT ret
= DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1321 wParam
, (DWORD
)txt
);
1322 HeapFree(GetProcessHeap(),0,txt
);
1327 return DefFrameProc32A( hwnd
, hwndMDIClient
, message
,
1332 return DefWindowProc32W( hwnd
, message
, wParam
, lParam
);
1336 /***********************************************************************
1337 * DefMDIChildProc16 (USER.447)
1339 LRESULT
DefMDIChildProc16( HWND16 hwnd
, UINT16 message
,
1340 WPARAM16 wParam
, LPARAM lParam
)
1345 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1346 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1351 DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1352 MDI_MenuModifyItem(clientWnd
,hwnd
);
1353 if( ci
->hwndChildMaximized
== hwnd
)
1354 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1355 MDI_REPAINTFRAME
, NULL
);
1359 SendMessage16(ci
->self
,WM_MDIDESTROY
,(WPARAM16
)hwnd
,0L);
1363 if( ci
->hwndActiveChild
!= hwnd
)
1364 MDI_ChildActivate(clientWnd
, hwnd
);
1367 case WM_CHILDACTIVATE
:
1368 MDI_ChildActivate(clientWnd
, hwnd
);
1372 dprintf_mdi(stddeb
,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
1373 hwnd
, ci
->hwndActiveChild
);
1380 if( ci
->hwndChildMaximized
== hwnd
) return 0;
1384 WIN_FindWndPtr(hwnd
)->dwStyle
|= WS_SYSMENU
;
1387 if( ci
->hwndChildMaximized
== hwnd
)
1388 return SendMessage16( clientWnd
->parent
->hwndSelf
,
1389 message
, wParam
, lParam
);
1390 WIN_FindWndPtr(hwnd
)->dwStyle
&= ~WS_SYSMENU
;
1393 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 0);
1396 SendMessage16( ci
->self
, WM_MDINEXT
, 0, 1);
1401 case WM_GETMINMAXINFO
:
1402 MDI_ChildGetMinMaxInfo(clientWnd
, hwnd
, (MINMAXINFO16
*) PTR_SEG_TO_LIN(lParam
));
1406 if( ci
->hwndChildMaximized
)
1407 ci
->sbNeedUpdate
= 0;
1409 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1415 if( ci
->hwndActiveChild
== hwnd
&& wParam
!= SIZE_MAXIMIZED
)
1417 ci
->hwndChildMaximized
= 0;
1419 MDI_RestoreFrameMenu( clientWnd
->parent
, hwnd
);
1420 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1421 MDI_REPAINTFRAME
, NULL
);
1424 if( wParam
== SIZE_MAXIMIZED
)
1426 HWND16 hMaxChild
= ci
->hwndChildMaximized
;
1428 if( hMaxChild
== hwnd
) break;
1432 SendMessage16( hMaxChild
, WM_SETREDRAW
, FALSE
, 0L );
1434 MDI_RestoreFrameMenu( clientWnd
->parent
, hMaxChild
);
1435 ShowWindow16( hMaxChild
, SW_SHOWNOACTIVATE
);
1437 SendMessage16( hMaxChild
, WM_SETREDRAW
, TRUE
, 0L );
1440 dprintf_mdi(stddeb
,"\tMDI: maximizing child %04x\n", hwnd
);
1442 ci
->hwndChildMaximized
= hwnd
; /* !!! */
1444 MDI_AugmentFrameMenu( ci
, clientWnd
->parent
, hwnd
);
1445 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1446 MDI_REPAINTFRAME
, NULL
);
1449 if( wParam
== SIZE_MINIMIZED
)
1451 HWND16 switchTo
= MDI_GetWindow(clientWnd
, hwnd
, 0);
1454 SendMessage16( switchTo
, WM_CHILDACTIVATE
, 0, 0L);
1457 MDI_PostUpdate(clientWnd
->hwndSelf
, ci
, SB_BOTH
+1);
1462 /* MDI children don't have menu bars */
1463 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1464 (WPARAM16
)SC_KEYMENU
, (LPARAM
)wParam
);
1469 if( wParam
== VK_LEFT
) /* switch to frame system menu */
1470 return MAKELONG( GetSystemMenu16(clientWnd
->parent
->hwndSelf
, 0),
1471 clientWnd
->parent
->hwndSelf
);
1472 if( wParam
== VK_RIGHT
) /* to frame menu bar */
1473 return MAKELONG( clientWnd
->parent
->wIDmenu
,
1474 clientWnd
->parent
->hwndSelf
);
1479 return DefWindowProc16(hwnd
, message
, wParam
, lParam
);
1483 /***********************************************************************
1484 * DefMDIChildProc32A (USER32.123)
1486 LRESULT
DefMDIChildProc32A( HWND32 hwnd
, UINT32 message
,
1487 WPARAM32 wParam
, LPARAM lParam
)
1492 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1493 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1498 DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1499 MDI_MenuModifyItem(clientWnd
,hwnd
);
1500 if( ci
->hwndChildMaximized
== hwnd
)
1501 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1502 MDI_REPAINTFRAME
, NULL
);
1505 case WM_GETMINMAXINFO
:
1508 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32
*)lParam
, &mmi
);
1509 MDI_ChildGetMinMaxInfo( clientWnd
, hwnd
, &mmi
);
1510 STRUCT32_MINMAXINFO16to32( &mmi
, (MINMAXINFO32
*)lParam
);
1516 /* MDI children don't have menu bars */
1517 PostMessage( clientWnd
->parent
->hwndSelf
, WM_SYSCOMMAND
,
1518 (WPARAM16
)SC_KEYMENU
, (LPARAM
)LOWORD(wParam
) );
1523 case WM_CHILDACTIVATE
:
1529 return DefMDIChildProc16( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1531 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);
1535 /***********************************************************************
1536 * DefMDIChildProc32W (USER32.124)
1538 LRESULT
DefMDIChildProc32W( HWND32 hwnd
, UINT32 message
,
1539 WPARAM32 wParam
, LPARAM lParam
)
1544 clientWnd
= WIN_FindWndPtr(GetParent16(hwnd
));
1545 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1550 DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1551 MDI_MenuModifyItem(clientWnd
,hwnd
);
1552 if( ci
->hwndChildMaximized
== hwnd
)
1553 MDI_UpdateFrameText( clientWnd
->parent
, ci
->self
,
1554 MDI_REPAINTFRAME
, NULL
);
1557 case WM_GETMINMAXINFO
:
1561 case WM_CHILDACTIVATE
:
1567 return DefMDIChildProc32A( hwnd
, message
, (WPARAM16
)wParam
, lParam
);
1569 return DefWindowProc32W(hwnd
, message
, wParam
, lParam
);
1573 /**********************************************************************
1574 * CreateMDIWindowA (USER32.78)
1577 /**********************************************************************
1578 * CreateMDIWindowW (USER32.79)
1581 /**********************************************************************
1582 * TranslateMDISysAccel32 (USER32.554)
1584 BOOL32
TranslateMDISysAccel32( HWND32 hwndClient
, LPMSG32 msg
)
1588 STRUCT32_MSG32to16(msg
,&msg16
);
1589 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1590 return TranslateMDISysAccel16(hwndClient
,&msg16
);
1594 /**********************************************************************
1595 * TranslateMDISysAccel16 (USER.451)
1597 BOOL16
TranslateMDISysAccel16( HWND16 hwndClient
, LPMSG16 msg
)
1599 WND
* clientWnd
= WIN_FindWndPtr( hwndClient
);
1601 MDICLIENTINFO
*ci
= NULL
;
1602 WPARAM16 wParam
= 0;
1604 if( (msg
->message
!= WM_KEYDOWN
&& msg
->message
!= WM_SYSKEYDOWN
) || !clientWnd
)
1607 ci
= (MDICLIENTINFO
*) clientWnd
->wExtra
;
1608 wnd
= WIN_FindWndPtr(ci
->hwndActiveChild
);
1610 if( !wnd
) return 0;
1612 if( wnd
->dwStyle
& WS_DISABLED
) return 0;
1614 if ((GetKeyState32(VK_CONTROL
) & 0x8000) && !(GetKeyState32(VK_MENU
) & 0x8000))
1615 switch( msg
->wParam
)
1619 wParam
= ( GetKeyState32(VK_SHIFT
) & 0x8000 )? SC_NEXTWINDOW
: SC_PREVWINDOW
;
1631 dprintf_mdi(stddeb
,"TranslateMDISysAccel: wParam = %04x\n", wParam
);
1633 SendMessage16(ci
->hwndActiveChild
,WM_SYSCOMMAND
, wParam
, (LPARAM
)msg
->wParam
);
1638 /***********************************************************************
1639 * CalcChildScroll (USER.462)
1641 void CalcChildScroll( HWND16 hwnd
, WORD scroll
)
1643 RECT16 childRect
, clientRect
;
1644 INT vmin
, vmax
, hmin
, hmax
, vpos
, hpos
;
1645 BOOL noscroll
= FALSE
;
1648 if (!(Wnd
= pWnd
= WIN_FindWndPtr( hwnd
))) return;
1649 GetClientRect16( hwnd
, &clientRect
);
1650 SetRectEmpty16( &childRect
);
1652 for ( pWnd
= pWnd
->child
; pWnd
; pWnd
= pWnd
->next
)
1654 UnionRect16( &childRect
, &pWnd
->rectWindow
, &childRect
);
1655 if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1658 UnionRect16( &childRect
, &clientRect
, &childRect
);
1660 /* jump through the hoops to prevent excessive flashing
1663 hmin
= childRect
.left
; hmax
= childRect
.right
- clientRect
.right
;
1664 hpos
= clientRect
.left
- childRect
.left
;
1665 vmin
= childRect
.top
; vmax
= childRect
.bottom
- clientRect
.bottom
;
1666 vpos
= clientRect
.top
- childRect
.top
;
1669 ShowScrollBar32(hwnd
, SB_BOTH
, FALSE
);
1674 vpos
= hpos
; vmin
= hmin
; vmax
= hmax
;
1676 SetScrollPos32(hwnd
, scroll
, vpos
, FALSE
);
1677 SetScrollRange32(hwnd
, scroll
, vmin
, vmax
, TRUE
);
1680 SCROLL_SetNCSbState( Wnd
, vmin
, vmax
, vpos
,
1682 SetWindowPos32(hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
1683 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
1688 /***********************************************************************
1689 * ScrollChildren16 (USER.463)
1691 void ScrollChildren16(HWND16 hWnd
, UINT16 uMsg
, WPARAM16 wParam
, LPARAM lParam
)
1693 return ScrollChildren32( hWnd
, uMsg
, wParam
, lParam
);
1697 /***********************************************************************
1698 * ScrollChildren32 (USER32.447)
1700 void ScrollChildren32(HWND32 hWnd
, UINT32 uMsg
, WPARAM32 wParam
, LPARAM lParam
)
1702 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1704 INT32 curPos
, length
, minPos
, maxPos
, shift
;
1706 if( !wndPtr
) return;
1708 if( uMsg
== WM_HSCROLL
)
1710 GetScrollRange32(hWnd
,SB_HORZ
,&minPos
,&maxPos
);
1711 curPos
= GetScrollPos32(hWnd
,SB_HORZ
);
1712 length
= (wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
)/2;
1713 shift
= SYSMETRICS_CYHSCROLL
;
1715 else if( uMsg
== WM_VSCROLL
)
1717 GetScrollRange32(hWnd
,SB_VERT
,&minPos
,&maxPos
);
1718 curPos
= GetScrollPos32(hWnd
,SB_VERT
);
1719 length
= (wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
)/2;
1720 shift
= SYSMETRICS_CXVSCROLL
;
1727 newPos
= curPos
- shift
;
1730 newPos
= curPos
+ shift
;
1733 newPos
= curPos
- length
;
1736 newPos
= curPos
+ length
;
1739 case SB_THUMBPOSITION
:
1740 newPos
= LOWORD(lParam
);
1753 CalcChildScroll(hWnd
,(uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
);
1757 if( newPos
> maxPos
)
1759 else if( newPos
< minPos
)
1762 SetScrollPos32(hWnd
, (uMsg
== WM_VSCROLL
)?SB_VERT
:SB_HORZ
, newPos
, TRUE
);
1764 if( uMsg
== WM_VSCROLL
)
1765 ScrollWindow32(hWnd
,0 ,curPos
- newPos
, NULL
, NULL
);
1767 ScrollWindow32(hWnd
,curPos
- newPos
, 0, NULL
, NULL
);