Removed process argument to PROCESS_CallUserSignalProc.
[wine/multimedia.git] / windows / mdi.c
blob43f340e0d07eb262305e9db4d107bac49a9cfa50
1 /* MDI.C
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.
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include "winuser.h"
19 #include "win.h"
20 #include "heap.h"
21 #include "nonclient.h"
22 #include "mdi.h"
23 #include "user.h"
24 #include "menu.h"
25 #include "resource.h"
26 #include "struct32.h"
27 #include "tweak.h"
28 #include "debug.h"
30 DEFAULT_DEBUG_CHANNEL(mdi)
32 #define MDIF_NEEDUPDATE 0x0001
34 static HBITMAP16 hBmpClose = 0;
35 static HBITMAP16 hBmpRestore = 0;
37 INT SCROLL_SetNCSbState(WND*,int,int,int,int,int,int);
39 /* ----------------- declarations ----------------- */
40 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
41 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
42 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
44 static LONG MDI_ChildActivate( WND*, HWND );
46 /* -------- Miscellaneous service functions ----------
48 * MDI_GetChildByID
51 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
53 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
54 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
55 return 0;
58 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
60 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
62 ci->mdiFlags |= MDIF_NEEDUPDATE;
63 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
65 ci->sbRecalc = recalc;
68 /**********************************************************************
69 * MDI_MenuModifyItem
71 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
73 char buffer[128];
74 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
75 WND *wndPtr = WIN_FindWndPtr(hWndChild);
76 UINT n = sprintf(buffer, "%d ",
77 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
78 BOOL bRet = 0;
80 if( !clientInfo->hWindowMenu )
82 bRet = FALSE;
83 goto END;
86 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
88 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
89 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
90 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
91 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
92 END:
93 WIN_ReleaseWndPtr(wndPtr);
94 return bRet;
97 /**********************************************************************
98 * MDI_MenuDeleteItem
100 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
102 char buffer[128];
103 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
104 WND *wndPtr = WIN_FindWndPtr(hWndChild);
105 UINT index = 0,id,n;
106 BOOL retvalue;
108 if( !clientInfo->nActiveChildren ||
109 !clientInfo->hWindowMenu )
111 retvalue = FALSE;
112 goto END;
115 id = wndPtr->wIDmenu;
116 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
118 /* walk the rest of MDI children to prevent gaps in the id
119 * sequence and in the menu child list */
121 for( index = id+1; index <= clientInfo->nActiveChildren +
122 clientInfo->idFirstChild; index++ )
124 WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
125 if( !tmpWnd )
127 TRACE(mdi,"no window for id=%i\n",index);
128 WIN_ReleaseWndPtr(tmpWnd);
129 continue;
132 /* set correct id */
133 tmpWnd->wIDmenu--;
135 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
136 if (tmpWnd->text)
137 lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n );
139 /* change menu */
140 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
141 index - 1 , buffer );
142 WIN_ReleaseWndPtr(tmpWnd);
144 retvalue = TRUE;
145 END:
146 WIN_ReleaseWndPtr(wndPtr);
147 return retvalue;
150 /**********************************************************************
151 * MDI_GetWindow
153 * returns "activateable" child different from the current or zero
155 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
156 DWORD dwStyleMask )
158 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
159 WND *wndPtr, *pWnd, *pWndLast = NULL;
161 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
162 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
164 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
166 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
168 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
170 if ( pWnd == wndPtr ) break; /* went full circle */
172 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
174 pWndLast = pWnd;
175 if ( bNext ) break;
178 WIN_ReleaseWndPtr(wndPtr);
179 WIN_ReleaseWndPtr(pWnd);
180 return pWndLast ? pWndLast->hwndSelf : 0;
183 /**********************************************************************
184 * MDI_CalcDefaultChildPos
186 * It seems that the default height is about 2/3 of the client rect
188 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
189 INT delta)
191 INT nstagger;
192 RECT rect = w->rectClient;
193 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
194 GetSystemMetrics(SM_CYFRAME) - 1;
196 if( rect.bottom - rect.top - delta >= spacing )
197 rect.bottom -= delta;
199 nstagger = (rect.bottom - rect.top)/(3 * spacing);
200 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
201 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
202 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
205 /**********************************************************************
206 * MDISetMenu
208 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
209 HMENU hmenuWindow)
211 WND *w = WIN_FindWndPtr(hwnd);
212 MDICLIENTINFO *ci;
213 HWND hwndFrame = GetParent(hwnd);
214 HMENU oldFrameMenu = GetMenu(hwndFrame);
216 TRACE(mdi, "%04x %04x %04x\n",
217 hwnd, hmenuFrame, hmenuWindow);
219 ci = (MDICLIENTINFO *) w->wExtra;
221 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
222 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
224 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
226 /* delete menu items from ci->hWindowMenu
227 * and add them to hmenuWindow */
229 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
230 INT pos = GetMenuItemCount(hmenuWindow) + 1;
232 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
234 if( ci->nActiveChildren )
236 INT j = i - ci->nActiveChildren + 1;
237 char buffer[100];
238 UINT id,state;
240 for( ; i >= j ; i-- )
242 id = GetMenuItemID(ci->hWindowMenu,i );
243 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
245 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
247 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
248 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
249 id, buffer);
250 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
254 /* remove separator */
255 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
257 ci->hWindowMenu = hmenuWindow;
260 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
262 SetMenu(hwndFrame, hmenuFrame);
263 if( ci->hwndChildMaximized )
264 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
265 WIN_ReleaseWndPtr(w);
266 return oldFrameMenu;
268 WIN_ReleaseWndPtr(w);
269 return 0;
272 /**********************************************************************
273 * MDIRefreshMenu
275 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
276 HMENU hmenuWindow)
278 HWND hwndFrame = GetParent(hwnd);
279 HMENU oldFrameMenu = GetMenu(hwndFrame);
281 TRACE(mdi, "%04x %04x %04x\n",
282 hwnd, hmenuFrame, hmenuWindow);
284 FIXME(mdi,"partially function stub\n");
286 return oldFrameMenu;
290 /* ------------------ MDI child window functions ---------------------- */
293 /**********************************************************************
294 * MDICreateChild
296 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
297 LPMDICREATESTRUCTA cs )
299 POINT pos[2];
300 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
301 HWND hwnd, hwndMax = 0;
302 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
303 char lpstrDef[]="junk!";
305 TRACE(mdi, "origin %i,%i - dim %i,%i, style %08x\n",
306 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
307 /* calculate placement */
308 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
310 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
311 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
313 if( cs->x == CW_USEDEFAULT )
315 cs->x = pos[0].x;
316 cs->y = pos[0].y;
319 /* restore current maximized child */
320 if( style & WS_VISIBLE && ci->hwndChildMaximized )
322 if( style & WS_MAXIMIZE )
323 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
324 hwndMax = ci->hwndChildMaximized;
325 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
326 if( style & WS_MAXIMIZE )
327 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
330 /* this menu is needed to set a check mark in MDI_ChildActivate */
331 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
333 ci->nActiveChildren++;
335 /* fix window style */
336 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
338 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
339 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
340 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
343 if( w->flags & WIN_ISWIN32 )
345 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
346 cs->x, cs->y, cs->cx, cs->cy, parent,
347 (HMENU16)wIDmenu, cs->hOwner, cs );
349 else
351 MDICREATESTRUCT16 *cs16;
352 LPSTR title, cls;
354 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
355 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
356 title = SEGPTR_STRDUP( cs->szTitle );
357 cls = SEGPTR_STRDUP( cs->szClass );
358 cs16->szTitle = SEGPTR_GET(title);
359 cs16->szClass = SEGPTR_GET(cls);
361 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
362 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
363 (HMENU)wIDmenu, cs16->hOwner,
364 (LPVOID)SEGPTR_GET(cs16) );
365 SEGPTR_FREE( title );
366 SEGPTR_FREE( cls );
367 SEGPTR_FREE( cs16 );
370 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
372 if (hwnd)
374 WND* wnd = WIN_FindWndPtr( hwnd );
376 MDI_MenuModifyItem(w ,hwnd);
377 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
378 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
379 else
381 /* WS_VISIBLE is clear if a) the MDI client has
382 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
383 * MDICreateStruct. If so the created window is not shown nor
384 * activated.
386 int showflag=wnd->dwStyle & WS_VISIBLE;
387 /* clear visible flag, otherwise SetWindoPos32 ignores
388 * the SWP_SHOWWINDOW command.
390 wnd->dwStyle &= ~WS_VISIBLE;
391 if(showflag){
392 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
394 /* Set maximized state here in case hwnd didn't receive WM_SIZE
395 * during CreateWindow - bad!
398 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
400 ci->hwndChildMaximized = wnd->hwndSelf;
401 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
402 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
404 }else
405 /* needed, harmless ? */
406 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
409 WIN_ReleaseWndPtr(wnd);
410 TRACE(mdi, "created child - %04x\n",hwnd);
412 else
414 ci->nActiveChildren--;
415 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
416 if( IsWindow(hwndMax) )
417 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
420 return hwnd;
423 /**********************************************************************
424 * MDI_ChildGetMinMaxInfo
426 * Note: The rule here is that client rect of the maximized MDI child
427 * is equal to the client rect of the MDI client window.
429 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
430 MINMAXINFO16* lpMinMax )
432 WND* childWnd = WIN_FindWndPtr(hwnd);
433 RECT rect = clientWnd->rectClient;
435 MapWindowPoints( clientWnd->parent->hwndSelf,
436 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
437 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
439 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
440 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
442 lpMinMax->ptMaxPosition.x = rect.left;
443 lpMinMax->ptMaxPosition.y = rect.top;
445 WIN_ReleaseWndPtr(childWnd);
447 TRACE(mdi,"max rect (%i,%i - %i, %i)\n",
448 rect.left,rect.top,rect.right,rect.bottom);
452 /**********************************************************************
453 * MDI_SwitchActiveChild
455 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
456 * being activated
458 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
459 BOOL bNextWindow )
461 WND *w = WIN_FindWndPtr(clientHwnd);
462 HWND hwndTo = 0;
463 HWND hwndPrev = 0;
464 MDICLIENTINFO *ci;
466 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
468 ci = (MDICLIENTINFO *) w->wExtra;
470 TRACE(mdi, "from %04x, to %04x\n",childHwnd,hwndTo);
472 if ( !hwndTo ) goto END; /* no window to switch to */
474 hwndPrev = ci->hwndActiveChild;
476 if ( hwndTo != hwndPrev )
478 BOOL bOptimize = 0;
480 if( ci->hwndChildMaximized )
482 bOptimize = 1;
483 w->dwStyle &= ~WS_VISIBLE;
486 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
487 SWP_NOMOVE | SWP_NOSIZE );
489 if( bNextWindow && hwndPrev )
490 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
491 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
492 if( bOptimize )
493 ShowWindow( clientHwnd, SW_SHOW );
495 END:
496 WIN_ReleaseWndPtr(w);
500 /**********************************************************************
501 * MDIDestroyChild
503 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
504 HWND parent, HWND child,
505 BOOL flagDestroy )
507 WND *childPtr = WIN_FindWndPtr(child);
509 if( childPtr )
511 if( child == ci->hwndActiveChild )
513 MDI_SwitchActiveChild(parent, child, TRUE);
515 if( child == ci->hwndActiveChild )
517 ShowWindow( child, SW_HIDE);
518 if( child == ci->hwndChildMaximized )
520 MDI_RestoreFrameMenu(w_parent->parent, child);
521 ci->hwndChildMaximized = 0;
522 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
525 MDI_ChildActivate(w_parent, 0);
527 MDI_MenuDeleteItem(w_parent, child);
529 WIN_ReleaseWndPtr(childPtr);
531 ci->nActiveChildren--;
533 TRACE(mdi,"child destroyed - %04x\n",child);
535 if (flagDestroy)
537 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
538 DestroyWindow(child);
542 return 0;
546 /**********************************************************************
547 * MDI_ChildActivate
549 * Note: hWndChild is NULL when last child is being destroyed
551 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
553 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
554 HWND prevActiveWnd = clientInfo->hwndActiveChild;
555 WND *wndPtr = WIN_FindWndPtr( hWndChild );
556 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
557 BOOL isActiveFrameWnd = 0;
558 LONG retvalue;
560 if( hWndChild == prevActiveWnd )
562 retvalue = 0L;
563 goto END;
566 if( wndPtr )
568 if( wndPtr->dwStyle & WS_DISABLED )
570 retvalue = 0L;
571 goto END;
575 TRACE(mdi,"%04x\n", hWndChild);
577 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
578 isActiveFrameWnd = TRUE;
580 /* deactivate prev. active child */
581 if( wndPrev )
583 wndPrev->dwStyle |= WS_SYSMENU;
584 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
585 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
586 (LPARAM)hWndChild);
587 /* uncheck menu item */
588 if( clientInfo->hWindowMenu )
589 CheckMenuItem( clientInfo->hWindowMenu,
590 wndPrev->wIDmenu, 0);
593 /* set appearance */
594 if( clientInfo->hwndChildMaximized )
596 if( clientInfo->hwndChildMaximized != hWndChild ) {
597 if( hWndChild ) {
598 clientInfo->hwndActiveChild = hWndChild;
599 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
600 } else
601 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
605 clientInfo->hwndActiveChild = hWndChild;
607 /* check if we have any children left */
608 if( !hWndChild )
610 if( isActiveFrameWnd )
611 SetFocus( clientInfo->self );
612 retvalue = 0;
613 goto END;
616 /* check menu item */
617 if( clientInfo->hWindowMenu )
618 CheckMenuItem( clientInfo->hWindowMenu,
619 wndPtr->wIDmenu, MF_CHECKED);
621 /* bring active child to the top */
622 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
624 if( isActiveFrameWnd )
626 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
627 if( GetFocus() == clientInfo->self )
628 SendMessageA( clientInfo->self, WM_SETFOCUS,
629 (WPARAM)clientInfo->self, 0L );
630 else
631 SetFocus( clientInfo->self );
633 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
634 (LPARAM)hWndChild );
635 retvalue = 1;
636 END:
637 WIN_ReleaseWndPtr(wndPtr);
638 WIN_ReleaseWndPtr(wndPrev);
639 return retvalue;
642 /* -------------------- MDI client window functions ------------------- */
644 /**********************************************************************
645 * CreateMDIMenuBitmap
647 static HBITMAP16 CreateMDIMenuBitmap(void)
649 HDC hDCSrc = CreateCompatibleDC(0);
650 HDC hDCDest = CreateCompatibleDC(hDCSrc);
651 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
652 HBITMAP16 hbCopy;
653 HANDLE16 hobjSrc, hobjDest;
655 hobjSrc = SelectObject(hDCSrc, hbClose);
656 hbCopy = CreateCompatibleBitmap(hDCSrc,GetSystemMetrics(SM_CXSIZE),GetSystemMetrics(SM_CYSIZE));
657 hobjDest = SelectObject(hDCDest, hbCopy);
659 BitBlt(hDCDest, 0, 0, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
660 hDCSrc, GetSystemMetrics(SM_CXSIZE), 0, SRCCOPY);
662 SelectObject(hDCSrc, hobjSrc);
663 DeleteObject(hbClose);
664 DeleteDC(hDCSrc);
666 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
668 MoveToEx( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, 0, NULL );
669 LineTo( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, GetSystemMetrics(SM_CYSIZE) - 1);
671 SelectObject(hDCDest, hobjSrc );
672 SelectObject(hDCDest, hobjDest);
673 DeleteDC(hDCDest);
675 return hbCopy;
678 /**********************************************************************
679 * MDICascade
681 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
683 WND** ppWnd;
684 UINT total;
686 if (ci->hwndChildMaximized)
687 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
688 (WPARAM)ci->hwndChildMaximized, 0);
690 if (ci->nActiveChildren == 0) return 0;
692 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
693 BWA_SKIPICONIC, &total)))
695 WND** heapPtr = ppWnd;
696 if( total )
698 INT delta = 0, n = 0;
699 POINT pos[2];
700 if( total < ci->nActiveChildren )
701 delta = GetSystemMetrics(SM_CYICONSPACING) +
702 GetSystemMetrics(SM_CYICON);
704 /* walk the list (backwards) and move windows */
705 while (*ppWnd) ppWnd++;
706 while (ppWnd != heapPtr)
708 ppWnd--;
709 TRACE(mdi, "move %04x to (%ld,%ld) size [%ld,%ld]\n",
710 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
712 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
713 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
714 pos[1].x, pos[1].y,
715 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
718 WIN_ReleaseWinArray(heapPtr);
721 if( total < ci->nActiveChildren )
722 ArrangeIconicWindows( clientWnd->hwndSelf );
723 return 0;
726 /**********************************************************************
727 * MDITile
729 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
731 WND** ppWnd;
732 UINT total = 0;
734 if (ci->hwndChildMaximized)
735 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
736 (WPARAM)ci->hwndChildMaximized, 0);
738 if (ci->nActiveChildren == 0) return;
740 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
741 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
743 TRACE(mdi,"%u windows to tile\n", total);
745 if( ppWnd )
747 WND** heapPtr = ppWnd;
749 if( total )
751 RECT rect;
752 int x, y, xsize, ysize;
753 int rows, columns, r, c, i;
755 rect = wndClient->rectClient;
756 rows = (int) sqrt((double)total);
757 columns = total / rows;
759 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
761 i = rows;
762 rows = columns; /* exchange r and c */
763 columns = i;
766 if( total != ci->nActiveChildren)
768 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
769 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
772 ysize = rect.bottom / rows;
773 xsize = rect.right / columns;
775 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
777 if (c == columns)
779 rows = total - i;
780 ysize = rect.bottom / rows;
783 y = 0;
784 for (r = 1; r <= rows && *ppWnd; r++, i++)
786 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
787 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
788 y += ysize;
789 ppWnd++;
791 x += xsize;
794 WIN_ReleaseWinArray(heapPtr);
797 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
800 /* ----------------------- Frame window ---------------------------- */
803 /**********************************************************************
804 * MDI_AugmentFrameMenu
806 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
807 HWND hChild )
809 WND* child = WIN_FindWndPtr(hChild);
810 HMENU hSysPopup = 0;
812 TRACE(mdi,"frame %p,child %04x\n",frame,hChild);
814 if( !frame->wIDmenu || !child->hSysMenu )
816 WIN_ReleaseWndPtr(child);
817 return 0;
819 WIN_ReleaseWndPtr(child);
821 /* create a copy of sysmenu popup and insert it into frame menu bar */
823 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
824 return 0;
826 TRACE(mdi,"\tgot popup %04x in sysmenu %04x\n",
827 hSysPopup, child->hSysMenu);
829 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
830 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
831 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
832 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
834 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
835 hSysPopup, (LPSTR)(DWORD)hBmpClose ))
837 TRACE(mdi,"not inserted\n");
838 DestroyMenu(hSysPopup);
839 return 0;
842 /* The close button is only present in Win 95 look */
843 if(TWEAK_WineLook > WIN31_LOOK)
845 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
846 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
849 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
850 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
851 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
852 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
854 /* redraw menu */
855 DrawMenuBar(frame->hwndSelf);
857 return 1;
860 /**********************************************************************
861 * MDI_RestoreFrameMenu
863 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
865 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
866 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
868 TRACE(mdi,"frameWnd %p,child %04x\n",frameWnd,hChild);
870 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
871 return 0;
873 /* app button */
874 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
876 if(TWEAK_WineLook > WIN31_LOOK)
878 /* close */
879 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
881 /* restore */
882 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
883 /* minimize */
884 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
886 DrawMenuBar(frameWnd->hwndSelf);
888 return 1;
892 /**********************************************************************
893 * MDI_UpdateFrameText
895 * used when child window is maximized/restored
897 * Note: lpTitle can be NULL
899 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
900 BOOL repaint, LPCSTR lpTitle )
902 char lpBuffer[MDI_MAXTITLELENGTH+1];
903 WND* clientWnd = WIN_FindWndPtr(hClient);
904 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
906 TRACE(mdi, "repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
908 if (!clientWnd)
909 return;
911 if (!ci)
913 WIN_ReleaseWndPtr(clientWnd);
914 return;
917 /* store new "default" title if lpTitle is not NULL */
918 if (lpTitle)
920 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
921 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
924 if (ci->frameTitle)
926 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
928 if( childWnd && childWnd->text )
930 /* combine frame title and child title if possible */
932 LPCSTR lpBracket = " - [";
933 int i_frame_text_length = strlen(ci->frameTitle);
934 int i_child_text_length = strlen(childWnd->text);
936 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
938 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
940 strcat( lpBuffer, lpBracket );
942 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
944 strcat( lpBuffer, childWnd->text );
945 strcat( lpBuffer, "]" );
947 else
949 lstrcpynA( lpBuffer + i_frame_text_length + 4,
950 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
951 strcat( lpBuffer, "]" );
955 else
957 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
958 lpBuffer[MDI_MAXTITLELENGTH]='\0';
960 WIN_ReleaseWndPtr(childWnd);
963 else
964 lpBuffer[0] = '\0';
966 DEFWND_SetText( frameWnd, lpBuffer );
967 if( repaint == MDI_REPAINTFRAME)
968 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
969 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
971 WIN_ReleaseWndPtr(clientWnd);
976 /* ----------------------------- Interface ---------------------------- */
979 /**********************************************************************
980 * MDIClientWndProc
982 * This function handles all MDI requests.
984 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
985 LPARAM lParam )
987 LPCREATESTRUCTA cs;
988 MDICLIENTINFO *ci;
989 RECT rect;
990 WND *w = WIN_FindWndPtr(hwnd);
991 WND *frameWnd = WIN_LockWndPtr(w->parent);
992 INT nItems;
993 LRESULT retvalue;
995 ci = (MDICLIENTINFO *) w->wExtra;
997 switch (message)
999 case WM_CREATE:
1001 cs = (LPCREATESTRUCTA)lParam;
1003 /* Translation layer doesn't know what's in the cs->lpCreateParams
1004 * so we have to keep track of what environment we're in. */
1006 if( w->flags & WIN_ISWIN32 )
1008 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1009 ci->hWindowMenu = ccs->hWindowMenu;
1010 ci->idFirstChild = ccs->idFirstChild;
1011 #undef ccs
1013 else
1015 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1016 PTR_SEG_TO_LIN(cs->lpCreateParams);
1017 ci->hWindowMenu = ccs->hWindowMenu;
1018 ci->idFirstChild = ccs->idFirstChild;
1021 ci->hwndChildMaximized = 0;
1022 ci->nActiveChildren = 0;
1023 ci->nTotalCreated = 0;
1024 ci->frameTitle = NULL;
1025 ci->mdiFlags = 0;
1026 ci->self = hwnd;
1027 w->dwStyle |= WS_CLIPCHILDREN;
1029 if (!hBmpClose)
1031 hBmpClose = CreateMDIMenuBitmap();
1032 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1034 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1036 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1038 GetClientRect(frameWnd->hwndSelf, &rect);
1039 NC_HandleNCCalcSize( w, &rect );
1040 w->rectClient = rect;
1042 TRACE(mdi,"Client created - hwnd = %04x, idFirst = %u\n",
1043 hwnd, ci->idFirstChild );
1045 retvalue = 0;
1046 goto END;
1048 case WM_DESTROY:
1049 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1050 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1052 ci->idFirstChild = nItems - 1;
1053 ci->nActiveChildren++; /* to delete a separator */
1054 while( ci->nActiveChildren-- )
1055 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1057 retvalue = 0;
1058 goto END;
1060 case WM_MDIACTIVATE:
1061 if( ci->hwndActiveChild != (HWND)wParam )
1062 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1063 retvalue = 0;
1064 goto END;
1066 case WM_MDICASCADE:
1067 retvalue = MDICascade(w, ci);
1068 goto END;
1070 case WM_MDICREATE:
1071 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1072 (MDICREATESTRUCTA*)lParam );
1073 else retvalue = 0;
1074 goto END;
1076 case WM_MDIDESTROY:
1077 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1078 goto END;
1080 case WM_MDIGETACTIVE:
1081 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1082 retvalue = ci->hwndActiveChild;
1083 goto END;
1085 case WM_MDIICONARRANGE:
1086 ci->mdiFlags |= MDIF_NEEDUPDATE;
1087 ArrangeIconicWindows(hwnd);
1088 ci->sbRecalc = SB_BOTH+1;
1089 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1090 retvalue = 0;
1091 goto END;
1093 case WM_MDIMAXIMIZE:
1094 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1095 retvalue = 0;
1096 goto END;
1098 case WM_MDINEXT: /* lParam != 0 means previous window */
1099 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1100 break;
1102 case WM_MDIRESTORE:
1103 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1104 retvalue = 0;
1105 goto END;
1107 case WM_MDISETMENU:
1108 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1109 goto END;
1110 case WM_MDIREFRESHMENU:
1111 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1112 goto END;
1114 case WM_MDITILE:
1115 ci->mdiFlags |= MDIF_NEEDUPDATE;
1116 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1117 MDITile(w, ci, wParam);
1118 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1119 retvalue = 0;
1120 goto END;
1122 case WM_VSCROLL:
1123 case WM_HSCROLL:
1124 ci->mdiFlags |= MDIF_NEEDUPDATE;
1125 ScrollChildren(hwnd, message, wParam, lParam);
1126 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1127 retvalue = 0;
1128 goto END;
1130 case WM_SETFOCUS:
1131 if( ci->hwndActiveChild )
1133 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1134 if( !(pw->dwStyle & WS_MINIMIZE) )
1135 SetFocus( ci->hwndActiveChild );
1136 WIN_ReleaseWndPtr(pw);
1138 retvalue = 0;
1139 goto END;
1141 case WM_NCACTIVATE:
1142 if( ci->hwndActiveChild )
1143 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1144 break;
1146 case WM_PARENTNOTIFY:
1147 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1149 POINT16 pt = MAKEPOINT16(lParam);
1150 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1152 TRACE(mdi,"notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1154 if( child && child != hwnd && child != ci->hwndActiveChild )
1155 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1157 retvalue = 0;
1158 goto END;
1160 case WM_SIZE:
1161 if( IsWindow(ci->hwndChildMaximized) )
1163 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1164 RECT rect;
1166 rect.left = 0;
1167 rect.top = 0;
1168 rect.right = LOWORD(lParam);
1169 rect.bottom = HIWORD(lParam);
1171 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1172 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1173 rect.right - rect.left, rect.bottom - rect.top, 1);
1174 WIN_ReleaseWndPtr(child);
1176 else
1177 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1179 break;
1181 case WM_MDICALCCHILDSCROLL:
1182 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1184 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1185 ci->sbRecalc = 0;
1186 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1188 retvalue = 0;
1189 goto END;
1192 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1193 END:
1194 WIN_ReleaseWndPtr(w);
1195 WIN_ReleaseWndPtr(frameWnd);
1196 return retvalue;
1200 /***********************************************************************
1201 * DefFrameProc16 (USER.445)
1203 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1204 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1206 HWND16 childHwnd;
1207 MDICLIENTINFO* ci;
1208 WND* wndPtr;
1210 if (hwndMDIClient)
1212 switch (message)
1214 case WM_COMMAND:
1215 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1217 if (!wndPtr) {
1218 ERR(mdi,"null wndPtr for mdi window hwndMDIClient=%04x\n",
1219 hwndMDIClient);
1220 return 0;
1223 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1225 /* check for possible syscommands for maximized MDI child */
1226 WIN_ReleaseWndPtr(wndPtr);
1228 if( ci && (
1229 wParam < ci->idFirstChild ||
1230 wParam >= ci->idFirstChild + ci->nActiveChildren
1232 if( (wParam - 0xF000) & 0xF00F ) break;
1233 switch( wParam )
1235 case SC_SIZE:
1236 case SC_MOVE:
1237 case SC_MINIMIZE:
1238 case SC_MAXIMIZE:
1239 case SC_NEXTWINDOW:
1240 case SC_PREVWINDOW:
1241 case SC_CLOSE:
1242 case SC_RESTORE:
1243 if( ci->hwndChildMaximized )
1244 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1245 wParam, lParam);
1248 else
1250 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1251 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1252 WIN_ReleaseWndPtr(wndPtr);
1254 if( childHwnd )
1255 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1256 (WPARAM16)childHwnd , 0L);
1258 break;
1260 case WM_NCACTIVATE:
1261 SendMessage16(hwndMDIClient, message, wParam, lParam);
1262 break;
1264 case WM_SETTEXT:
1265 wndPtr = WIN_FindWndPtr(hwnd);
1266 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1267 MDI_REPAINTFRAME,
1268 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1269 WIN_ReleaseWndPtr(wndPtr);
1270 return 0;
1272 case WM_SETFOCUS:
1273 SetFocus(hwndMDIClient);
1274 break;
1276 case WM_SIZE:
1277 MoveWindow16(hwndMDIClient, 0, 0,
1278 LOWORD(lParam), HIWORD(lParam), TRUE);
1279 break;
1281 case WM_NEXTMENU:
1283 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1284 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1286 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1287 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1289 /* control menu is between the frame system menu and
1290 * the first entry of menu bar */
1292 if( (wParam == VK_LEFT &&
1293 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1294 (wParam == VK_RIGHT &&
1295 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1297 LRESULT retvalue;
1298 WIN_ReleaseWndPtr(wndPtr);
1299 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1300 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1301 ci->hwndActiveChild);
1302 WIN_ReleaseWndPtr(wndPtr);
1303 return retvalue;
1306 WIN_ReleaseWndPtr(wndPtr);
1307 break;
1311 return DefWindowProc16(hwnd, message, wParam, lParam);
1315 /***********************************************************************
1316 * DefFrameProc32A (USER32.122)
1318 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1319 UINT message, WPARAM wParam, LPARAM lParam)
1321 if (hwndMDIClient)
1323 switch (message)
1325 case WM_COMMAND:
1326 return DefFrameProc16( hwnd, hwndMDIClient, message,
1327 (WPARAM16)wParam,
1328 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1330 case WM_NCACTIVATE:
1331 SendMessageA(hwndMDIClient, message, wParam, lParam);
1332 break;
1334 case WM_SETTEXT: {
1335 LRESULT ret;
1336 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1338 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1339 wParam, (LPARAM)SEGPTR_GET(segstr) );
1340 SEGPTR_FREE(segstr);
1341 return ret;
1344 case WM_NEXTMENU:
1345 case WM_SETFOCUS:
1346 case WM_SIZE:
1347 return DefFrameProc16( hwnd, hwndMDIClient, message,
1348 wParam, lParam );
1352 return DefWindowProcA(hwnd, message, wParam, lParam);
1356 /***********************************************************************
1357 * DefFrameProc32W (USER32.123)
1359 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1360 UINT message, WPARAM wParam, LPARAM lParam)
1362 if (hwndMDIClient)
1364 switch (message)
1366 case WM_COMMAND:
1367 return DefFrameProc16( hwnd, hwndMDIClient, message,
1368 (WPARAM16)wParam,
1369 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1371 case WM_NCACTIVATE:
1372 SendMessageW(hwndMDIClient, message, wParam, lParam);
1373 break;
1375 case WM_SETTEXT:
1377 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1378 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1379 wParam, (DWORD)txt );
1380 HeapFree(GetProcessHeap(),0,txt);
1381 return ret;
1383 case WM_NEXTMENU:
1384 case WM_SETFOCUS:
1385 case WM_SIZE:
1386 return DefFrameProcA( hwnd, hwndMDIClient, message,
1387 wParam, lParam );
1391 return DefWindowProcW( hwnd, message, wParam, lParam );
1395 /***********************************************************************
1396 * DefMDIChildProc16 (USER.447)
1398 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1399 WPARAM16 wParam, LPARAM lParam )
1401 MDICLIENTINFO *ci;
1402 WND *clientWnd,*tmpWnd = 0;
1403 LRESULT retvalue;
1405 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1406 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1408 switch (message)
1410 case WM_SETTEXT:
1411 DefWindowProc16(hwnd, message, wParam, lParam);
1412 MDI_MenuModifyItem(clientWnd,hwnd);
1413 if( ci->hwndChildMaximized == hwnd )
1414 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1415 MDI_REPAINTFRAME, NULL );
1416 retvalue = 0;
1417 goto END;
1419 case WM_CLOSE:
1420 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1421 retvalue = 0;
1422 goto END;
1424 case WM_SETFOCUS:
1425 if( ci->hwndActiveChild != hwnd )
1426 MDI_ChildActivate(clientWnd, hwnd);
1427 break;
1429 case WM_CHILDACTIVATE:
1430 MDI_ChildActivate(clientWnd, hwnd);
1431 retvalue = 0;
1432 goto END;
1434 case WM_NCPAINT:
1435 TRACE(mdi,"WM_NCPAINT for %04x, active %04x\n",
1436 hwnd, ci->hwndActiveChild );
1437 break;
1439 case WM_SYSCOMMAND:
1440 switch( wParam )
1442 case SC_MOVE:
1443 if( ci->hwndChildMaximized == hwnd)
1445 retvalue = 0;
1446 goto END;
1448 break;
1449 case SC_RESTORE:
1450 case SC_MINIMIZE:
1451 tmpWnd = WIN_FindWndPtr(hwnd);
1452 tmpWnd->dwStyle |= WS_SYSMENU;
1453 WIN_ReleaseWndPtr(tmpWnd);
1454 break;
1455 case SC_MAXIMIZE:
1456 if( ci->hwndChildMaximized == hwnd)
1458 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1459 message, wParam, lParam);
1460 goto END;
1462 tmpWnd = WIN_FindWndPtr(hwnd);
1463 tmpWnd->dwStyle &= ~WS_SYSMENU;
1464 WIN_ReleaseWndPtr(tmpWnd);
1465 break;
1466 case SC_NEXTWINDOW:
1467 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1468 retvalue = 0;
1469 goto END;
1470 case SC_PREVWINDOW:
1471 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1472 retvalue = 0;
1473 goto END;
1475 break;
1477 case WM_GETMINMAXINFO:
1478 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1479 retvalue = 0;
1480 goto END;
1482 case WM_SETVISIBLE:
1483 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1484 else
1485 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1486 break;
1488 case WM_SIZE:
1489 /* do not change */
1491 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1493 ci->hwndChildMaximized = 0;
1495 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1496 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1497 MDI_REPAINTFRAME, NULL );
1500 if( wParam == SIZE_MAXIMIZED )
1502 HWND16 hMaxChild = ci->hwndChildMaximized;
1504 if( hMaxChild == hwnd ) break;
1506 if( hMaxChild)
1508 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1510 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1511 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1513 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1516 TRACE(mdi,"maximizing child %04x\n", hwnd );
1518 ci->hwndChildMaximized = hwnd; /* !!! */
1519 ci->hwndActiveChild = hwnd;
1521 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1522 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1523 MDI_REPAINTFRAME, NULL );
1526 if( wParam == SIZE_MINIMIZED )
1528 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1530 if( switchTo )
1531 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1534 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1535 break;
1537 case WM_MENUCHAR:
1539 /* MDI children don't have menu bars */
1540 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1541 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1542 retvalue = 0x00010000L;
1543 goto END;
1545 case WM_NEXTMENU:
1547 if( wParam == VK_LEFT ) /* switch to frame system menu */
1549 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1550 clientWnd->parent->hwndSelf );
1551 goto END;
1553 if( wParam == VK_RIGHT ) /* to frame menu bar */
1555 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1556 clientWnd->parent->hwndSelf );
1557 goto END;
1560 break;
1562 case WM_SYSCHAR:
1563 if (wParam == '-')
1565 SendMessage16(hwnd,WM_SYSCOMMAND,
1566 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1567 retvalue = 0;
1568 goto END;
1572 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1573 END:
1574 WIN_ReleaseWndPtr(clientWnd);
1575 return retvalue;
1579 /***********************************************************************
1580 * DefMDIChildProc32A (USER32.124)
1582 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1583 WPARAM wParam, LPARAM lParam )
1585 MDICLIENTINFO *ci;
1586 WND *clientWnd,*tmpWnd;
1587 LRESULT retvalue;
1589 tmpWnd = WIN_FindWndPtr(hwnd);
1590 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1591 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1592 WIN_ReleaseWndPtr(tmpWnd);
1594 switch (message)
1596 case WM_SETTEXT:
1597 DefWindowProcA(hwnd, message, wParam, lParam);
1598 MDI_MenuModifyItem(clientWnd,hwnd);
1599 if( ci->hwndChildMaximized == hwnd )
1600 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1601 MDI_REPAINTFRAME, NULL );
1602 retvalue = 0;
1603 goto END;
1605 case WM_GETMINMAXINFO:
1607 MINMAXINFO16 mmi;
1608 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1609 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1610 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1612 retvalue = 0;
1613 goto END;
1615 case WM_MENUCHAR:
1617 /* MDI children don't have menu bars */
1618 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1619 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1620 retvalue = 0x00010000L;
1621 goto END;
1623 case WM_CLOSE:
1624 case WM_SETFOCUS:
1625 case WM_CHILDACTIVATE:
1626 case WM_NCPAINT:
1627 case WM_SYSCOMMAND:
1628 case WM_SETVISIBLE:
1629 case WM_SIZE:
1630 case WM_NEXTMENU:
1631 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1632 goto END;
1634 case WM_SYSCHAR:
1635 if (wParam == '-')
1637 SendMessageA(hwnd,WM_SYSCOMMAND,
1638 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1639 retvalue = 0;
1640 goto END;
1643 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1644 END:
1645 WIN_ReleaseWndPtr(clientWnd);
1646 return retvalue;
1650 /***********************************************************************
1651 * DefMDIChildProc32W (USER32.125)
1653 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1654 WPARAM wParam, LPARAM lParam )
1656 MDICLIENTINFO *ci;
1657 WND *clientWnd;
1658 LRESULT retvalue;
1660 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1661 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1663 switch (message)
1665 case WM_SETTEXT:
1666 DefWindowProcW(hwnd, message, wParam, lParam);
1667 MDI_MenuModifyItem(clientWnd,hwnd);
1668 if( ci->hwndChildMaximized == hwnd )
1669 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1670 MDI_REPAINTFRAME, NULL );
1671 retvalue = 0;
1672 goto END;
1674 case WM_GETMINMAXINFO:
1675 case WM_MENUCHAR:
1676 case WM_CLOSE:
1677 case WM_SETFOCUS:
1678 case WM_CHILDACTIVATE:
1679 case WM_NCPAINT:
1680 case WM_SYSCOMMAND:
1681 case WM_SETVISIBLE:
1682 case WM_SIZE:
1683 case WM_NEXTMENU:
1684 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1685 goto END;
1687 case WM_SYSCHAR:
1688 if (wParam == '-')
1690 SendMessageW(hwnd,WM_SYSCOMMAND,
1691 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1692 retvalue = 0;
1693 goto END;
1696 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1697 END:
1698 WIN_ReleaseWndPtr(clientWnd);
1699 return retvalue;
1704 /**********************************************************************
1705 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1706 * FIXME: its in the same thread now
1708 * RETURNS
1709 * Success: Handle to created window
1710 * Failure: NULL
1712 HWND WINAPI CreateMDIWindowA(
1713 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1714 LPCSTR lpWindowName, /* [in] Pointer to window name */
1715 DWORD dwStyle, /* [in] Window style */
1716 INT X, /* [in] Horizontal position of window */
1717 INT Y, /* [in] Vertical position of window */
1718 INT nWidth, /* [in] Width of window */
1719 INT nHeight, /* [in] Height of window */
1720 HWND hWndParent, /* [in] Handle to parent window */
1721 HINSTANCE hInstance, /* [in] Handle to application instance */
1722 LPARAM lParam) /* [in] Application-defined value */
1724 WARN(mdi,"is only single threaded!\n");
1725 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1726 nWidth, nHeight, hWndParent, hInstance, lParam);
1729 /**********************************************************************
1730 * MDI_CreateMDIWindowA
1731 * single threaded version of CreateMDIWindowA
1732 * called by CreateWindowEx32A
1734 HWND MDI_CreateMDIWindowA(
1735 LPCSTR lpClassName,
1736 LPCSTR lpWindowName,
1737 DWORD dwStyle,
1738 INT X,
1739 INT Y,
1740 INT nWidth,
1741 INT nHeight,
1742 HWND hWndParent,
1743 HINSTANCE hInstance,
1744 LPARAM lParam)
1746 MDICLIENTINFO* pCi;
1747 MDICREATESTRUCTA cs;
1748 WND *pWnd=WIN_FindWndPtr(hWndParent);
1749 HWND retvalue;
1751 TRACE(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1752 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1753 nWidth,nHeight,hWndParent,hInstance,lParam);
1755 if(!pWnd){
1756 ERR(mdi," bad hwnd for MDI-client: %d\n",hWndParent);
1757 return 0;
1759 cs.szClass=lpClassName;
1760 cs.szTitle=lpWindowName;
1761 cs.hOwner=hInstance;
1762 cs.x=X;
1763 cs.y=Y;
1764 cs.cx=nWidth;
1765 cs.cy=nHeight;
1766 cs.style=dwStyle;
1767 cs.lParam=lParam;
1769 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1771 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1772 WIN_ReleaseWndPtr(pWnd);
1773 return retvalue;
1776 /***************************************
1777 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1779 * RETURNS
1780 * Success: Handle to created window
1781 * Failure: NULL
1783 HWND WINAPI CreateMDIWindowW(
1784 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1785 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1786 DWORD dwStyle, /* [in] Window style */
1787 INT X, /* [in] Horizontal position of window */
1788 INT Y, /* [in] Vertical position of window */
1789 INT nWidth, /* [in] Width of window */
1790 INT nHeight, /* [in] Height of window */
1791 HWND hWndParent, /* [in] Handle to parent window */
1792 HINSTANCE hInstance, /* [in] Handle to application instance */
1793 LPARAM lParam) /* [in] Application-defined value */
1795 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1796 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1797 nWidth,nHeight,hWndParent,hInstance,lParam);
1798 return (HWND)NULL;
1802 /******************************************************************************
1803 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1804 * single threaded version of CreateMDIWindow
1805 * called by CreateWindowEx32W().
1807 HWND MDI_CreateMDIWindowW(
1808 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1809 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1810 DWORD dwStyle, /* [in] Window style */
1811 INT X, /* [in] Horizontal position of window */
1812 INT Y, /* [in] Vertical position of window */
1813 INT nWidth, /* [in] Width of window */
1814 INT nHeight, /* [in] Height of window */
1815 HWND hWndParent, /* [in] Handle to parent window */
1816 HINSTANCE hInstance, /* [in] Handle to application instance */
1817 LPARAM lParam) /* [in] Application-defined value */
1819 FIXME(mdi, "(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1820 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1821 nWidth,nHeight,hWndParent,hInstance,lParam);
1822 return (HWND)NULL;
1826 /**********************************************************************
1827 * TranslateMDISysAccel32 (USER32.555)
1829 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1831 MSG16 msg16;
1833 STRUCT32_MSG32to16(msg,&msg16);
1834 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1835 return TranslateMDISysAccel16(hwndClient,&msg16);
1839 /**********************************************************************
1840 * TranslateMDISysAccel16 (USER.451)
1842 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1845 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1847 MDICLIENTINFO *ci = NULL;
1848 HWND wnd;
1849 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1851 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1852 wnd = ci->hwndActiveChild;
1854 WIN_ReleaseWndPtr(clientWnd);
1856 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1858 WPARAM16 wParam = 0;
1860 /* translate if the Ctrl key is down and Alt not. */
1862 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1863 !(GetKeyState(VK_MENU) & 0x8000))
1865 switch( msg->wParam )
1867 case VK_F6:
1868 case VK_TAB:
1869 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1870 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1871 break;
1872 case VK_F4:
1873 case VK_RBUTTON:
1874 wParam = SC_CLOSE;
1875 break;
1876 default:
1877 return 0;
1879 TRACE(mdi,"wParam = %04x\n", wParam);
1880 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1881 wParam, (LPARAM)msg->wParam);
1882 return 1;
1886 return 0; /* failure */
1890 /***********************************************************************
1891 * CalcChildScroll (USER.462)
1893 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1895 SCROLLINFO info;
1896 RECT childRect, clientRect;
1897 INT vmin, vmax, hmin, hmax, vpos, hpos;
1898 WND *pWnd, *Wnd;
1900 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1901 Wnd = WIN_FindWndPtr(hwnd);
1902 GetClientRect( hwnd, &clientRect );
1903 SetRectEmpty( &childRect );
1905 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1907 if( pWnd->dwStyle & WS_MAXIMIZE )
1909 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1910 WIN_ReleaseWndPtr(pWnd);
1911 WIN_ReleaseWndPtr(Wnd);
1912 return;
1914 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1916 WIN_ReleaseWndPtr(pWnd);
1917 UnionRect( &childRect, &clientRect, &childRect );
1919 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1920 hpos = clientRect.left - childRect.left;
1921 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1922 vpos = clientRect.top - childRect.top;
1924 switch( scroll )
1926 case SB_HORZ:
1927 vpos = hpos; vmin = hmin; vmax = hmax;
1928 case SB_VERT:
1929 info.cbSize = sizeof(info);
1930 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1931 info.fMask = SIF_POS | SIF_RANGE;
1932 SetScrollInfo(hwnd, scroll, &info, TRUE);
1933 break;
1934 case SB_BOTH:
1935 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1936 hmin, hmax, hpos);
1938 WIN_ReleaseWndPtr(Wnd);
1942 /***********************************************************************
1943 * ScrollChildren16 (USER.463)
1945 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
1947 ScrollChildren( hWnd, uMsg, wParam, lParam );
1951 /***********************************************************************
1952 * ScrollChildren32 (USER32.448)
1954 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
1955 LPARAM lParam)
1957 WND *wndPtr = WIN_FindWndPtr(hWnd);
1958 INT newPos = -1;
1959 INT curPos, length, minPos, maxPos, shift;
1961 if( !wndPtr ) return;
1963 if( uMsg == WM_HSCROLL )
1965 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1966 curPos = GetScrollPos(hWnd,SB_HORZ);
1967 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
1968 shift = GetSystemMetrics(SM_CYHSCROLL);
1970 else if( uMsg == WM_VSCROLL )
1972 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1973 curPos = GetScrollPos(hWnd,SB_VERT);
1974 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
1975 shift = GetSystemMetrics(SM_CXVSCROLL);
1977 else
1979 WIN_ReleaseWndPtr(wndPtr);
1980 return;
1983 WIN_ReleaseWndPtr(wndPtr);
1984 switch( wParam )
1986 case SB_LINEUP:
1987 newPos = curPos - shift;
1988 break;
1989 case SB_LINEDOWN:
1990 newPos = curPos + shift;
1991 break;
1992 case SB_PAGEUP:
1993 newPos = curPos - length;
1994 break;
1995 case SB_PAGEDOWN:
1996 newPos = curPos + length;
1997 break;
1999 case SB_THUMBPOSITION:
2000 newPos = LOWORD(lParam);
2001 break;
2003 case SB_THUMBTRACK:
2004 return;
2006 case SB_TOP:
2007 newPos = minPos;
2008 break;
2009 case SB_BOTTOM:
2010 newPos = maxPos;
2011 break;
2012 case SB_ENDSCROLL:
2013 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2014 return;
2017 if( newPos > maxPos )
2018 newPos = maxPos;
2019 else
2020 if( newPos < minPos )
2021 newPos = minPos;
2023 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2025 if( uMsg == WM_VSCROLL )
2026 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2027 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2028 else
2029 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2030 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2034 /******************************************************************************
2035 * CascadeWindows [USER32.21] Cascades MDI child windows
2037 * RETURNS
2038 * Success: Number of cascaded windows.
2039 * Failure: 0
2041 WORD WINAPI
2042 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2043 UINT cKids, const HWND *lpKids)
2045 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2046 hwndParent, wFlags, cKids);
2048 return 0;
2052 /******************************************************************************
2053 * TileWindows [USER32.545] Tiles MDI child windows
2055 * RETURNS
2056 * Success: Number of tiled windows.
2057 * Failure: 0
2059 WORD WINAPI
2060 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2061 UINT cKids, const HWND *lpKids)
2063 FIXME (mdi, "(0x%08x,0x%08x,...,%u,...): stub\n",
2064 hwndParent, wFlags, cKids);
2066 return 0;