MDIDestroyChild: MDI window menu item was deleted only if the current
[wine/dcerpc.git] / windows / mdi.c
blob0ece27328b5a1715bb2920233744f007ea7c6477
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 "scroll.h"
27 #include "struct32.h"
28 #include "tweak.h"
29 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(mdi)
33 #define MDIF_NEEDUPDATE 0x0001
35 static HBITMAP16 hBmpClose = 0;
36 static HBITMAP16 hBmpRestore = 0;
38 /* ----------------- declarations ----------------- */
39 static void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
40 static BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
41 static BOOL MDI_RestoreFrameMenu(WND *, HWND);
43 static LONG MDI_ChildActivate( WND*, HWND );
45 /* -------- Miscellaneous service functions ----------
47 * MDI_GetChildByID
50 static HWND MDI_GetChildByID(WND* wndPtr, INT id)
52 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
53 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
54 return 0;
57 static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
59 if( !(ci->mdiFlags & MDIF_NEEDUPDATE) )
61 ci->mdiFlags |= MDIF_NEEDUPDATE;
62 PostMessageA( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
64 ci->sbRecalc = recalc;
67 /**********************************************************************
68 * MDI_MenuModifyItem
70 static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
72 char buffer[128];
73 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
74 WND *wndPtr = WIN_FindWndPtr(hWndChild);
75 UINT n = sprintf(buffer, "%d ",
76 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
77 BOOL bRet = 0;
79 if( !clientInfo->hWindowMenu )
81 bRet = FALSE;
82 goto END;
85 if (wndPtr->text) lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n );
87 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
88 bRet = ModifyMenuA(clientInfo->hWindowMenu , wndPtr->wIDmenu,
89 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
90 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
91 END:
92 WIN_ReleaseWndPtr(wndPtr);
93 return bRet;
96 /**********************************************************************
97 * MDI_MenuDeleteItem
99 static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
101 char buffer[128];
102 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
103 WND *wndPtr = WIN_FindWndPtr(hWndChild);
104 UINT index = 0,id,n;
105 BOOL retvalue;
107 if( !clientInfo->nActiveChildren ||
108 !clientInfo->hWindowMenu )
110 retvalue = FALSE;
111 goto END;
114 id = wndPtr->wIDmenu;
115 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
117 /* walk the rest of MDI children to prevent gaps in the id
118 * sequence and in the menu child list */
120 for( index = id+1; index <= clientInfo->nActiveChildren +
121 clientInfo->idFirstChild; index++ )
123 WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
124 if( !tmpWnd )
126 TRACE("no window for id=%i\n",index);
127 WIN_ReleaseWndPtr(tmpWnd);
128 continue;
131 /* set correct id */
132 tmpWnd->wIDmenu--;
134 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
135 if (tmpWnd->text)
136 lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n );
138 /* change menu */
139 ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
140 index - 1 , buffer );
141 WIN_ReleaseWndPtr(tmpWnd);
143 retvalue = TRUE;
144 END:
145 WIN_ReleaseWndPtr(wndPtr);
146 return retvalue;
149 /**********************************************************************
150 * MDI_GetWindow
152 * returns "activateable" child different from the current or zero
154 static HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, BOOL bNext,
155 DWORD dwStyleMask )
157 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
158 WND *wndPtr, *pWnd, *pWndLast = NULL;
160 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
161 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
163 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
165 for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
167 if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
169 if ( pWnd == wndPtr ) break; /* went full circle */
171 if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
173 pWndLast = pWnd;
174 if ( bNext ) break;
177 WIN_ReleaseWndPtr(wndPtr);
178 WIN_ReleaseWndPtr(pWnd);
179 return pWndLast ? pWndLast->hwndSelf : 0;
182 /**********************************************************************
183 * MDI_CalcDefaultChildPos
185 * It seems that the default height is about 2/3 of the client rect
187 static void MDI_CalcDefaultChildPos( WND* w, WORD n, LPPOINT lpPos,
188 INT delta)
190 INT nstagger;
191 RECT rect = w->rectClient;
192 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
193 GetSystemMetrics(SM_CYFRAME) - 1;
195 if( rect.bottom - rect.top - delta >= spacing )
196 rect.bottom -= delta;
198 nstagger = (rect.bottom - rect.top)/(3 * spacing);
199 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
200 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
201 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
204 /**********************************************************************
205 * MDISetMenu
207 static LRESULT MDISetMenu( HWND hwnd, HMENU hmenuFrame,
208 HMENU hmenuWindow)
210 WND *w = WIN_FindWndPtr(hwnd);
211 MDICLIENTINFO *ci;
212 HWND hwndFrame = GetParent(hwnd);
213 HMENU oldFrameMenu = GetMenu(hwndFrame);
215 TRACE("%04x %04x %04x\n",
216 hwnd, hmenuFrame, hmenuWindow);
218 ci = (MDICLIENTINFO *) w->wExtra;
220 if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
221 MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
223 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
225 /* delete menu items from ci->hWindowMenu
226 * and add them to hmenuWindow */
228 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
229 INT pos = GetMenuItemCount(hmenuWindow) + 1;
231 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
233 if( ci->nActiveChildren )
235 INT j = i - ci->nActiveChildren + 1;
236 char buffer[100];
237 UINT id,state;
239 for( ; i >= j ; i-- )
241 id = GetMenuItemID(ci->hWindowMenu,i );
242 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
244 GetMenuStringA(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
246 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
247 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
248 id, buffer);
249 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
253 /* remove separator */
254 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
256 ci->hWindowMenu = hmenuWindow;
259 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
261 SetMenu(hwndFrame, hmenuFrame);
262 if( ci->hwndChildMaximized )
263 MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
264 WIN_ReleaseWndPtr(w);
265 return oldFrameMenu;
267 WIN_ReleaseWndPtr(w);
268 return 0;
271 /**********************************************************************
272 * MDIRefreshMenu
274 static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
275 HMENU hmenuWindow)
277 HWND hwndFrame = GetParent(hwnd);
278 HMENU oldFrameMenu = GetMenu(hwndFrame);
280 TRACE("%04x %04x %04x\n",
281 hwnd, hmenuFrame, hmenuWindow);
283 FIXME("partially function stub\n");
285 return oldFrameMenu;
289 /* ------------------ MDI child window functions ---------------------- */
292 /**********************************************************************
293 * MDICreateChild
295 static HWND MDICreateChild( WND *w, MDICLIENTINFO *ci, HWND parent,
296 LPMDICREATESTRUCTA cs )
298 POINT pos[2];
299 DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
300 HWND hwnd, hwndMax = 0;
301 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
302 char lpstrDef[]="junk!";
304 TRACE("origin %i,%i - dim %i,%i, style %08x\n",
305 cs->x, cs->y, cs->cx, cs->cy, (unsigned)cs->style);
306 /* calculate placement */
307 MDI_CalcDefaultChildPos(w, ci->nTotalCreated++, pos, 0);
309 if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x;
310 if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y;
312 if( cs->x == CW_USEDEFAULT )
314 cs->x = pos[0].x;
315 cs->y = pos[0].y;
318 /* restore current maximized child */
319 if( style & WS_VISIBLE && ci->hwndChildMaximized )
321 if( style & WS_MAXIMIZE )
322 SendMessageA(w->hwndSelf, WM_SETREDRAW, FALSE, 0L );
323 hwndMax = ci->hwndChildMaximized;
324 ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
325 if( style & WS_MAXIMIZE )
326 SendMessageA(w->hwndSelf, WM_SETREDRAW, TRUE, 0L );
329 /* this menu is needed to set a check mark in MDI_ChildActivate */
330 AppendMenuA(ci->hWindowMenu ,MF_STRING ,wIDmenu, lpstrDef );
332 ci->nActiveChildren++;
334 /* fix window style */
335 if( !(w->dwStyle & MDIS_ALLCHILDSTYLES) )
337 style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
338 WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
339 style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
342 if( w->flags & WIN_ISWIN32 )
344 hwnd = CreateWindowA( cs->szClass, cs->szTitle, style,
345 cs->x, cs->y, cs->cx, cs->cy, parent,
346 (HMENU16)wIDmenu, cs->hOwner, cs );
348 else
350 MDICREATESTRUCT16 *cs16;
351 LPSTR title, cls;
353 cs16 = SEGPTR_NEW(MDICREATESTRUCT16);
354 STRUCT32_MDICREATESTRUCT32Ato16( cs, cs16 );
355 title = SEGPTR_STRDUP( cs->szTitle );
356 cls = SEGPTR_STRDUP( cs->szClass );
357 cs16->szTitle = SEGPTR_GET(title);
358 cs16->szClass = SEGPTR_GET(cls);
360 hwnd = CreateWindow16( cs->szClass, cs->szTitle, style,
361 cs16->x, cs16->y, cs16->cx, cs16->cy, parent,
362 (HMENU)wIDmenu, cs16->hOwner,
363 (LPVOID)SEGPTR_GET(cs16) );
364 SEGPTR_FREE( title );
365 SEGPTR_FREE( cls );
366 SEGPTR_FREE( cs16 );
369 /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
371 if (hwnd)
373 WND* wnd = WIN_FindWndPtr( hwnd );
375 MDI_MenuModifyItem(w ,hwnd);
376 if( wnd->dwStyle & WS_MINIMIZE && ci->hwndActiveChild )
377 ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
378 else
380 /* WS_VISIBLE is clear if a) the MDI client has
381 * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
382 * MDICreateStruct. If so the created window is not shown nor
383 * activated.
385 int showflag=wnd->dwStyle & WS_VISIBLE;
386 /* clear visible flag, otherwise SetWindoPos32 ignores
387 * the SWP_SHOWWINDOW command.
389 wnd->dwStyle &= ~WS_VISIBLE;
390 if(showflag){
391 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE );
393 /* Set maximized state here in case hwnd didn't receive WM_SIZE
394 * during CreateWindow - bad!
397 if((wnd->dwStyle & WS_MAXIMIZE) && !ci->hwndChildMaximized )
399 ci->hwndChildMaximized = wnd->hwndSelf;
400 MDI_AugmentFrameMenu( ci, w->parent, hwnd );
401 MDI_UpdateFrameText( w->parent, ci->self, MDI_REPAINTFRAME, NULL );
403 }else
404 /* needed, harmless ? */
405 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
408 WIN_ReleaseWndPtr(wnd);
409 TRACE("created child - %04x\n",hwnd);
411 else
413 ci->nActiveChildren--;
414 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
415 if( IsWindow(hwndMax) )
416 ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
419 return hwnd;
422 /**********************************************************************
423 * MDI_ChildGetMinMaxInfo
425 * Note: The rule here is that client rect of the maximized MDI child
426 * is equal to the client rect of the MDI client window.
428 static void MDI_ChildGetMinMaxInfo( WND* clientWnd, HWND hwnd,
429 MINMAXINFO16* lpMinMax )
431 WND* childWnd = WIN_FindWndPtr(hwnd);
432 RECT rect = clientWnd->rectClient;
434 MapWindowPoints( clientWnd->parent->hwndSelf,
435 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
436 AdjustWindowRectEx( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
438 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
439 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
441 lpMinMax->ptMaxPosition.x = rect.left;
442 lpMinMax->ptMaxPosition.y = rect.top;
444 WIN_ReleaseWndPtr(childWnd);
446 TRACE("max rect (%i,%i - %i, %i)\n",
447 rect.left,rect.top,rect.right,rect.bottom);
451 /**********************************************************************
452 * MDI_SwitchActiveChild
454 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
455 * being activated
457 static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd,
458 BOOL bNextWindow )
460 WND *w = WIN_FindWndPtr(clientHwnd);
461 HWND hwndTo = 0;
462 HWND hwndPrev = 0;
463 MDICLIENTINFO *ci;
465 hwndTo = MDI_GetWindow(w, childHwnd, bNextWindow, 0);
467 ci = (MDICLIENTINFO *) w->wExtra;
469 TRACE("from %04x, to %04x\n",childHwnd,hwndTo);
471 if ( !hwndTo ) goto END; /* no window to switch to */
473 hwndPrev = ci->hwndActiveChild;
475 if ( hwndTo != hwndPrev )
477 BOOL bOptimize = 0;
479 if( ci->hwndChildMaximized )
481 bOptimize = 1;
482 w->dwStyle &= ~WS_VISIBLE;
485 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
486 SWP_NOMOVE | SWP_NOSIZE );
488 if( bNextWindow && hwndPrev )
489 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
490 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
491 if( bOptimize )
492 ShowWindow( clientHwnd, SW_SHOW );
494 END:
495 WIN_ReleaseWndPtr(w);
499 /**********************************************************************
500 * MDIDestroyChild
502 static LRESULT MDIDestroyChild( WND *w_parent, MDICLIENTINFO *ci,
503 HWND parent, HWND child,
504 BOOL flagDestroy )
506 WND *childPtr = WIN_FindWndPtr(child);
508 if( childPtr )
510 if( child == ci->hwndActiveChild )
512 MDI_SwitchActiveChild(parent, child, TRUE);
514 if( child == ci->hwndActiveChild )
516 ShowWindow( child, SW_HIDE);
517 if( child == ci->hwndChildMaximized )
519 MDI_RestoreFrameMenu(w_parent->parent, child);
520 ci->hwndChildMaximized = 0;
521 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
524 MDI_ChildActivate(w_parent, 0);
527 MDI_MenuDeleteItem(w_parent, child);
529 WIN_ReleaseWndPtr(childPtr);
531 ci->nActiveChildren--;
533 TRACE("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("%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("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("%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 GetClientRect(wndClient->hwndSelf,&rect);
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;
811 HBITMAP hSysMenuBitmap = 0;
813 TRACE("frame %p,child %04x\n",frame,hChild);
815 if( !frame->wIDmenu || !child->hSysMenu )
817 WIN_ReleaseWndPtr(child);
818 return 0;
820 WIN_ReleaseWndPtr(child);
822 /* create a copy of sysmenu popup and insert it into frame menu bar */
824 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
825 return 0;
827 TRACE("\tgot popup %04x in sysmenu %04x\n",
828 hSysPopup, child->hSysMenu);
830 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
831 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
832 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
833 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
835 /* In Win 95 look, the system menu is replaced by the child icon */
837 if(TWEAK_WineLook > WIN31_LOOK)
839 HICON hIcon = GetClassLongA(hChild, GCL_HICONSM);
840 if (!hIcon)
841 hIcon = GetClassLongA(hChild, GCL_HICON);
842 if (hIcon)
844 HDC hMemDC;
845 HBITMAP hBitmap, hOldBitmap;
846 HBRUSH hBrush;
847 HDC hdc = GetDC(hChild);
849 if (hdc)
851 int cx, cy;
852 cx = GetSystemMetrics(SM_CXSMICON);
853 cy = GetSystemMetrics(SM_CYSMICON);
854 hMemDC = CreateCompatibleDC(hdc);
855 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
856 hOldBitmap = SelectObject(hMemDC, hBitmap);
857 SetMapMode(hMemDC, MM_TEXT);
858 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
859 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
860 SelectObject (hMemDC, hOldBitmap);
861 DeleteObject(hBrush);
862 DeleteDC(hMemDC);
863 ReleaseDC(hChild, hdc);
864 hSysMenuBitmap = hBitmap;
868 else
869 hSysMenuBitmap = hBmpClose;
871 if( !InsertMenuA(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
872 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
874 TRACE("not inserted\n");
875 DestroyMenu(hSysPopup);
876 return 0;
879 /* The close button is only present in Win 95 look */
880 if(TWEAK_WineLook > WIN31_LOOK)
882 AppendMenuA(frame->wIDmenu,MF_HELP | MF_BITMAP,
883 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
886 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
887 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
888 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
889 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
891 /* redraw menu */
892 DrawMenuBar(frame->hwndSelf);
894 return 1;
897 /**********************************************************************
898 * MDI_RestoreFrameMenu
900 static BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild )
902 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
903 UINT iId = GetMenuItemID(frameWnd->wIDmenu,nItems) ;
905 TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
907 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
908 return 0;
910 /* app button */
911 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
913 if(TWEAK_WineLook > WIN31_LOOK)
915 /* close */
916 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
918 /* restore */
919 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
920 /* minimize */
921 DeleteMenu(frameWnd->wIDmenu,GetMenuItemCount(frameWnd->wIDmenu) - 1,MF_BYPOSITION);
923 DrawMenuBar(frameWnd->hwndSelf);
925 return 1;
929 /**********************************************************************
930 * MDI_UpdateFrameText
932 * used when child window is maximized/restored
934 * Note: lpTitle can be NULL
936 static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient,
937 BOOL repaint, LPCSTR lpTitle )
939 char lpBuffer[MDI_MAXTITLELENGTH+1];
940 WND* clientWnd = WIN_FindWndPtr(hClient);
941 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
943 TRACE("repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
945 if (!clientWnd)
946 return;
948 if (!ci)
950 WIN_ReleaseWndPtr(clientWnd);
951 return;
954 /* store new "default" title if lpTitle is not NULL */
955 if (lpTitle)
957 if (ci->frameTitle) HeapFree( SystemHeap, 0, ci->frameTitle );
958 ci->frameTitle = HEAP_strdupA( SystemHeap, 0, lpTitle );
961 if (ci->frameTitle)
963 WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );
965 if( childWnd && childWnd->text )
967 /* combine frame title and child title if possible */
969 LPCSTR lpBracket = " - [";
970 int i_frame_text_length = strlen(ci->frameTitle);
971 int i_child_text_length = strlen(childWnd->text);
973 lstrcpynA( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
975 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
977 strcat( lpBuffer, lpBracket );
979 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
981 strcat( lpBuffer, childWnd->text );
982 strcat( lpBuffer, "]" );
984 else
986 lstrcpynA( lpBuffer + i_frame_text_length + 4,
987 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
988 strcat( lpBuffer, "]" );
992 else
994 strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH );
995 lpBuffer[MDI_MAXTITLELENGTH]='\0';
997 WIN_ReleaseWndPtr(childWnd);
1000 else
1001 lpBuffer[0] = '\0';
1003 DEFWND_SetText( frameWnd, lpBuffer );
1004 if( repaint == MDI_REPAINTFRAME)
1005 SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
1006 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1008 WIN_ReleaseWndPtr(clientWnd);
1013 /* ----------------------------- Interface ---------------------------- */
1016 /**********************************************************************
1017 * MDIClientWndProc
1019 * This function handles all MDI requests.
1021 LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
1022 LPARAM lParam )
1024 LPCREATESTRUCTA cs;
1025 MDICLIENTINFO *ci;
1026 RECT rect;
1027 WND *w = WIN_FindWndPtr(hwnd);
1028 WND *frameWnd = WIN_LockWndPtr(w->parent);
1029 INT nItems;
1030 LRESULT retvalue;
1032 ci = (MDICLIENTINFO *) w->wExtra;
1034 switch (message)
1036 case WM_CREATE:
1038 cs = (LPCREATESTRUCTA)lParam;
1040 /* Translation layer doesn't know what's in the cs->lpCreateParams
1041 * so we have to keep track of what environment we're in. */
1043 if( w->flags & WIN_ISWIN32 )
1045 #define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
1046 ci->hWindowMenu = ccs->hWindowMenu;
1047 ci->idFirstChild = ccs->idFirstChild;
1048 #undef ccs
1050 else
1052 LPCLIENTCREATESTRUCT16 ccs = (LPCLIENTCREATESTRUCT16)
1053 PTR_SEG_TO_LIN(cs->lpCreateParams);
1054 ci->hWindowMenu = ccs->hWindowMenu;
1055 ci->idFirstChild = ccs->idFirstChild;
1058 ci->hwndChildMaximized = 0;
1059 ci->nActiveChildren = 0;
1060 ci->nTotalCreated = 0;
1061 ci->frameTitle = NULL;
1062 ci->mdiFlags = 0;
1063 ci->self = hwnd;
1064 w->dwStyle |= WS_CLIPCHILDREN;
1066 if (!hBmpClose)
1068 hBmpClose = CreateMDIMenuBitmap();
1069 hBmpRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1071 MDI_UpdateFrameText(frameWnd, hwnd, MDI_NOFRAMEREPAINT,frameWnd->text);
1073 AppendMenuA( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
1075 GetClientRect(frameWnd->hwndSelf, &rect);
1076 NC_HandleNCCalcSize( w, &rect );
1077 w->rectClient = rect;
1079 TRACE("Client created - hwnd = %04x, idFirst = %u\n",
1080 hwnd, ci->idFirstChild );
1082 retvalue = 0;
1083 goto END;
1085 case WM_DESTROY:
1086 if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
1087 if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
1089 ci->idFirstChild = nItems - 1;
1090 ci->nActiveChildren++; /* to delete a separator */
1091 while( ci->nActiveChildren-- )
1092 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
1094 retvalue = 0;
1095 goto END;
1097 case WM_MDIACTIVATE:
1098 if( ci->hwndActiveChild != (HWND)wParam )
1099 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
1100 retvalue = 0;
1101 goto END;
1103 case WM_MDICASCADE:
1104 retvalue = MDICascade(w, ci);
1105 goto END;
1107 case WM_MDICREATE:
1108 if (lParam) retvalue = MDICreateChild( w, ci, hwnd,
1109 (MDICREATESTRUCTA*)lParam );
1110 else retvalue = 0;
1111 goto END;
1113 case WM_MDIDESTROY:
1114 retvalue = MDIDestroyChild( w, ci, hwnd, (HWND)wParam, TRUE );
1115 goto END;
1117 case WM_MDIGETACTIVE:
1118 if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized > 0);
1119 retvalue = ci->hwndActiveChild;
1120 goto END;
1122 case WM_MDIICONARRANGE:
1123 ci->mdiFlags |= MDIF_NEEDUPDATE;
1124 ArrangeIconicWindows(hwnd);
1125 ci->sbRecalc = SB_BOTH+1;
1126 SendMessageA(hwnd, WM_MDICALCCHILDSCROLL, 0, 0L);
1127 retvalue = 0;
1128 goto END;
1130 case WM_MDIMAXIMIZE:
1131 ShowWindow( (HWND)wParam, SW_MAXIMIZE );
1132 retvalue = 0;
1133 goto END;
1135 case WM_MDINEXT: /* lParam != 0 means previous window */
1136 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)? FALSE : TRUE );
1137 break;
1139 case WM_MDIRESTORE:
1140 SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
1141 retvalue = 0;
1142 goto END;
1144 case WM_MDISETMENU:
1145 retvalue = MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1146 goto END;
1147 case WM_MDIREFRESHMENU:
1148 retvalue = MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
1149 goto END;
1151 case WM_MDITILE:
1152 ci->mdiFlags |= MDIF_NEEDUPDATE;
1153 ShowScrollBar(hwnd,SB_BOTH,FALSE);
1154 MDITile(w, ci, wParam);
1155 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1156 retvalue = 0;
1157 goto END;
1159 case WM_VSCROLL:
1160 case WM_HSCROLL:
1161 ci->mdiFlags |= MDIF_NEEDUPDATE;
1162 ScrollChildren(hwnd, message, wParam, lParam);
1163 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1164 retvalue = 0;
1165 goto END;
1167 case WM_SETFOCUS:
1168 if( ci->hwndActiveChild )
1170 WND* pw = WIN_FindWndPtr( ci->hwndActiveChild );
1171 if( !(pw->dwStyle & WS_MINIMIZE) )
1172 SetFocus( ci->hwndActiveChild );
1173 WIN_ReleaseWndPtr(pw);
1175 retvalue = 0;
1176 goto END;
1178 case WM_NCACTIVATE:
1179 if( ci->hwndActiveChild )
1180 SendMessageA(ci->hwndActiveChild, message, wParam, lParam);
1181 break;
1183 case WM_PARENTNOTIFY:
1184 if (LOWORD(wParam) == WM_LBUTTONDOWN)
1186 POINT16 pt = MAKEPOINT16(lParam);
1187 HWND16 child = ChildWindowFromPoint16(hwnd, pt);
1189 TRACE("notification from %04x (%i,%i)\n",child,pt.x,pt.y);
1191 if( child && child != hwnd && child != ci->hwndActiveChild )
1192 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1194 retvalue = 0;
1195 goto END;
1197 case WM_SIZE:
1198 if( IsWindow(ci->hwndChildMaximized) )
1200 WND* child = WIN_FindWndPtr(ci->hwndChildMaximized);
1201 RECT rect;
1203 rect.left = 0;
1204 rect.top = 0;
1205 rect.right = LOWORD(lParam);
1206 rect.bottom = HIWORD(lParam);
1208 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1209 MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
1210 rect.right - rect.left, rect.bottom - rect.top, 1);
1211 WIN_ReleaseWndPtr(child);
1213 else
1214 MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
1216 break;
1218 case WM_MDICALCCHILDSCROLL:
1219 if( (ci->mdiFlags & MDIF_NEEDUPDATE) && ci->sbRecalc )
1221 CalcChildScroll16(hwnd, ci->sbRecalc-1);
1222 ci->sbRecalc = 0;
1223 ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1225 retvalue = 0;
1226 goto END;
1229 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
1230 END:
1231 WIN_ReleaseWndPtr(w);
1232 WIN_ReleaseWndPtr(frameWnd);
1233 return retvalue;
1237 /***********************************************************************
1238 * DefFrameProc16 (USER.445)
1240 LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient,
1241 UINT16 message, WPARAM16 wParam, LPARAM lParam )
1243 HWND16 childHwnd;
1244 MDICLIENTINFO* ci;
1245 WND* wndPtr;
1247 if (hwndMDIClient)
1249 switch (message)
1251 case WM_COMMAND:
1252 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1254 if (!wndPtr) {
1255 ERR("null wndPtr for mdi window hwndMDIClient=%04x\n",
1256 hwndMDIClient);
1257 return 0;
1260 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1262 /* check for possible syscommands for maximized MDI child */
1263 WIN_ReleaseWndPtr(wndPtr);
1265 if( ci && (
1266 wParam < ci->idFirstChild ||
1267 wParam >= ci->idFirstChild + ci->nActiveChildren
1269 if( (wParam - 0xF000) & 0xF00F ) break;
1270 switch( wParam )
1272 case SC_SIZE:
1273 case SC_MOVE:
1274 case SC_MINIMIZE:
1275 case SC_MAXIMIZE:
1276 case SC_NEXTWINDOW:
1277 case SC_PREVWINDOW:
1278 case SC_CLOSE:
1279 case SC_RESTORE:
1280 if( ci->hwndChildMaximized )
1281 return SendMessage16( ci->hwndChildMaximized, WM_SYSCOMMAND,
1282 wParam, lParam);
1285 else
1287 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1288 childHwnd = MDI_GetChildByID(wndPtr,wParam );
1289 WIN_ReleaseWndPtr(wndPtr);
1291 if( childHwnd )
1292 SendMessage16(hwndMDIClient, WM_MDIACTIVATE,
1293 (WPARAM16)childHwnd , 0L);
1295 break;
1297 case WM_NCACTIVATE:
1298 SendMessage16(hwndMDIClient, message, wParam, lParam);
1299 break;
1301 case WM_SETTEXT:
1302 wndPtr = WIN_FindWndPtr(hwnd);
1303 MDI_UpdateFrameText(wndPtr, hwndMDIClient,
1304 MDI_REPAINTFRAME,
1305 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1306 WIN_ReleaseWndPtr(wndPtr);
1307 return 0;
1309 case WM_SETFOCUS:
1310 SetFocus(hwndMDIClient);
1311 break;
1313 case WM_SIZE:
1314 MoveWindow16(hwndMDIClient, 0, 0,
1315 LOWORD(lParam), HIWORD(lParam), TRUE);
1316 break;
1318 case WM_NEXTMENU:
1320 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1321 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1323 if( !(wndPtr->parent->dwStyle & WS_MINIMIZE)
1324 && ci->hwndActiveChild && !ci->hwndChildMaximized )
1326 /* control menu is between the frame system menu and
1327 * the first entry of menu bar */
1329 if( (wParam == VK_LEFT &&
1330 wndPtr->parent->wIDmenu == LOWORD(lParam)) ||
1331 (wParam == VK_RIGHT &&
1332 GetSubMenu16(wndPtr->parent->hSysMenu, 0) == LOWORD(lParam)) )
1334 LRESULT retvalue;
1335 WIN_ReleaseWndPtr(wndPtr);
1336 wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
1337 retvalue = MAKELONG( GetSubMenu16(wndPtr->hSysMenu, 0),
1338 ci->hwndActiveChild);
1339 WIN_ReleaseWndPtr(wndPtr);
1340 return retvalue;
1343 WIN_ReleaseWndPtr(wndPtr);
1344 break;
1348 return DefWindowProc16(hwnd, message, wParam, lParam);
1352 /***********************************************************************
1353 * DefFrameProc32A (USER32.122)
1355 LRESULT WINAPI DefFrameProcA( HWND hwnd, HWND hwndMDIClient,
1356 UINT message, WPARAM wParam, LPARAM lParam)
1358 if (hwndMDIClient)
1360 switch (message)
1362 case WM_COMMAND:
1363 return DefFrameProc16( hwnd, hwndMDIClient, message,
1364 (WPARAM16)wParam,
1365 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1367 case WM_NCACTIVATE:
1368 SendMessageA(hwndMDIClient, message, wParam, lParam);
1369 break;
1371 case WM_SETTEXT: {
1372 LRESULT ret;
1373 LPSTR segstr = SEGPTR_STRDUP((LPSTR)lParam);
1375 ret = DefFrameProc16(hwnd, hwndMDIClient, message,
1376 wParam, (LPARAM)SEGPTR_GET(segstr) );
1377 SEGPTR_FREE(segstr);
1378 return ret;
1381 case WM_NEXTMENU:
1382 case WM_SETFOCUS:
1383 case WM_SIZE:
1384 return DefFrameProc16( hwnd, hwndMDIClient, message,
1385 wParam, lParam );
1389 return DefWindowProcA(hwnd, message, wParam, lParam);
1393 /***********************************************************************
1394 * DefFrameProc32W (USER32.123)
1396 LRESULT WINAPI DefFrameProcW( HWND hwnd, HWND hwndMDIClient,
1397 UINT message, WPARAM wParam, LPARAM lParam)
1399 if (hwndMDIClient)
1401 switch (message)
1403 case WM_COMMAND:
1404 return DefFrameProc16( hwnd, hwndMDIClient, message,
1405 (WPARAM16)wParam,
1406 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
1408 case WM_NCACTIVATE:
1409 SendMessageW(hwndMDIClient, message, wParam, lParam);
1410 break;
1412 case WM_SETTEXT:
1414 LPSTR txt = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lParam);
1415 LRESULT ret = DefFrameProcA( hwnd, hwndMDIClient, message,
1416 wParam, (DWORD)txt );
1417 HeapFree(GetProcessHeap(),0,txt);
1418 return ret;
1420 case WM_NEXTMENU:
1421 case WM_SETFOCUS:
1422 case WM_SIZE:
1423 return DefFrameProcA( hwnd, hwndMDIClient, message,
1424 wParam, lParam );
1428 return DefWindowProcW( hwnd, message, wParam, lParam );
1432 /***********************************************************************
1433 * DefMDIChildProc16 (USER.447)
1435 LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message,
1436 WPARAM16 wParam, LPARAM lParam )
1438 MDICLIENTINFO *ci;
1439 WND *clientWnd,*tmpWnd = 0;
1440 LRESULT retvalue;
1442 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1443 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1445 switch (message)
1447 case WM_SETTEXT:
1448 DefWindowProc16(hwnd, message, wParam, lParam);
1449 MDI_MenuModifyItem(clientWnd,hwnd);
1450 if( ci->hwndChildMaximized == hwnd )
1451 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1452 MDI_REPAINTFRAME, NULL );
1453 retvalue = 0;
1454 goto END;
1456 case WM_CLOSE:
1457 SendMessage16(ci->self,WM_MDIDESTROY,(WPARAM16)hwnd,0L);
1458 retvalue = 0;
1459 goto END;
1461 case WM_SETFOCUS:
1462 if( ci->hwndActiveChild != hwnd )
1463 MDI_ChildActivate(clientWnd, hwnd);
1464 break;
1466 case WM_CHILDACTIVATE:
1467 MDI_ChildActivate(clientWnd, hwnd);
1468 retvalue = 0;
1469 goto END;
1471 case WM_NCPAINT:
1472 TRACE("WM_NCPAINT for %04x, active %04x\n",
1473 hwnd, ci->hwndActiveChild );
1474 break;
1476 case WM_SYSCOMMAND:
1477 switch( wParam )
1479 case SC_MOVE:
1480 if( ci->hwndChildMaximized == hwnd)
1482 retvalue = 0;
1483 goto END;
1485 break;
1486 case SC_RESTORE:
1487 case SC_MINIMIZE:
1488 tmpWnd = WIN_FindWndPtr(hwnd);
1489 tmpWnd->dwStyle |= WS_SYSMENU;
1490 WIN_ReleaseWndPtr(tmpWnd);
1491 break;
1492 case SC_MAXIMIZE:
1493 if( ci->hwndChildMaximized == hwnd)
1495 retvalue = SendMessage16( clientWnd->parent->hwndSelf,
1496 message, wParam, lParam);
1497 goto END;
1499 tmpWnd = WIN_FindWndPtr(hwnd);
1500 tmpWnd->dwStyle &= ~WS_SYSMENU;
1501 WIN_ReleaseWndPtr(tmpWnd);
1502 break;
1503 case SC_NEXTWINDOW:
1504 SendMessage16( ci->self, WM_MDINEXT, 0, 0);
1505 retvalue = 0;
1506 goto END;
1507 case SC_PREVWINDOW:
1508 SendMessage16( ci->self, WM_MDINEXT, 0, 1);
1509 retvalue = 0;
1510 goto END;
1512 break;
1514 case WM_GETMINMAXINFO:
1515 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO16*) PTR_SEG_TO_LIN(lParam));
1516 retvalue = 0;
1517 goto END;
1519 case WM_SETVISIBLE:
1520 if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
1521 else
1522 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1523 break;
1525 case WM_SIZE:
1526 /* do not change */
1528 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1530 ci->hwndChildMaximized = 0;
1532 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1533 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1534 MDI_REPAINTFRAME, NULL );
1537 if( wParam == SIZE_MAXIMIZED )
1539 HWND16 hMaxChild = ci->hwndChildMaximized;
1541 if( hMaxChild == hwnd ) break;
1543 if( hMaxChild)
1545 SendMessage16( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1547 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
1548 ShowWindow16( hMaxChild, SW_SHOWNOACTIVATE);
1550 SendMessage16( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1553 TRACE("maximizing child %04x\n", hwnd );
1555 ci->hwndChildMaximized = hwnd; /* !!! */
1556 ci->hwndActiveChild = hwnd;
1558 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1559 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1560 MDI_REPAINTFRAME, NULL );
1563 if( wParam == SIZE_MINIMIZED )
1565 HWND16 switchTo = MDI_GetWindow(clientWnd, hwnd, TRUE, WS_MINIMIZE);
1567 if( switchTo )
1568 SendMessage16( switchTo, WM_CHILDACTIVATE, 0, 0L);
1571 MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
1572 break;
1574 case WM_MENUCHAR:
1576 /* MDI children don't have menu bars */
1577 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1578 (WPARAM16)SC_KEYMENU, (LPARAM)wParam);
1579 retvalue = 0x00010000L;
1580 goto END;
1582 case WM_NEXTMENU:
1584 if( wParam == VK_LEFT ) /* switch to frame system menu */
1586 retvalue = MAKELONG( GetSubMenu16(clientWnd->parent->hSysMenu, 0),
1587 clientWnd->parent->hwndSelf );
1588 goto END;
1590 if( wParam == VK_RIGHT ) /* to frame menu bar */
1592 retvalue = MAKELONG( clientWnd->parent->wIDmenu,
1593 clientWnd->parent->hwndSelf );
1594 goto END;
1597 break;
1599 case WM_SYSCHAR:
1600 if (wParam == '-')
1602 SendMessage16(hwnd,WM_SYSCOMMAND,
1603 (WPARAM16)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1604 retvalue = 0;
1605 goto END;
1609 retvalue = DefWindowProc16(hwnd, message, wParam, lParam);
1610 END:
1611 WIN_ReleaseWndPtr(clientWnd);
1612 return retvalue;
1616 /***********************************************************************
1617 * DefMDIChildProc32A (USER32.124)
1619 LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
1620 WPARAM wParam, LPARAM lParam )
1622 MDICLIENTINFO *ci;
1623 WND *clientWnd,*tmpWnd;
1624 LRESULT retvalue;
1626 tmpWnd = WIN_FindWndPtr(hwnd);
1627 clientWnd = WIN_FindWndPtr(tmpWnd->parent->hwndSelf);
1628 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1629 WIN_ReleaseWndPtr(tmpWnd);
1631 switch (message)
1633 case WM_SETTEXT:
1634 DefWindowProcA(hwnd, message, wParam, lParam);
1635 MDI_MenuModifyItem(clientWnd,hwnd);
1636 if( ci->hwndChildMaximized == hwnd )
1637 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1638 MDI_REPAINTFRAME, NULL );
1639 retvalue = 0;
1640 goto END;
1642 case WM_GETMINMAXINFO:
1644 MINMAXINFO16 mmi;
1645 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)lParam, &mmi );
1646 MDI_ChildGetMinMaxInfo( clientWnd, hwnd, &mmi );
1647 STRUCT32_MINMAXINFO16to32( &mmi, (MINMAXINFO *)lParam );
1649 retvalue = 0;
1650 goto END;
1652 case WM_MENUCHAR:
1654 /* MDI children don't have menu bars */
1655 PostMessage16( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1656 (WPARAM16)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
1657 retvalue = 0x00010000L;
1658 goto END;
1660 case WM_CLOSE:
1661 case WM_SETFOCUS:
1662 case WM_CHILDACTIVATE:
1663 case WM_NCPAINT:
1664 case WM_SYSCOMMAND:
1665 case WM_SETVISIBLE:
1666 case WM_SIZE:
1667 case WM_NEXTMENU:
1668 retvalue = DefMDIChildProc16( hwnd, message, (WPARAM16)wParam, lParam );
1669 goto END;
1671 case WM_SYSCHAR:
1672 if (wParam == '-')
1674 SendMessageA(hwnd,WM_SYSCOMMAND,
1675 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1676 retvalue = 0;
1677 goto END;
1680 retvalue = DefWindowProcA(hwnd, message, wParam, lParam);
1681 END:
1682 WIN_ReleaseWndPtr(clientWnd);
1683 return retvalue;
1687 /***********************************************************************
1688 * DefMDIChildProc32W (USER32.125)
1690 LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
1691 WPARAM wParam, LPARAM lParam )
1693 MDICLIENTINFO *ci;
1694 WND *clientWnd;
1695 LRESULT retvalue;
1697 clientWnd = WIN_FindWndPtr(GetParent16(hwnd));
1698 ci = (MDICLIENTINFO *) clientWnd->wExtra;
1700 switch (message)
1702 case WM_SETTEXT:
1703 DefWindowProcW(hwnd, message, wParam, lParam);
1704 MDI_MenuModifyItem(clientWnd,hwnd);
1705 if( ci->hwndChildMaximized == hwnd )
1706 MDI_UpdateFrameText( clientWnd->parent, ci->self,
1707 MDI_REPAINTFRAME, NULL );
1708 retvalue = 0;
1709 goto END;
1711 case WM_GETMINMAXINFO:
1712 case WM_MENUCHAR:
1713 case WM_CLOSE:
1714 case WM_SETFOCUS:
1715 case WM_CHILDACTIVATE:
1716 case WM_NCPAINT:
1717 case WM_SYSCOMMAND:
1718 case WM_SETVISIBLE:
1719 case WM_SIZE:
1720 case WM_NEXTMENU:
1721 retvalue = DefMDIChildProcA( hwnd, message, (WPARAM16)wParam, lParam );
1722 goto END;
1724 case WM_SYSCHAR:
1725 if (wParam == '-')
1727 SendMessageW(hwnd,WM_SYSCOMMAND,
1728 (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)VK_SPACE);
1729 retvalue = 0;
1730 goto END;
1733 retvalue = DefWindowProcW(hwnd, message, wParam, lParam);
1734 END:
1735 WIN_ReleaseWndPtr(clientWnd);
1736 return retvalue;
1741 /**********************************************************************
1742 * CreateMDIWindowA [USER32.79] Creates a MDI child in new thread
1743 * FIXME: its in the same thread now
1745 * RETURNS
1746 * Success: Handle to created window
1747 * Failure: NULL
1749 HWND WINAPI CreateMDIWindowA(
1750 LPCSTR lpClassName, /* [in] Pointer to registered child class name */
1751 LPCSTR lpWindowName, /* [in] Pointer to window name */
1752 DWORD dwStyle, /* [in] Window style */
1753 INT X, /* [in] Horizontal position of window */
1754 INT Y, /* [in] Vertical position of window */
1755 INT nWidth, /* [in] Width of window */
1756 INT nHeight, /* [in] Height of window */
1757 HWND hWndParent, /* [in] Handle to parent window */
1758 HINSTANCE hInstance, /* [in] Handle to application instance */
1759 LPARAM lParam) /* [in] Application-defined value */
1761 WARN("is only single threaded!\n");
1762 return MDI_CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, X, Y,
1763 nWidth, nHeight, hWndParent, hInstance, lParam);
1766 /**********************************************************************
1767 * MDI_CreateMDIWindowA
1768 * single threaded version of CreateMDIWindowA
1769 * called by CreateWindowEx32A
1771 HWND MDI_CreateMDIWindowA(
1772 LPCSTR lpClassName,
1773 LPCSTR lpWindowName,
1774 DWORD dwStyle,
1775 INT X,
1776 INT Y,
1777 INT nWidth,
1778 INT nHeight,
1779 HWND hWndParent,
1780 HINSTANCE hInstance,
1781 LPARAM lParam)
1783 MDICLIENTINFO* pCi;
1784 MDICREATESTRUCTA cs;
1785 WND *pWnd=WIN_FindWndPtr(hWndParent);
1786 HWND retvalue;
1788 TRACE("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld)\n",
1789 debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
1790 nWidth,nHeight,hWndParent,hInstance,lParam);
1792 if(!pWnd){
1793 ERR(" bad hwnd for MDI-client: %d\n",hWndParent);
1794 return 0;
1796 cs.szClass=lpClassName;
1797 cs.szTitle=lpWindowName;
1798 cs.hOwner=hInstance;
1799 cs.x=X;
1800 cs.y=Y;
1801 cs.cx=nWidth;
1802 cs.cy=nHeight;
1803 cs.style=dwStyle;
1804 cs.lParam=lParam;
1806 pCi=(MDICLIENTINFO *)pWnd->wExtra;
1808 retvalue = MDICreateChild(pWnd,pCi,hWndParent,&cs);
1809 WIN_ReleaseWndPtr(pWnd);
1810 return retvalue;
1813 /***************************************
1814 * CreateMDIWindow32W [USER32.80] Creates a MDI child in new thread
1816 * RETURNS
1817 * Success: Handle to created window
1818 * Failure: NULL
1820 HWND WINAPI CreateMDIWindowW(
1821 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1822 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1823 DWORD dwStyle, /* [in] Window style */
1824 INT X, /* [in] Horizontal position of window */
1825 INT Y, /* [in] Vertical position of window */
1826 INT nWidth, /* [in] Width of window */
1827 INT nHeight, /* [in] Height of window */
1828 HWND hWndParent, /* [in] Handle to parent window */
1829 HINSTANCE hInstance, /* [in] Handle to application instance */
1830 LPARAM lParam) /* [in] Application-defined value */
1832 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1833 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1834 nWidth,nHeight,hWndParent,hInstance,lParam);
1835 return (HWND)NULL;
1839 /******************************************************************************
1840 * CreateMDIWindow32W [USER32.80] Creates a MDI child window
1841 * single threaded version of CreateMDIWindow
1842 * called by CreateWindowEx32W().
1844 HWND MDI_CreateMDIWindowW(
1845 LPCWSTR lpClassName, /* [in] Pointer to registered child class name */
1846 LPCWSTR lpWindowName, /* [in] Pointer to window name */
1847 DWORD dwStyle, /* [in] Window style */
1848 INT X, /* [in] Horizontal position of window */
1849 INT Y, /* [in] Vertical position of window */
1850 INT nWidth, /* [in] Width of window */
1851 INT nHeight, /* [in] Height of window */
1852 HWND hWndParent, /* [in] Handle to parent window */
1853 HINSTANCE hInstance, /* [in] Handle to application instance */
1854 LPARAM lParam) /* [in] Application-defined value */
1856 FIXME("(%s,%s,%ld,%d,%d,%d,%d,%x,%d,%ld): stub\n",
1857 debugstr_w(lpClassName),debugstr_w(lpWindowName),dwStyle,X,Y,
1858 nWidth,nHeight,hWndParent,hInstance,lParam);
1859 return (HWND)NULL;
1863 /**********************************************************************
1864 * TranslateMDISysAccel32 (USER32.555)
1866 BOOL WINAPI TranslateMDISysAccel( HWND hwndClient, LPMSG msg )
1868 MSG16 msg16;
1870 STRUCT32_MSG32to16(msg,&msg16);
1871 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1872 return TranslateMDISysAccel16(hwndClient,&msg16);
1876 /**********************************************************************
1877 * TranslateMDISysAccel16 (USER.451)
1879 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1882 if( IsWindow(hwndClient) && (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN))
1884 MDICLIENTINFO *ci = NULL;
1885 HWND wnd;
1886 WND *clientWnd = WIN_FindWndPtr(hwndClient);
1888 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1889 wnd = ci->hwndActiveChild;
1891 WIN_ReleaseWndPtr(clientWnd);
1893 if( IsWindow(wnd) && !(GetWindowLongA(wnd,GWL_STYLE) & WS_DISABLED) )
1895 WPARAM16 wParam = 0;
1897 /* translate if the Ctrl key is down and Alt not. */
1899 if( (GetKeyState(VK_CONTROL) & 0x8000) &&
1900 !(GetKeyState(VK_MENU) & 0x8000))
1902 switch( msg->wParam )
1904 case VK_F6:
1905 case VK_TAB:
1906 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )
1907 ? SC_NEXTWINDOW : SC_PREVWINDOW;
1908 break;
1909 case VK_F4:
1910 case VK_RBUTTON:
1911 wParam = SC_CLOSE;
1912 break;
1913 default:
1914 return 0;
1916 TRACE("wParam = %04x\n", wParam);
1917 SendMessage16( ci->hwndActiveChild, WM_SYSCOMMAND,
1918 wParam, (LPARAM)msg->wParam);
1919 return 1;
1923 return 0; /* failure */
1927 /***********************************************************************
1928 * CalcChildScroll (USER.462)
1930 void WINAPI CalcChildScroll16( HWND16 hwnd, WORD scroll )
1932 SCROLLINFO info;
1933 RECT childRect, clientRect;
1934 INT vmin, vmax, hmin, hmax, vpos, hpos;
1935 WND *pWnd, *Wnd;
1937 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
1938 Wnd = WIN_FindWndPtr(hwnd);
1939 GetClientRect( hwnd, &clientRect );
1940 SetRectEmpty( &childRect );
1942 for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1944 if( pWnd->dwStyle & WS_MAXIMIZE )
1946 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1947 WIN_ReleaseWndPtr(pWnd);
1948 WIN_ReleaseWndPtr(Wnd);
1949 return;
1951 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
1953 WIN_ReleaseWndPtr(pWnd);
1954 UnionRect( &childRect, &clientRect, &childRect );
1956 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1957 hpos = clientRect.left - childRect.left;
1958 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1959 vpos = clientRect.top - childRect.top;
1961 switch( scroll )
1963 case SB_HORZ:
1964 vpos = hpos; vmin = hmin; vmax = hmax;
1965 case SB_VERT:
1966 info.cbSize = sizeof(info);
1967 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1968 info.fMask = SIF_POS | SIF_RANGE;
1969 SetScrollInfo(hwnd, scroll, &info, TRUE);
1970 break;
1971 case SB_BOTH:
1972 SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
1973 hmin, hmax, hpos);
1975 WIN_ReleaseWndPtr(Wnd);
1979 /***********************************************************************
1980 * ScrollChildren16 (USER.463)
1982 void WINAPI ScrollChildren16(HWND16 hWnd, UINT16 uMsg, WPARAM16 wParam, LPARAM lParam)
1984 ScrollChildren( hWnd, uMsg, wParam, lParam );
1988 /***********************************************************************
1989 * ScrollChildren32 (USER32.448)
1991 void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam,
1992 LPARAM lParam)
1994 WND *wndPtr = WIN_FindWndPtr(hWnd);
1995 INT newPos = -1;
1996 INT curPos, length, minPos, maxPos, shift;
1998 if( !wndPtr ) return;
2000 if( uMsg == WM_HSCROLL )
2002 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
2003 curPos = GetScrollPos(hWnd,SB_HORZ);
2004 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
2005 shift = GetSystemMetrics(SM_CYHSCROLL);
2007 else if( uMsg == WM_VSCROLL )
2009 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
2010 curPos = GetScrollPos(hWnd,SB_VERT);
2011 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
2012 shift = GetSystemMetrics(SM_CXVSCROLL);
2014 else
2016 WIN_ReleaseWndPtr(wndPtr);
2017 return;
2020 WIN_ReleaseWndPtr(wndPtr);
2021 switch( wParam )
2023 case SB_LINEUP:
2024 newPos = curPos - shift;
2025 break;
2026 case SB_LINEDOWN:
2027 newPos = curPos + shift;
2028 break;
2029 case SB_PAGEUP:
2030 newPos = curPos - length;
2031 break;
2032 case SB_PAGEDOWN:
2033 newPos = curPos + length;
2034 break;
2036 case SB_THUMBPOSITION:
2037 newPos = LOWORD(lParam);
2038 break;
2040 case SB_THUMBTRACK:
2041 return;
2043 case SB_TOP:
2044 newPos = minPos;
2045 break;
2046 case SB_BOTTOM:
2047 newPos = maxPos;
2048 break;
2049 case SB_ENDSCROLL:
2050 CalcChildScroll16(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
2051 return;
2054 if( newPos > maxPos )
2055 newPos = maxPos;
2056 else
2057 if( newPos < minPos )
2058 newPos = minPos;
2060 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
2062 if( uMsg == WM_VSCROLL )
2063 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
2064 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2065 else
2066 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
2067 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
2071 /******************************************************************************
2072 * CascadeWindows [USER32.21] Cascades MDI child windows
2074 * RETURNS
2075 * Success: Number of cascaded windows.
2076 * Failure: 0
2078 WORD WINAPI
2079 CascadeWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2080 UINT cKids, const HWND *lpKids)
2082 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2083 hwndParent, wFlags, cKids);
2085 return 0;
2089 /******************************************************************************
2090 * TileWindows [USER32.545] Tiles MDI child windows
2092 * RETURNS
2093 * Success: Number of tiled windows.
2094 * Failure: 0
2096 WORD WINAPI
2097 TileWindows (HWND hwndParent, UINT wFlags, const LPRECT lpRect,
2098 UINT cKids, const HWND *lpKids)
2100 FIXME("(0x%08x,0x%08x,...,%u,...): stub\n",
2101 hwndParent, wFlags, cKids);
2103 return 0;