Created separate dlls for user,gdi,ttydrv,x11drv.
[wine/dcerpc.git] / windows / mdi.c
blob40489764e898c6d25282ab27dffcb6b2a23d9c97
1 /* MDI.C
3 * Copyright 1994, Bob Amstadt
4 * 1995,1996 Alex Korobka
6 * This file contains routines to support MDI (Multiple Document
7 * Interface) features .
9 * Notes: Fairly complete implementation. Any volunteers for
10 * "More windows..." stuff?
12 * Also, Excel and WinWord do _not_ use MDI so if you're trying
13 * to fix them look elsewhere.
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <math.h>
20 #include "windef.h"
21 #include "wingdi.h"
22 #include "winuser.h"
23 #include "win.h"
24 #include "heap.h"
25 #include "nonclient.h"
26 #include "mdi.h"
27 #include "user.h"
28 #include "menu.h"
29 #include "scroll.h"
30 #include "struct32.h"
31 #include "tweak.h"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(mdi);
36 #define MDIF_NEEDUPDATE 0x0001
38 static HBITMAP16 hBmpClose = 0;
39 static HBITMAP16 hBmpRestore = 0;
41 /* ----------------- declarations ----------------- */
42 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
43 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
44 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
46 static LONG MDI_ChildActivate( WND*, HWND );
48 /* -------- Miscellaneous service functions ----------
50 * MDI_GetChildByID
53 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
55 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
56 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
57 return 0;
60 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
62 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
64 ci->mdiFlags |= MDIF_NEEDUPDATE;
65 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
67 ci->sbRecalc = recalc;
70 /**********************************************************************
71 * MDI_MenuModifyItem
73 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
75 char buffer[128];
76 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
77 WND *wndPtr = WIN_FindWndPtr(hWndChild);
78 UINT n = sprintf(buffer, "%d ",
79 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
80 BOOL bRet = 0;
82 if( !clientInfo->hWindowMenu )
84 bRet = FALSE;
85 goto END;
88 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
90 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
91 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
92 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
93 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
94 END:
95 WIN_ReleaseWndPtr(wndPtr);
96 return bRet;
99 /**********************************************************************
100 * MDI_MenuDeleteItem
102 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
104 char buffer[128];
105 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
106 WND *wndPtr = WIN_FindWndPtr(hWndChild);
107 UINT index = 0,id,n;
108 BOOL retvalue;
110 if( !clientInfo->nActiveChildren ||
111 !clientInfo->hWindowMenu )
113 retvalue = FALSE;
114 goto END;
117 id = wndPtr->wIDmenu;
118 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
120 /* walk the rest of MDI children to prevent gaps in the id
121 * sequence and in the menu child list */
123 for( index = id+1; index <= clientInfo->nActiveChildren +
124 clientInfo->idFirstChild; index++ )
126 WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
127 if( !tmpWnd )
129 TRACE("no window for id=%i\n",index);
130 WIN_ReleaseWndPtr(tmpWnd);
131 continue;
134 /* set correct id */
135 tmpWnd->wIDmenu--;
137 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
138 if (tmpWnd->text)
139 lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n );
141 /* change menu */
142 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
143 index - 1 , buffer );
144 WIN_ReleaseWndPtr(tmpWnd);
146 retvalue = TRUE;
147 END:
148 WIN_ReleaseWndPtr(wndPtr);
149 return retvalue;
152 /**********************************************************************
153 * MDI_GetWindow
155 * returns "activateable" child different from the current or zero
157 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
158 DWORD dwStyleMask )
160 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
161 WND *wndPtr, *pWnd, *pWndLast = NULL;
163 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
164 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
166 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
168 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
170 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
172 if ( pWnd == wndPtr ) break; /* went full circle */
174 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
176 pWndLast = pWnd;
177 if ( bNext ) break;
180 WIN_ReleaseWndPtr(wndPtr);
181 WIN_ReleaseWndPtr(pWnd);
182 return pWndLast ? pWndLast->hwndSelf : 0;
185 /**********************************************************************
186 * MDI_CalcDefaultChildPos
188 * It seems that the default height is about 2/3 of the client rect
190 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
191 INT delta)
193 INT nstagger;
194 RECT rect = w->rectClient;
195 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
196 GetSystemMetrics(SM_CYFRAME) - 1;
198 if( rect.bottom - rect.top - delta >= spacing )
199 rect.bottom -= delta;
201 nstagger = (rect.bottom - rect.top)/(3 * spacing);
202 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
203 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
204 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
207 /**********************************************************************
208 * MDISetMenu
210 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
211 HMENU hmenuWindow)
213 WND *w;
214 MDICLIENTINFO *ci;
215 HWND hwndFrame = GetParent(hwnd);
216 HMENU oldFrameMenu = GetMenu(hwndFrame);
218 TRACE("%04x %04x %04x\n",
219 hwnd, hmenuFrame, hmenuWindow);
221 if (hmenuFrame && !IsMenu(hmenuFrame))
223 WARN("hmenuFrame is not a menu handle\n");
224 return 0L;
227 if (hmenuWindow && !IsMenu(hmenuWindow))
229 WARN("hmenuWindow is not a menu handle\n");
230 return 0L;
233 w = WIN_FindWndPtr(hwnd);
234 ci = (MDICLIENTINFO *) w->wExtra;
236 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
237 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
239 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
241 /* delete menu items from ci->hWindowMenu
242 * and add them to hmenuWindow */
244 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
245 INT pos = GetMenuItemCount(hmenuWindow) + 1;
247 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
249 if( ci->nActiveChildren )
251 INT j = i - ci->nActiveChildren + 1;
252 char buffer[100];
253 UINT id,state;
255 for( ; i >= j ; i-- )
257 id = GetMenuItemID(ci->hWindowMenu,i );
258 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
260 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
262 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
263 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
264 id, buffer);
265 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
269 /* remove separator */
270 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
272 ci->hWindowMenu = hmenuWindow;
275 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
277 SetMenu(hwndFrame, hmenuFrame);
278 if( ci->hwndChildMaximized )
279 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
280 WIN_ReleaseWndPtr(w);
281 return oldFrameMenu;
283 WIN_ReleaseWndPtr(w);
284 return 0;
287 /**********************************************************************
288 * MDIRefreshMenu
290 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
291 HMENU hmenuWindow)
293 HWND hwndFrame = GetParent(hwnd);
294 HMENU oldFrameMenu = GetMenu(hwndFrame);
296 TRACE("%04x %04x %04x\n",
297 hwnd, hmenuFrame, hmenuWindow);
299 FIXME("partially function stub\n");
301 return oldFrameMenu;
305 /* ------------------ MDI child window functions ---------------------- */
308 /**********************************************************************
309 * MDICreateChild
311 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
312 LPMDICREATESTRUCTA cs )
314 POINT pos[2];
315 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
316 HWND hwnd, hwndMax = 0;
317 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
318 char lpstrDef[]="junk!";
320 TRACE("origin %i,%i - dim %i,%i, style %08x\n",
321 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
322 /* calculate placement */
323 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
325 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
326 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
328 if( cs->x == CW_USEDEFAULT )
330 cs->x = pos[0].x;
331 cs->y = pos[0].y;
334 /* restore current maximized child */
335 if( style & WS_VISIBLE && ci->hwndChildMaximized )
337 if( style & WS_MAXIMIZE )
338 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
339 hwndMax = ci->hwndChildMaximized;
340 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
341 if( style & WS_MAXIMIZE )
342 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
345 /* this menu is needed to set a check mark in MDI_ChildActivate */
346 if (ci->hWindowMenu != 0)
347 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
349 ci->nActiveChildren++;
351 /* fix window style */
352 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
354 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
355 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
356 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
359 if( w->flags & WIN_ISWIN32 )
361 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
362 cs->x, cs->y, cs->cx, cs->cy, parent,
363 (HMENU16)wIDmenu, cs->hOwner, cs );
365 else
367 MDICREATESTRUCT16 *cs16;
368 LPSTR title, cls;
370 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
371 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
372 title = SEGPTR_STRDUP( cs->szTitle );
373 cls = SEGPTR_STRDUP( cs->szClass );
374 cs16->szTitle = SEGPTR_GET(title);
375 cs16->szClass = SEGPTR_GET(cls);
377 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
378 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
379 (HMENU)wIDmenu, cs16->hOwner,
380 (LPVOID)SEGPTR_GET(cs16) );
381 SEGPTR_FREE( title );
382 SEGPTR_FREE( cls );
383 SEGPTR_FREE( cs16 );
386 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
388 if (hwnd)
390 WND* wnd = WIN_FindWndPtr( hwnd );
392 /* All MDI child windows have the WS_EX_MDICHILD style */
393 wnd->dwExStyle |= WS_EX_MDICHILD;
395 MDI_MenuModifyItem(w ,hwnd);
396 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
397 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
398 else
400 /* WS_VISIBLE is clear if a) the MDI client has
401 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
402 * MDICreateStruct. If so the created window is not shown nor
403 * activated.
405 int showflag=wnd->dwStyle & WS_VISIBLE;
406 /* clear visible flag, otherwise SetWindoPos32 ignores
407 * the SWP_SHOWWINDOW command.
409 wnd->dwStyle &= ~WS_VISIBLE;
410 if(showflag){
411 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
413 /* Set maximized state here in case hwnd didn't receive WM_SIZE
414 * during CreateWindow - bad!
417 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
419 ci->hwndChildMaximized = wnd->hwndSelf;
420 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
421 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
423 }else
424 /* needed, harmless ? */
425 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
428 WIN_ReleaseWndPtr(wnd);
429 TRACE("created child - %04x\n",hwnd);
431 else
433 ci->nActiveChildren--;
434 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
435 if( IsWindow(hwndMax) )
436 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
439 return hwnd;
442 /**********************************************************************
443 * MDI_ChildGetMinMaxInfo
445 * Note: The rule here is that client rect of the maximized MDI child
446 * is equal to the client rect of the MDI client window.
448 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
449 MINMAXINFO16* lpMinMax )
451 WND* childWnd = WIN_FindWndPtr(hwnd);
452 RECT rect = clientWnd->rectClient;
454 MapWindowPoints( clientWnd->parent->hwndSelf,
455 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
456 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
458 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
459 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
461 lpMinMax->ptMaxPosition.x = rect.left;
462 lpMinMax->ptMaxPosition.y = rect.top;
464 WIN_ReleaseWndPtr(childWnd);
466 TRACE("max rect (%i,%i - %i, %i)\n",
467 rect.left,rect.top,rect.right,rect.bottom);
471 /**********************************************************************
472 * MDI_SwitchActiveChild
474 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
475 * being activated
477 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
478 BOOL bNextWindow )
480 WND *w = WIN_FindWndPtr(clientHwnd);
481 HWND hwndTo = 0;
482 HWND hwndPrev = 0;
483 MDICLIENTINFO *ci;
485 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
487 ci = (MDICLIENTINFO *) w->wExtra;
489 TRACE("from %04x, to %04x\n",childHwnd,hwndTo);
491 if ( !hwndTo ) goto END; /* no window to switch to */
493 hwndPrev = ci->hwndActiveChild;
495 if ( hwndTo != hwndPrev )
497 BOOL bOptimize = 0;
499 if( ci->hwndChildMaximized )
501 bOptimize = 1;
502 w->dwStyle &= ~WS_VISIBLE;
505 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
506 SWP_NOMOVE | SWP_NOSIZE );
508 if( bNextWindow && hwndPrev )
509 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
510 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
511 if( bOptimize )
512 ShowWindow( clientHwnd, SW_SHOW );
514 END:
515 WIN_ReleaseWndPtr(w);
519 /**********************************************************************
520 * MDIDestroyChild
522 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
523 HWND parent, HWND child,
524 BOOL flagDestroy )
526 WND *childPtr = WIN_FindWndPtr(child);
528 if( childPtr )
530 if( child == ci->hwndActiveChild )
532 MDI_SwitchActiveChild(parent, child, TRUE);
534 if( child == ci->hwndActiveChild )
536 ShowWindow( child, SW_HIDE);
537 if( child == ci->hwndChildMaximized )
539 MDI_RestoreFrameMenu(w_parent->parent, child);
540 ci->hwndChildMaximized = 0;
541 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
544 MDI_ChildActivate(w_parent, 0);
547 MDI_MenuDeleteItem(w_parent, child);
549 WIN_ReleaseWndPtr(childPtr);
551 ci->nActiveChildren--;
553 TRACE("child destroyed - %04x\n",child);
555 if (flagDestroy)
557 MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
558 DestroyWindow(child);
562 return 0;
566 /**********************************************************************
567 * MDI_ChildActivate
569 * Note: hWndChild is NULL when last child is being destroyed
571 static LONG MDI_ChildActivate( WND *clientPtr, HWND hWndChild )
573 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
574 HWND prevActiveWnd = clientInfo->hwndActiveChild;
575 WND *wndPtr = WIN_FindWndPtr( hWndChild );
576 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
577 BOOL isActiveFrameWnd = 0;
578 LONG retvalue;
580 if( wndPtr )
582 if( wndPtr->dwStyle & WS_DISABLED )
584 retvalue = 0L;
585 goto END;
589 /* Don't activate if it is already active. Might happen
590 since ShowWindow DOES activate MDI children */
591 if (clientInfo->hwndActiveChild == hWndChild)
593 retvalue = 0L;
594 goto END;
597 TRACE("%04x\n", hWndChild);
599 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
600 isActiveFrameWnd = TRUE;
602 /* deactivate prev. active child */
603 if( wndPrev )
605 wndPrev->dwStyle |= WS_SYSMENU;
606 SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
607 SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
608 (LPARAM)hWndChild);
609 /* uncheck menu item */
610 if( clientInfo->hWindowMenu )
611 CheckMenuItem( clientInfo->hWindowMenu,
612 wndPrev->wIDmenu, 0);
615 /* set appearance */
616 if( clientInfo->hwndChildMaximized )
618 if( clientInfo->hwndChildMaximized != hWndChild ) {
619 if( hWndChild ) {
620 clientInfo->hwndActiveChild = hWndChild;
621 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
622 } else
623 ShowWindow( clientInfo->hwndActiveChild, SW_SHOWNORMAL );
627 clientInfo->hwndActiveChild = hWndChild;
629 /* check if we have any children left */
630 if( !hWndChild )
632 if( isActiveFrameWnd )
633 SetFocus( clientInfo->self );
634 retvalue = 0;
635 goto END;
638 /* check menu item */
639 if( clientInfo->hWindowMenu )
640 CheckMenuItem( clientInfo->hWindowMenu,
641 wndPtr->wIDmenu, MF_CHECKED);
643 /* bring active child to the top */
644 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
646 if( isActiveFrameWnd )
648 SendMessageA( hWndChild, WM_NCACTIVATE, TRUE, 0L);
649 if( GetFocus() == clientInfo->self )
650 SendMessageA( clientInfo->self, WM_SETFOCUS,
651 (WPARAM)clientInfo->self, 0L );
652 else
653 SetFocus( clientInfo->self );
655 SendMessageA( hWndChild, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
656 (LPARAM)hWndChild );
657 retvalue = 1;
658 END:
659 WIN_ReleaseWndPtr(wndPtr);
660 WIN_ReleaseWndPtr(wndPrev);
661 return retvalue;
664 /* -------------------- MDI client window functions ------------------- */
666 /**********************************************************************
667 * CreateMDIMenuBitmap
669 static HBITMAP16 CreateMDIMenuBitmap(void)
671 HDC hDCSrc = CreateCompatibleDC(0);
672 HDC hDCDest = CreateCompatibleDC(hDCSrc);
673 HBITMAP16 hbClose = LoadBitmap16(0, MAKEINTRESOURCE16(OBM_CLOSE) );
674 HBITMAP16 hbCopy;
675 HANDLE16 hobjSrc, hobjDest;
677 hobjSrc = SelectObject(hDCSrc, hbClose);
678 hbCopy = CreateCompatibleBitmap(hDCSrc,GetSystemMetrics(SM_CXSIZE),GetSystemMetrics(SM_CYSIZE));
679 hobjDest = SelectObject(hDCDest, hbCopy);
681 BitBlt(hDCDest, 0, 0, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
682 hDCSrc, GetSystemMetrics(SM_CXSIZE), 0, SRCCOPY);
684 SelectObject(hDCSrc, hobjSrc);
685 DeleteObject(hbClose);
686 DeleteDC(hDCSrc);
688 hobjSrc = SelectObject( hDCDest, GetStockObject(BLACK_PEN) );
690 MoveToEx( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, 0, NULL );
691 LineTo( hDCDest, GetSystemMetrics(SM_CXSIZE) - 1, GetSystemMetrics(SM_CYSIZE) - 1);
693 SelectObject(hDCDest, hobjSrc );
694 SelectObject(hDCDest, hobjDest);
695 DeleteDC(hDCDest);
697 return hbCopy;
700 /**********************************************************************
701 * MDICascade
703 static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci)
705 WND** ppWnd;
706 UINT total;
708 if (ci->hwndChildMaximized)
709 SendMessageA( clientWnd->hwndSelf, WM_MDIRESTORE,
710 (WPARAM)ci->hwndChildMaximized, 0);
712 if (ci->nActiveChildren == 0) return 0;
714 if ((ppWnd = WIN_BuildWinArray(clientWnd, BWA_SKIPHIDDEN | BWA_SKIPOWNED |
715 BWA_SKIPICONIC, &total)))
717 WND** heapPtr = ppWnd;
718 if( total )
720 INT delta = 0, n = 0;
721 POINT pos[2];
722 if( total < ci->nActiveChildren )
723 delta = GetSystemMetrics(SM_CYICONSPACING) +
724 GetSystemMetrics(SM_CYICON);
726 /* walk the list (backwards) and move windows */
727 while (*ppWnd) ppWnd++;
728 while (ppWnd != heapPtr)
730 ppWnd--;
731 TRACE("move %04x to (%ld,%ld) size [%ld,%ld]\n",
732 (*ppWnd)->hwndSelf, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
734 MDI_CalcDefaultChildPos(clientWnd, n++, pos, delta);
735 SetWindowPos( (*ppWnd)->hwndSelf, 0, pos[0].x, pos[0].y,
736 pos[1].x, pos[1].y,
737 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
740 WIN_ReleaseWinArray(heapPtr);
743 if( total < ci->nActiveChildren )
744 ArrangeIconicWindows( clientWnd->hwndSelf );
745 return 0;
748 /**********************************************************************
749 * MDITile
751 static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam )
753 WND** ppWnd;
754 UINT total = 0;
756 if (ci->hwndChildMaximized)
757 SendMessageA( wndClient->hwndSelf, WM_MDIRESTORE,
758 (WPARAM)ci->hwndChildMaximized, 0);
760 if (ci->nActiveChildren == 0) return;
762 ppWnd = WIN_BuildWinArray(wndClient, BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
763 ((wParam & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
765 TRACE("%u windows to tile\n", total);
767 if( ppWnd )
769 WND** heapPtr = ppWnd;
771 if( total )
773 RECT rect;
774 int x, y, xsize, ysize;
775 int rows, columns, r, c, i;
777 GetClientRect(wndClient->hwndSelf,&rect);
778 rows = (int) sqrt((double)total);
779 columns = total / rows;
781 if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */
783 i = rows;
784 rows = columns; /* exchange r and c */
785 columns = i;
788 if( total != ci->nActiveChildren)
790 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
791 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
794 ysize = rect.bottom / rows;
795 xsize = rect.right / columns;
797 for (x = i = 0, c = 1; c <= columns && *ppWnd; c++)
799 if (c == columns)
801 rows = total - i;
802 ysize = rect.bottom / rows;
805 y = 0;
806 for (r = 1; r <= rows && *ppWnd; r++, i++)
808 SetWindowPos((*ppWnd)->hwndSelf, 0, x, y, xsize, ysize,
809 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
810 y += ysize;
811 ppWnd++;
813 x += xsize;
816 WIN_ReleaseWinArray(heapPtr);
819 if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf );
822 /* ----------------------- Frame window ---------------------------- */
825 /**********************************************************************
826 * MDI_AugmentFrameMenu
828 static BOOL MDI_AugmentFrameMenu( MDICLIENTINFO* ci, WND *frame,
829 HWND hChild )
831 WND* child = WIN_FindWndPtr(hChild);
832 HMENU hSysPopup = 0;
833 HBITMAP hSysMenuBitmap = 0;
835 TRACE("frame %p,child %04x\n",frame,hChild);
837 if( !frame->wIDmenu || !child->hSysMenu )
839 WIN_ReleaseWndPtr(child);
840 return 0;
842 WIN_ReleaseWndPtr(child);
844 /* create a copy of sysmenu popup and insert it into frame menu bar */
846 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
847 return 0;
849 TRACE("\tgot popup %04x in sysmenu %04x\n",
850 hSysPopup, child->hSysMenu);
852 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
853 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
854 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
855 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
857 /* In Win 95 look, the system menu is replaced by the child icon */
859 if(TWEAK_WineLook > WIN31_LOOK)
861 HICON hIcon = GetClassLongA(hChild, GCL_HICONSM);
862 if (!hIcon)
863 hIcon = GetClassLongA(hChild, GCL_HICON);
864 if (hIcon)
866 HDC hMemDC;
867 HBITMAP hBitmap, hOldBitmap;
868 HBRUSH hBrush;
869 HDC hdc = GetDC(hChild);
871 if (hdc)
873 int cx, cy;
874 cx = GetSystemMetrics(SM_CXSMICON);
875 cy = GetSystemMetrics(SM_CYSMICON);
876 hMemDC = CreateCompatibleDC(hdc);
877 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
878 hOldBitmap = SelectObject(hMemDC, hBitmap);
879 SetMapMode(hMemDC, MM_TEXT);
880 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
881 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
882 SelectObject (hMemDC, hOldBitmap);
883 DeleteObject(hBrush);
884 DeleteDC(hMemDC);
885 ReleaseDC(hChild, hdc);
886 hSysMenuBitmap = hBitmap;
890 else
891 hSysMenuBitmap = hBmpClose;
893 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
894 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
896 TRACE("not inserted\n");
897 DestroyMenu(hSysPopup);
898 return 0;
901 /* The close button is only present in Win 95 look */
902 if(TWEAK_WineLook > WIN31_LOOK)
904 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
905 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
908 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
909 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
910 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
911 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
913 /* redraw menu */
914 DrawMenuBar(frame->hwndSelf);
916 return 1;
919 /**********************************************************************
920 * MDI_RestoreFrameMenu
922 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
924 MENUITEMINFOA menuInfo;
925 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
926 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
928 TRACE("frameWnd %p,(%04x),child %04x,nIt=%d,iId=%d\n",
929 frameWnd,frameWnd->hwndSelf,hChild,nItems,iId);
931 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
932 return 0;
935 * Remove the system menu, If that menu is the icon of the window
936 * as it is in win95, we have to delete the bitmap.
938 menuInfo.cbSize = sizeof(MENUITEMINFOA);
939 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
941 GetMenuItemInfoA(frameWnd->wIDmenu,
943 TRUE,
944 &menuInfo);
946 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
948 if ( (menuInfo.fType & MFT_BITMAP) &&
949 (LOWORD(menuInfo.dwTypeData)!=0) &&
950 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
952 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
955 if(TWEAK_WineLook > WIN31_LOOK)
957 /* close */
958 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
960 /* restore */
961 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
962 /* minimize */
963 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
965 DrawMenuBar(frameWnd->hwndSelf);
967 return 1;
971 /**********************************************************************
972 * MDI_UpdateFrameText
974 * used when child window is maximized/restored
976 * Note: lpTitle can be NULL
978 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
979 BOOL repaint, LPCSTR lpTitle )
981 char lpBuffer[MDI_MAXTITLELENGTH+1];
982 WND* clientWnd = WIN_FindWndPtr(hClient);
983 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
985 TRACE("repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
987 if (!clientWnd)
988 return;
990 if (!ci)
992 WIN_ReleaseWndPtr(clientWnd);
993 return;
996 /* store new "default" title if lpTitle is not NULL */
997 if (lpTitle)
999 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
1000 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
1003 if (ci->frameTitle)
1005 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
1007 if( childWnd && childWnd->text )
1009 /* combine frame title and child title if possible */
1011 LPCSTR lpBracket = " - [";
1012 int i_frame_text_length = strlen(ci->frameTitle);
1013 int i_child_text_length = strlen(childWnd->text);
1015 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
1017 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
1019 strcat( lpBuffer, lpBracket );
1021 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
1023 strcat( lpBuffer, childWnd->text );
1024 strcat( lpBuffer, "]" );
1026 else
1028 lstrcpynA( lpBuffer + i_frame_text_length + 4,
1029 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
1030 strcat( lpBuffer, "]" );
1034 else
1036 lstrcpynA(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH+1 );
1038 WIN_ReleaseWndPtr(childWnd);
1041 else
1042 lpBuffer[0] = '\0';
1044 DEFWND_SetText( frameWnd, lpBuffer );
1045 if( repaint == MDI_REPAINTFRAME)
1046 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
1047 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1049 WIN_ReleaseWndPtr(clientWnd);
1054 /* ----------------------------- Interface ---------------------------- */
1057 /**********************************************************************
1058 * MDIClientWndProc
1060 * This function handles all MDI requests.
1062 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
1063 LPARAM lParam )
1065 LPCREATESTRUCTA cs;
1066 MDICLIENTINFO *ci;
1067 RECT rect;
1068 WND *w, *frameWnd;
1069 INT nItems;
1070 LRESULT retvalue;
1072 if ( ( w = WIN_FindWndPtr(hwnd) ) == NULL )
1073 return 0;
1075 if ( ( frameWnd = WIN_LockWndPtr(w->parent) ) == NULL ) {
1076 WIN_ReleaseWndPtr(w);
1077 return 0;
1080 ci = (MDICLIENTINFO *) w->wExtra;
1082 switch (message)
1084 case WM_CREATE:
1086 cs = (LPCREATESTRUCTA)lParam;
1088 /* Translation layer doesn't know what's in the cs->lpCreateParams
1089 * so we have to keep track of what environment we're in. */
1091 if( w->flags & WIN_ISWIN32 )
1093 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1094 ci->hWindowMenu = ccs->hWindowMenu;
1095 ci->idFirstChild = ccs->idFirstChild;
1096 #undef ccs
1098 else
1100 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1101 PTR_SEG_TO_LIN(cs->lpCreateParams);
1102 ci->hWindowMenu = ccs->hWindowMenu;
1103 ci->idFirstChild = ccs->idFirstChild;
1106 ci->hwndChildMaximized = 0;
1107 ci->nActiveChildren = 0;
1108 ci->nTotalCreated = 0;
1109 ci->frameTitle = NULL;
1110 ci->mdiFlags = 0;
1111 ci->self = hwnd;
1112 w->dwStyle |= WS_CLIPCHILDREN;
1114 if (!hBmpClose)
1116 hBmpClose = CreateMDIMenuBitmap();
1117 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1119 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1121 if (ci->hWindowMenu != 0)
1122 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1124 GetClientRect(frameWnd->hwndSelf, &rect);
1125 NC_HandleNCCalcSize( w, &rect );
1126 w->rectClient = rect;
1128 TRACE("Client created - hwnd = %04x, idFirst = %u\n",
1129 hwnd, ci->idFirstChild );
1131 retvalue = 0;
1132 goto END;
1134 case WM_DESTROY:
1135 if( ci->hwndChildMaximized )
1136 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized);
1137 if((ci->hWindowMenu != 0) &&
1138 (nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1140 ci->idFirstChild = nItems - 1;
1141 ci->nActiveChildren++; /* to delete a separator */
1142 while( ci->nActiveChildren-- )
1143 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1145 retvalue = 0;
1146 goto END;
1148 case WM_MDIACTIVATE:
1149 if( ci->hwndActiveChild != (HWND)wParam )
1150 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1151 retvalue = 0;
1152 goto END;
1154 case WM_MDICASCADE:
1155 retvalue = MDICascade(w, ci);
1156 goto END;
1158 case WM_MDICREATE:
1159 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1160 (MDICREATESTRUCTA*)lParam );
1161 else retvalue = 0;
1162 goto END;
1164 case WM_MDIDESTROY:
1165 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1166 goto END;
1168 case WM_MDIGETACTIVE:
1169 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1170 retvalue = ci->hwndActiveChild;
1171 goto END;
1173 case WM_MDIICONARRANGE:
1174 ci->mdiFlags |= MDIF_NEEDUPDATE;
1175 ArrangeIconicWindows(hwnd);
1176 ci->sbRecalc = SB_BOTH+1;
1177 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1178 retvalue = 0;
1179 goto END;
1181 case WM_MDIMAXIMIZE:
1182 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1183 retvalue = 0;
1184 goto END;
1186 case WM_MDINEXT: /* lParam != 0 means previous window */
1187 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1188 break;
1190 case WM_MDIRESTORE:
1191 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1192 retvalue = 0;
1193 goto END;
1195 case WM_MDISETMENU:
1196 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1197 goto END;
1198 case WM_MDIREFRESHMENU:
1199 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1200 goto END;
1202 case WM_MDITILE:
1203 ci->mdiFlags |= MDIF_NEEDUPDATE;
1204 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1205 MDITile(w, ci, wParam);
1206 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1207 retvalue = 0;
1208 goto END;
1210 case WM_VSCROLL:
1211 case WM_HSCROLL:
1212 ci->mdiFlags |= MDIF_NEEDUPDATE;
1213 ScrollChildren(hwnd, message, wParam, lParam);
1214 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1215 retvalue = 0;
1216 goto END;
1218 case WM_SETFOCUS:
1219 if( ci->hwndActiveChild )
1221 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1222 if( !(pw->dwStyle & WS_MINIMIZE) )
1223 SetFocus( ci->hwndActiveChild );
1224 WIN_ReleaseWndPtr(pw);
1226 retvalue = 0;
1227 goto END;
1229 case WM_NCACTIVATE:
1230 if( ci->hwndActiveChild )
1231 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1232 break;
1234 case WM_PARENTNOTIFY:
1235 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1237 POINT16 pt = MAKEPOINT16(lParam);
1238 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1240 TRACE("notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1242 if( child && child != hwnd && child != ci->hwndActiveChild )
1243 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1245 retvalue = 0;
1246 goto END;
1248 case WM_SIZE:
1249 if( IsWindow(ci->hwndChildMaximized) )
1251 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1252 RECT rect;
1254 rect.left = 0;
1255 rect.top = 0;
1256 rect.right = LOWORD(lParam);
1257 rect.bottom = HIWORD(lParam);
1259 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1260 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1261 rect.right - rect.left, rect.bottom - rect.top, 1);
1262 WIN_ReleaseWndPtr(child);
1264 else
1265 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1267 break;
1269 case WM_MDICALCCHILDSCROLL:
1270 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1272 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1273 ci->sbRecalc = 0;
1274 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1276 retvalue = 0;
1277 goto END;
1280 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1281 END:
1282 WIN_ReleaseWndPtr(w);
1283 WIN_ReleaseWndPtr(frameWnd);
1284 return retvalue;
1288 /***********************************************************************
1289 * DefFrameProc16 (USER.445)
1291 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1292 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1294 HWND16 childHwnd;
1295 MDICLIENTINFO* ci;
1296 WND* wndPtr;
1298 if (hwndMDIClient)
1300 switch (message)
1302 case WM_COMMAND:
1303 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1305 if (!wndPtr) {
1306 ERR("null wndPtr for mdi window hwndMDIClient=%04x\n",
1307 hwndMDIClient);
1308 return 0;
1311 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1313 /* check for possible syscommands for maximized MDI child */
1314 WIN_ReleaseWndPtr(wndPtr);
1316 if( ci && (
1317 wParam < ci->idFirstChild ||
1318 wParam >= ci->idFirstChild + ci->nActiveChildren
1320 if( (wParam - 0xF000) & 0xF00F ) break;
1321 switch( wParam )
1323 case SC_SIZE:
1324 case SC_MOVE:
1325 case SC_MINIMIZE:
1326 case SC_MAXIMIZE:
1327 case SC_NEXTWINDOW:
1328 case SC_PREVWINDOW:
1329 case SC_CLOSE:
1330 case SC_RESTORE:
1331 if( ci->hwndChildMaximized )
1332 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1333 wParam, lParam);
1336 else
1338 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1339 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1340 WIN_ReleaseWndPtr(wndPtr);
1342 if( childHwnd )
1343 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1344 (WPARAM16)childHwnd , 0L);
1346 break;
1348 case WM_NCACTIVATE:
1349 SendMessage16(hwndMDIClient, message, wParam, lParam);
1350 break;
1352 case WM_SETTEXT:
1353 wndPtr = WIN_FindWndPtr(hwnd);
1354 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1355 MDI_REPAINTFRAME,
1356 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1357 WIN_ReleaseWndPtr(wndPtr);
1358 return 0;
1360 case WM_SETFOCUS:
1361 SetFocus(hwndMDIClient);
1362 break;
1364 case WM_SIZE:
1365 MoveWindow16(hwndMDIClient, 0, 0,
1366 LOWORD(lParam), HIWORD(lParam), TRUE);
1367 break;
1369 case WM_NEXTMENU:
1371 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1372 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1374 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1375 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1377 /* control menu is between the frame system menu and
1378 * the first entry of menu bar */
1380 if( (wParam == VK_LEFT &&
1381 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1382 (wParam == VK_RIGHT &&
1383 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1385 LRESULT retvalue;
1386 WIN_ReleaseWndPtr(wndPtr);
1387 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1388 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1389 ci->hwndActiveChild);
1390 WIN_ReleaseWndPtr(wndPtr);
1391 return retvalue;
1394 WIN_ReleaseWndPtr(wndPtr);
1395 break;
1399 return DefWindowProc16(hwnd, message, wParam, lParam);
1403 /***********************************************************************
1404 * DefFrameProc32A (USER32.122)
1406 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1407 UINT message, WPARAM wParam, LPARAM lParam)
1409 if (hwndMDIClient)
1411 switch (message)
1413 case WM_COMMAND:
1414 return DefFrameProc16( hwnd, hwndMDIClient, message,
1415 (WPARAM16)wParam,
1416 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1418 case WM_NCACTIVATE:
1419 SendMessageA(hwndMDIClient, message, wParam, lParam);
1420 break;
1422 case WM_SETTEXT: {
1423 LRESULT ret;
1424 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1426 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1427 wParam, (LPARAM)SEGPTR_GET(segstr) );
1428 SEGPTR_FREE(segstr);
1429 return ret;
1432 case WM_NEXTMENU:
1433 case WM_SETFOCUS:
1434 case WM_SIZE:
1435 return DefFrameProc16( hwnd, hwndMDIClient, message,
1436 wParam, lParam );
1440 return DefWindowProcA(hwnd, message, wParam, lParam);
1444 /***********************************************************************
1445 * DefFrameProc32W (USER32.123)
1447 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1448 UINT message, WPARAM wParam, LPARAM lParam)
1450 if (hwndMDIClient)
1452 switch (message)
1454 case WM_COMMAND:
1455 return DefFrameProc16( hwnd, hwndMDIClient, message,
1456 (WPARAM16)wParam,
1457 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1459 case WM_NCACTIVATE:
1460 SendMessageW(hwndMDIClient, message, wParam, lParam);
1461 break;
1463 case WM_SETTEXT:
1465 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1466 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1467 wParam, (DWORD)txt );
1468 HeapFree(GetProcessHeap(),0,txt);
1469 return ret;
1471 case WM_NEXTMENU:
1472 case WM_SETFOCUS:
1473 case WM_SIZE:
1474 return DefFrameProcA( hwnd, hwndMDIClient, message,
1475 wParam, lParam );
1479 return DefWindowProcW( hwnd, message, wParam, lParam );
1483 /***********************************************************************
1484 * DefMDIChildProc16 (USER.447)
1486 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1487 WPARAM16 wParam, LPARAM lParam )
1489 MDICLIENTINFO *ci;
1490 WND *clientWnd,*tmpWnd = 0;
1491 LRESULT retvalue;
1493 tmpWnd = WIN_FindWndPtr(hwnd);
1494 if (!tmpWnd) return 0;
1495 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1496 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1497 WIN_ReleaseWndPtr(tmpWnd);
1499 switch (message)
1501 case WM_SETTEXT:
1502 DefWindowProc16(hwnd, message, wParam, lParam);
1503 MDI_MenuModifyItem(clientWnd,hwnd);
1504 if( ci->hwndChildMaximized == hwnd )
1505 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1506 MDI_REPAINTFRAME, NULL );
1507 retvalue = 0;
1508 goto END;
1510 case WM_CLOSE:
1511 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1512 retvalue = 0;
1513 goto END;
1515 case WM_SETFOCUS:
1516 if( ci->hwndActiveChild != hwnd )
1517 MDI_ChildActivate(clientWnd, hwnd);
1518 break;
1520 case WM_CHILDACTIVATE:
1521 MDI_ChildActivate(clientWnd, hwnd);
1522 retvalue = 0;
1523 goto END;
1525 case WM_NCPAINT:
1526 TRACE("WM_NCPAINT for %04x, active %04x\n",
1527 hwnd, ci->hwndActiveChild );
1528 break;
1530 case WM_SYSCOMMAND:
1531 switch( wParam )
1533 case SC_MOVE:
1534 if( ci->hwndChildMaximized == hwnd)
1536 retvalue = 0;
1537 goto END;
1539 break;
1540 case SC_RESTORE:
1541 case SC_MINIMIZE:
1542 tmpWnd = WIN_FindWndPtr(hwnd);
1543 tmpWnd->dwStyle |= WS_SYSMENU;
1544 WIN_ReleaseWndPtr(tmpWnd);
1545 break;
1546 case SC_MAXIMIZE:
1547 if( ci->hwndChildMaximized == hwnd)
1549 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1550 message, wParam, lParam);
1551 goto END;
1553 tmpWnd = WIN_FindWndPtr(hwnd);
1554 tmpWnd->dwStyle &= ~WS_SYSMENU;
1555 WIN_ReleaseWndPtr(tmpWnd);
1556 break;
1557 case SC_NEXTWINDOW:
1558 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1559 retvalue = 0;
1560 goto END;
1561 case SC_PREVWINDOW:
1562 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1563 retvalue = 0;
1564 goto END;
1566 break;
1568 case WM_GETMINMAXINFO:
1569 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1570 retvalue = 0;
1571 goto END;
1573 case WM_SETVISIBLE:
1574 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1575 else
1576 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1577 break;
1579 case WM_SIZE:
1580 /* do not change */
1582 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1584 ci->hwndChildMaximized = 0;
1586 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1587 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1588 MDI_REPAINTFRAME, NULL );
1591 if( wParam == SIZE_MAXIMIZED )
1593 HWND16 hMaxChild = ci->hwndChildMaximized;
1595 if( hMaxChild == hwnd ) break;
1597 if( hMaxChild)
1599 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1601 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1602 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1604 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1607 TRACE("maximizing child %04x\n", hwnd );
1609 ci->hwndChildMaximized = hwnd; /* !!! */
1610 ci->hwndActiveChild = hwnd;
1612 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1613 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1614 MDI_REPAINTFRAME, NULL );
1617 if( wParam == SIZE_MINIMIZED )
1619 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1621 if( switchTo )
1622 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1625 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1626 break;
1628 case WM_MENUCHAR:
1630 /* MDI children don't have menu bars */
1631 retvalue = 0x00010000L;
1632 goto END;
1634 case WM_NEXTMENU:
1636 if( wParam == VK_LEFT ) /* switch to frame system menu */
1638 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1639 clientWnd->parent->hwndSelf );
1640 goto END;
1642 if( wParam == VK_RIGHT ) /* to frame menu bar */
1644 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1645 clientWnd->parent->hwndSelf );
1646 goto END;
1649 break;
1651 case WM_SYSCHAR:
1652 if (wParam == '-')
1654 SendMessage16(hwnd,WM_SYSCOMMAND,
1655 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1656 retvalue = 0;
1657 goto END;
1661 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1662 END:
1663 WIN_ReleaseWndPtr(clientWnd);
1664 return retvalue;
1668 /***********************************************************************
1669 * DefMDIChildProc32A (USER32.124)
1671 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1672 WPARAM wParam, LPARAM lParam )
1674 MDICLIENTINFO *ci;
1675 WND *clientWnd,*tmpWnd;
1676 LRESULT retvalue;
1678 tmpWnd = WIN_FindWndPtr(hwnd);
1679 if (!tmpWnd) return 0;
1680 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1681 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1682 WIN_ReleaseWndPtr(tmpWnd);
1684 switch (message)
1686 case WM_SETTEXT:
1687 DefWindowProcA(hwnd, message, wParam, lParam);
1688 MDI_MenuModifyItem(clientWnd,hwnd);
1689 if( ci->hwndChildMaximized == hwnd )
1690 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1691 MDI_REPAINTFRAME, NULL );
1692 retvalue = 0;
1693 goto END;
1695 case WM_GETMINMAXINFO:
1697 MINMAXINFO16 mmi;
1698 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1699 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1700 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1702 retvalue = 0;
1703 goto END;
1705 case WM_MENUCHAR:
1707 /* MDI children don't have menu bars */
1708 retvalue = 0x00010000L;
1709 goto END;
1711 case WM_CLOSE:
1712 case WM_SETFOCUS:
1713 case WM_CHILDACTIVATE:
1714 case WM_NCPAINT:
1715 case WM_SYSCOMMAND:
1716 case WM_SETVISIBLE:
1717 case WM_SIZE:
1718 case WM_NEXTMENU:
1719 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1720 goto END;
1722 case WM_SYSCHAR:
1723 if (wParam == '-')
1725 SendMessageA(hwnd,WM_SYSCOMMAND,
1726 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1727 retvalue = 0;
1728 goto END;
1731 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1732 END:
1733 WIN_ReleaseWndPtr(clientWnd);
1734 return retvalue;
1738 /***********************************************************************
1739 * DefMDIChildProc32W (USER32.125)
1741 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1742 WPARAM wParam, LPARAM lParam )
1744 MDICLIENTINFO *ci;
1745 WND *clientWnd,*tmpWnd;
1746 LRESULT retvalue;
1748 tmpWnd = WIN_FindWndPtr(hwnd);
1749 if (!tmpWnd) return 0;
1750 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1751 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1752 WIN_ReleaseWndPtr(tmpWnd);
1754 switch (message)
1756 case WM_SETTEXT:
1757 DefWindowProcW(hwnd, message, wParam, lParam);
1758 MDI_MenuModifyItem(clientWnd,hwnd);
1759 if( ci->hwndChildMaximized == hwnd )
1760 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1761 MDI_REPAINTFRAME, NULL );
1762 retvalue = 0;
1763 goto END;
1765 case WM_GETMINMAXINFO:
1766 case WM_MENUCHAR:
1767 case WM_CLOSE:
1768 case WM_SETFOCUS:
1769 case WM_CHILDACTIVATE:
1770 case WM_NCPAINT:
1771 case WM_SYSCOMMAND:
1772 case WM_SETVISIBLE:
1773 case WM_SIZE:
1774 case WM_NEXTMENU:
1775 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1776 goto END;
1778 case WM_SYSCHAR:
1779 if (wParam == '-')
1781 SendMessageW(hwnd,WM_SYSCOMMAND,
1782 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1783 retvalue = 0;
1784 goto END;
1787 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1788 END:
1789 WIN_ReleaseWndPtr(clientWnd);
1790 return retvalue;
1795 /**********************************************************************
1796 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1797 * FIXME: its in the same thread now
1799 * RETURNS
1800 * Success: Handle to created window
1801 * Failure: NULL
1803 HWND WINAPI CreateMDIWindowA(
1804 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1805 LPCSTR lpWindowName, /* [in] Pointer to window name */
1806 DWORD dwStyle, /* [in] Window style */
1807 INT X, /* [in] Horizontal position of window */
1808 INT Y, /* [in] Vertical position of window */
1809 INT nWidth, /* [in] Width of window */
1810 INT nHeight, /* [in] Height of window */
1811 HWND hWndParent, /* [in] Handle to parent window */
1812 HINSTANCE hInstance, /* [in] Handle to application instance */
1813 LPARAM lParam) /* [in] Application-defined value */
1815 WARN("is only single threaded!\n");
1816 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1817 nWidth, nHeight, hWndParent, hInstance, lParam);
1820 /**********************************************************************
1821 * MDI_CreateMDIWindowA
1822 * single threaded version of CreateMDIWindowA
1823 * called by CreateWindowEx32A
1825 HWND MDI_CreateMDIWindowA(
1826 LPCSTR lpClassName,
1827 LPCSTR lpWindowName,
1828 DWORD dwStyle,
1829 INT X,
1830 INT Y,
1831 INT nWidth,
1832 INT nHeight,
1833 HWND hWndParent,
1834 HINSTANCE hInstance,
1835 LPARAM lParam)
1837 MDICLIENTINFO* pCi;
1838 MDICREATESTRUCTA cs;
1839 WND *pWnd=WIN_FindWndPtr(hWndParent);
1840 HWND retvalue;
1842 TRACE("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1843 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1844 nWidth,nHeight,hWndParent,hInstance,lParam);
1846 if(!pWnd){
1847 ERR(" bad hwnd for MDI-client: %d\n",hWndParent);
1848 return 0;
1850 cs.szClass=lpClassName;
1851 cs.szTitle=lpWindowName;
1852 cs.hOwner=hInstance;
1853 cs.x=X;
1854 cs.y=Y;
1855 cs.cx=nWidth;
1856 cs.cy=nHeight;
1857 cs.style=dwStyle;
1858 cs.lParam=lParam;
1860 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1862 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1863 WIN_ReleaseWndPtr(pWnd);
1864 return retvalue;
1867 /***************************************
1868 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1870 * RETURNS
1871 * Success: Handle to created window
1872 * Failure: NULL
1874 HWND WINAPI CreateMDIWindowW(
1875 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1876 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1877 DWORD dwStyle, /* [in] Window style */
1878 INT X, /* [in] Horizontal position of window */
1879 INT Y, /* [in] Vertical position of window */
1880 INT nWidth, /* [in] Width of window */
1881 INT nHeight, /* [in] Height of window */
1882 HWND hWndParent, /* [in] Handle to parent window */
1883 HINSTANCE hInstance, /* [in] Handle to application instance */
1884 LPARAM lParam) /* [in] Application-defined value */
1886 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1887 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1888 nWidth,nHeight,hWndParent,hInstance,lParam);
1889 return (HWND)NULL;
1893 /******************************************************************************
1894 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1895 * single threaded version of CreateMDIWindow
1896 * called by CreateWindowEx32W().
1898 HWND MDI_CreateMDIWindowW(
1899 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1900 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1901 DWORD dwStyle, /* [in] Window style */
1902 INT X, /* [in] Horizontal position of window */
1903 INT Y, /* [in] Vertical position of window */
1904 INT nWidth, /* [in] Width of window */
1905 INT nHeight, /* [in] Height of window */
1906 HWND hWndParent, /* [in] Handle to parent window */
1907 HINSTANCE hInstance, /* [in] Handle to application instance */
1908 LPARAM lParam) /* [in] Application-defined value */
1910 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1911 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1912 nWidth,nHeight,hWndParent,hInstance,lParam);
1913 return (HWND)NULL;
1917 /**********************************************************************
1918 * TranslateMDISysAccel32 (USER32.555)
1920 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1922 MSG16 msg16;
1924 STRUCT32_MSG32to16(msg,&msg16);
1925 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1926 return TranslateMDISysAccel16(hwndClient,&msg16);
1930 /**********************************************************************
1931 * TranslateMDISysAccel16 (USER.451)
1933 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1936 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1938 MDICLIENTINFO *ci = NULL;
1939 HWND wnd;
1940 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1942 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1943 wnd = ci->hwndActiveChild;
1945 WIN_ReleaseWndPtr(clientWnd);
1947 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1949 WPARAM16 wParam = 0;
1951 /* translate if the Ctrl key is down and Alt not. */
1953 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1954 !(GetKeyState(VK_MENU) & 0x8000))
1956 switch( msg->wParam )
1958 case VK_F6:
1959 case VK_TAB:
1960 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1961 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1962 break;
1963 case VK_F4:
1964 case VK_RBUTTON:
1965 wParam = SC_CLOSE;
1966 break;
1967 default:
1968 return 0;
1970 TRACE("wParam = %04x\n", wParam);
1971 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1972 wParam, (LPARAM)msg->wParam);
1973 return 1;
1977 return 0; /* failure */
1981 /***********************************************************************
1982 * CalcChildScroll (USER.462)
1984 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1986 SCROLLINFO info;
1987 RECT childRect, clientRect;
1988 INT vmin, vmax, hmin, hmax, vpos, hpos;
1989 WND *pWnd, *Wnd;
1991 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1992 Wnd = WIN_FindWndPtr(hwnd);
1993 GetClientRect( hwnd, &clientRect );
1994 SetRectEmpty( &childRect );
1996 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1998 if( pWnd->dwStyle & WS_MAXIMIZE )
2000 ShowScrollBar(hwnd, SB_BOTH, FALSE);
2001 WIN_ReleaseWndPtr(pWnd);
2002 WIN_ReleaseWndPtr(Wnd);
2003 return;
2005 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
2007 WIN_ReleaseWndPtr(pWnd);
2008 UnionRect( &childRect, &clientRect, &childRect );
2010 hmin = childRect.left; hmax = childRect.right - clientRect.right;
2011 hpos = clientRect.left - childRect.left;
2012 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
2013 vpos = clientRect.top - childRect.top;
2015 switch( scroll )
2017 case SB_HORZ:
2018 vpos = hpos; vmin = hmin; vmax = hmax;
2019 case SB_VERT:
2020 info.cbSize = sizeof(info);
2021 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
2022 info.fMask = SIF_POS | SIF_RANGE;
2023 SetScrollInfo(hwnd, scroll, &info, TRUE);
2024 break;
2025 case SB_BOTH:
2026 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
2027 hmin, hmax, hpos);
2029 WIN_ReleaseWndPtr(Wnd);
2033 /***********************************************************************
2034 * ScrollChildren16 (USER.463)
2036 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
2038 ScrollChildren( hWnd, uMsg, wParam, lParam );
2042 /***********************************************************************
2043 * ScrollChildren32 (USER32.448)
2045 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
2046 LPARAM lParam)
2048 WND *wndPtr = WIN_FindWndPtr(hWnd);
2049 INT newPos = -1;
2050 INT curPos, length, minPos, maxPos, shift;
2052 if( !wndPtr ) return;
2054 if( uMsg == WM_HSCROLL )
2056 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
2057 curPos = GetScrollPos(hWnd,SB_HORZ);
2058 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
2059 shift = GetSystemMetrics(SM_CYHSCROLL);
2061 else if( uMsg == WM_VSCROLL )
2063 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
2064 curPos = GetScrollPos(hWnd,SB_VERT);
2065 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
2066 shift = GetSystemMetrics(SM_CXVSCROLL);
2068 else
2070 WIN_ReleaseWndPtr(wndPtr);
2071 return;
2074 WIN_ReleaseWndPtr(wndPtr);
2075 switch( wParam )
2077 case SB_LINEUP:
2078 newPos = curPos - shift;
2079 break;
2080 case SB_LINEDOWN:
2081 newPos = curPos + shift;
2082 break;
2083 case SB_PAGEUP:
2084 newPos = curPos - length;
2085 break;
2086 case SB_PAGEDOWN:
2087 newPos = curPos + length;
2088 break;
2090 case SB_THUMBPOSITION:
2091 newPos = LOWORD(lParam);
2092 break;
2094 case SB_THUMBTRACK:
2095 return;
2097 case SB_TOP:
2098 newPos = minPos;
2099 break;
2100 case SB_BOTTOM:
2101 newPos = maxPos;
2102 break;
2103 case SB_ENDSCROLL:
2104 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2105 return;
2108 if( newPos > maxPos )
2109 newPos = maxPos;
2110 else
2111 if( newPos < minPos )
2112 newPos = minPos;
2114 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2116 if( uMsg == WM_VSCROLL )
2117 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2118 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2119 else
2120 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2121 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2125 /******************************************************************************
2126 * CascadeWindows [USER32.21] Cascades MDI child windows
2128 * RETURNS
2129 * Success: Number of cascaded windows.
2130 * Failure: 0
2132 WORD WINAPI
2133 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2134 UINT cKids, const HWND *lpKids)
2136 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2137 hwndParent, wFlags, cKids);
2139 return 0;
2143 /******************************************************************************
2144 * TileWindows [USER32.545] Tiles MDI child windows
2146 * RETURNS
2147 * Success: Number of tiled windows.
2148 * Failure: 0
2150 WORD WINAPI
2151 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2152 UINT cKids, const HWND *lpKids)
2154 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2155 hwndParent, wFlags, cKids);
2157 return 0;