[Win32k]
[reactos.git] / reactos / win32ss / user / ntuser / defwnd.c
index ea2e385..f6218b0 100644 (file)
 
 DBG_DEFAULT_CHANNEL(UserDefwnd);
 
 
 DBG_DEFAULT_CHANNEL(UserDefwnd);
 
+#define UserHasDlgFrameStyle(Style, ExStyle)                                   \
+ (((ExStyle) & WS_EX_DLGMODALFRAME) ||                                         \
+  (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
+
+#define UserHasThickFrameStyle(Style, ExStyle)                                 \
+  (((Style) & WS_THICKFRAME) &&                                                \
+   (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
+
+#define UserHasThinFrameStyle(Style, ExStyle)                                  \
+  (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
+
+#define ON_LEFT_BORDER(hit) \
+ (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
+#define ON_RIGHT_BORDER(hit) \
+ (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
+#define ON_TOP_BORDER(hit) \
+ (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
+#define ON_BOTTOM_BORDER(hit) \
+ (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
+
 // Client Shutdown messages
 #define MCS_SHUTDOWNTIMERS  1
 #define MCS_QUERYENDSESSION 2
 // Client Shutdown messages
 #define MCS_SHUTDOWNTIMERS  1
 #define MCS_QUERYENDSESSION 2
@@ -133,7 +153,6 @@ DefWndControlColor(HDC hDC, UINT ctlType)
   return IntGetSysColorBrush(COLOR_WINDOW);
 }
 
   return IntGetSysColorBrush(COLOR_WINDOW);
 }
 
-
 LRESULT FASTCALL
 DefWndHandleWindowPosChanging(PWND pWnd, WINDOWPOS* Pos)
 {
 LRESULT FASTCALL
 DefWndHandleWindowPosChanging(PWND pWnd, WINDOWPOS* Pos)
 {
@@ -163,27 +182,27 @@ DefWndHandleWindowPosChanging(PWND pWnd, WINDOWPOS* Pos)
 LRESULT FASTCALL
 DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
 {
 LRESULT FASTCALL
 DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
 {
-  RECT Rect;
-  LONG style = pWnd->style;
+   RECT Rect;
+   LONG style = pWnd->style;
 
 
-  IntGetClientRect(pWnd, &Rect);
-  IntMapWindowPoints(pWnd, (style & WS_CHILD ? IntGetParent(pWnd) : NULL), (LPPOINT) &Rect, 2);
+   IntGetClientRect(pWnd, &Rect);
+   IntMapWindowPoints(pWnd, (style & WS_CHILD ? IntGetParent(pWnd) : NULL), (LPPOINT) &Rect, 2);
 
 
-  if (!(Pos->flags & SWP_NOCLIENTMOVE))
-  {
+   if (!(Pos->flags & SWP_NOCLIENTMOVE))
+   {
       co_IntSendMessage(UserHMGetHandle(pWnd), WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
       co_IntSendMessage(UserHMGetHandle(pWnd), WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
-  }
+   }
 
 
-  if (!(Pos->flags & SWP_NOCLIENTSIZE) || (Pos->flags & SWP_STATECHANGED))
-  {
+   if (!(Pos->flags & SWP_NOCLIENTSIZE) || (Pos->flags & SWP_STATECHANGED))
+   {
       if (style & WS_MINIMIZE) co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, SIZE_MINIMIZED, 0 );
       else
       {
          WPARAM wp = (style & WS_MAXIMIZE) ? SIZE_MAXIMIZED : SIZE_RESTORED;
          co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, wp, MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
       }
       if (style & WS_MINIMIZE) co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, SIZE_MINIMIZED, 0 );
       else
       {
          WPARAM wp = (style & WS_MAXIMIZE) ? SIZE_MAXIMIZED : SIZE_RESTORED;
          co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, wp, MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
       }
-  }
-  return 0;
+   }
+   return 0;
 }
 
 VOID FASTCALL
 }
 
 VOID FASTCALL
@@ -192,12 +211,12 @@ UserDrawWindowFrame(HDC hdc,
                    ULONG width,
                    ULONG height)
 {
                    ULONG width,
                    ULONG height)
 {
-  HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
-  NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
-  NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
-  NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -height, PATINVERT );
-  NtGdiPatBlt( hdc, rect->right - 1, rect->top, -width, rect->bottom - rect->top - height, PATINVERT );
-  NtGdiSelectBrush( hdc, hbrush );
+   HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
+   NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->right - 1, rect->top, -width, rect->bottom - rect->top - height, PATINVERT );
+   NtGdiSelectBrush( hdc, hbrush );
 }
 
 VOID FASTCALL
 }
 
 VOID FASTCALL
@@ -205,10 +224,503 @@ UserDrawMovingFrame(HDC hdc,
                     RECTL *rect,
                     BOOL thickframe)
 {
                     RECTL *rect,
                     BOOL thickframe)
 {
-  if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
-  else UserDrawWindowFrame(hdc, rect, 1, 1);
+   if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
+   else UserDrawWindowFrame(hdc, rect, 1, 1);
+}
+
+/***********************************************************************
+ *           NC_GetInsideRect
+ *
+ * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
+ * but without the borders (if any).
+ */
+void FASTCALL
+NC_GetInsideRect(PWND Wnd, RECT *rect)
+{
+    ULONG Style;
+    ULONG ExStyle;
+
+    Style = Wnd->style;
+    ExStyle = Wnd->ExStyle;
+
+    rect->top    = rect->left = 0;
+    rect->right  = Wnd->rcWindow.right - Wnd->rcWindow.left;
+    rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
+
+    if (Style & WS_ICONIC) return;
+
+    /* Remove frame from rectangle */
+    if (UserHasThickFrameStyle(Style, ExStyle ))
+    {
+        RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
+    }
+    else
+    {
+        if (UserHasDlgFrameStyle(Style, ExStyle ))
+        {
+            RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
+            /* FIXME: this isn't in NC_AdjustRect? why not? */
+            if (ExStyle & WS_EX_DLGMODALFRAME)
+                   RECTL_vInflateRect( rect, -1, 0 );
+        }
+        else
+        {
+            if (UserHasThinFrameStyle(Style, ExStyle))
+            {
+                RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+            }
+        }
+    }
+    /* We have additional border information if the window
+     * is a child (but not an MDI child) */
+    if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
+    {
+       if (ExStyle & WS_EX_CLIENTEDGE)
+          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
+       if (ExStyle & WS_EX_STATICEDGE)
+          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+    }
+}
+
+LONG FASTCALL
+DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
+{
+   LONG hittest = 0;
+   POINT pt;
+   MSG msg;
+   RECT rectWindow;
+   ULONG Style = Wnd->style;
+   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+   rectWindow = Wnd->rcWindow;
+
+   if ((wParam & 0xfff0) == SC_MOVE)
+   {
+       /* Move pointer at the center of the caption */
+       RECT rect = rectWindow;
+       /* Note: to be exactly centered we should take the different types
+        * of border into account, but it shouldn't make more than a few pixels
+        * of difference so let's not bother with that */
+       if (Style & WS_SYSMENU)
+          rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
+       if (Style & WS_MINIMIZEBOX)
+         rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+       if (Style & WS_MAXIMIZEBOX)
+          rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+       pt.x = (rect.right + rect.left) / 2;
+       pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
+       hittest = HTCAPTION;
+       *capturePoint = pt;
+   }
+   else  /* SC_SIZE */
+   {
+       pt.x = pt.y = 0;
+       while (!hittest)
+       {
+          if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
+          if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+         switch(msg.message)
+           {
+           case WM_MOUSEMOVE:
+             //// Clamp the mouse position to the window rectangle when starting a window resize.
+              pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
+              pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
+             hittest = GetNCHitEx(Wnd, pt);
+             if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
+             break;
+
+           case WM_LBUTTONUP:
+             return 0;
+
+           case WM_KEYDOWN:
+             switch (msg.wParam)
+               {
+               case VK_UP:
+                 hittest = HTTOP;
+                 pt.x = (rectWindow.left+rectWindow.right)/2;
+                 pt.y =  rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_DOWN:
+                 hittest = HTBOTTOM;
+                 pt.x = (rectWindow.left+rectWindow.right)/2;
+                 pt.y =  rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_LEFT:
+                 hittest = HTLEFT;
+                 pt.x =  rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RIGHT:
+                 hittest = HTRIGHT;
+                 pt.x =  rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RETURN:
+               case VK_ESCAPE:
+                 return 0;
+               }
+            default:
+              IntTranslateKbdMessage( &msg, 0 );
+              pti->TIF_flags |= TIF_MOVESIZETRACKING;
+              IntDispatchMessage( &msg );
+              pti->TIF_flags |= TIF_MOVESIZETRACKING;
+              break;
+           }
+       }
+       *capturePoint = pt;
+    }
+    UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
+    co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
+    return hittest;
+}
+
+//
+//  System Command Size and Move
+//
+//  Perform SC_MOVE and SC_SIZE commands.
+//
+VOID FASTCALL
+DefWndDoSizeMove(PWND pwnd, WORD wParam)
+{
+   MSG msg;
+   RECT sizingRect, mouseRect, origRect, unmodRect;
+   HDC hdc;
+   LONG hittest = (LONG)(wParam & 0x0f);
+   HCURSOR hDragCursor = 0, hOldCursor = 0;
+   POINT minTrack, maxTrack;
+   POINT capturePoint, pt;
+   ULONG Style, ExStyle;
+   BOOL thickframe;
+   BOOL iconic;
+   BOOL moved = FALSE;
+   BOOL DragFullWindows = FALSE;
+   PWND pWndParent = NULL;
+   WPARAM syscommand = (wParam & 0xfff0);
+   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+   //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
+   //                  The task bar can grow in size and can not reduce due to the change
+   //                  in the work area.
+
+   Style = pwnd->style;
+   ExStyle = pwnd->ExStyle;
+   iconic = (Style & WS_MINIMIZE) != 0;
+
+   if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
+
+   thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
+
+   //
+   // Show window contents while dragging the window, get flag from registry data.
+   //
+   UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
+
+   pt.x = pti->ptLast.x;
+   pt.y = pti->ptLast.y;
+   capturePoint = pt;
+   UserClipCursor( NULL );
+
+   TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
+          pwnd, syscommand, hittest, pt.x, pt.y);
+
+   if (syscommand == SC_MOVE)
+   {
+      if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
+      if (!hittest) return;
+   }
+   else  /* SC_SIZE */
+   {
+      if (!thickframe) return;
+      if (hittest && (syscommand != SC_MOUSEMENU))
+      {
+          hittest += (HTLEFT - WMSZ_LEFT);
+      }
+      else
+      {
+          co_UserSetCapture(UserHMGetHandle(pwnd));
+          hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
+         if (!hittest)
+          {
+              IntReleaseCapture();
+              return;
+          }
+      }
+   }
+
+   /* Get min/max info */
+
+   co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
+   sizingRect = pwnd->rcWindow;
+   origRect = sizingRect;
+   if (Style & WS_CHILD)
+   {
+      pWndParent = IntGetParent(pwnd);
+      IntGetClientRect( pWndParent, &mouseRect );
+      IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
+      IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
+      unmodRect = sizingRect;
+   }
+   else
+   {
+      if (!(ExStyle & WS_EX_TOPMOST))
+      {
+        UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
+      }
+      else
+      {
+        RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
+      }
+      unmodRect = sizingRect;
+   }
+
+   if (ON_LEFT_BORDER(hittest))
+   {
+      mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
+      mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
+   }
+   else if (ON_RIGHT_BORDER(hittest))
+   {
+      mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
+      mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
+   }
+   if (ON_TOP_BORDER(hittest))
+   {
+      mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
+      mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
+   }
+   else if (ON_BOTTOM_BORDER(hittest))
+   {
+      mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
+      mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
+   }
+
+   hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
+
+   if ( iconic ) /* create a cursor for dragging */
+   {
+      hDragCursor = pwnd->pcls->hIcon;;
+      if ( !hDragCursor ) hDragCursor = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
+      if ( !hDragCursor ) iconic = FALSE;
+   }
+
+   /* repaint the window before moving it around */
+   co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
+
+   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
+
+   if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
+
+   pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
+
+   for(;;)
+   {
+      int dx = 0, dy = 0;
+
+      if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
+      if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+      /* Exit on button-up, Return, or Esc */
+      if ((msg.message == WM_LBUTTONUP) ||
+         ((msg.message == WM_KEYDOWN) &&
+          ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
+
+      if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
+      {
+         IntTranslateKbdMessage( &msg , 0 );
+         IntDispatchMessage( &msg );
+         continue;  /* We are not interested in other messages */
+      }
+
+      pt = msg.pt;
+
+      if (msg.message == WM_KEYDOWN) switch(msg.wParam)
+      {
+       case VK_UP:    pt.y -= 8; break;
+       case VK_DOWN:  pt.y += 8; break;
+       case VK_LEFT:  pt.x -= 8; break;
+       case VK_RIGHT: pt.x += 8; break;
+      }
+
+      pt.x = max( pt.x, mouseRect.left );
+      pt.x = min( pt.x, mouseRect.right - 1 );
+      pt.y = max( pt.y, mouseRect.top );
+      pt.y = min( pt.y, mouseRect.bottom - 1 );
+
+      dx = pt.x - capturePoint.x;
+      dy = pt.y - capturePoint.y;
+
+      if (dx || dy)
+      {
+         if ( !moved )
+         {
+             moved = TRUE;
+
+              if ( iconic ) /* ok, no system popup tracking */
+              {
+                 hOldCursor = IntSetCursor(hDragCursor);
+                 UserShowCursor( TRUE );
+              }
+              else if(!DragFullWindows)
+                 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+         }
+
+         if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
+         else
+         {
+             RECT newRect = unmodRect;
+
+             if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+             if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
+             if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
+             else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
+             if (ON_TOP_BORDER(hittest)) newRect.top += dy;
+             else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
+             capturePoint = pt;
+
+              //
+              //  Save the new position to the unmodified rectangle. This allows explorer task bar
+              //  sizing. Explorer will forces back the position unless a certain amount of sizing
+              //  has occurred.
+              //
+              unmodRect = newRect;
+
+             /* determine the hit location */
+              if (syscommand == SC_SIZE)
+              {
+                  WPARAM wpSizingHit = 0;
+
+                  if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
+                      wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
+                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
+              }
+              else
+                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
+
+             if (!iconic)
+              {
+                 if (!DragFullWindows)
+                     UserDrawMovingFrame( hdc, &newRect, thickframe );
+                 else
+                 {  // Moving the whole window now!
+                    PWND pwndTemp;
+                    //// This causes the mdi child window to jump up when it is moved.
+                    //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
+                   co_WinPosSetWindowPos( pwnd,
+                                          0,
+                                          newRect.left,
+                                          newRect.top,
+                                          newRect.right - newRect.left,
+                                          newRect.bottom - newRect.top,
+                                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+
+                    // Update all the windows after the move or size, including this window.
+                    for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
+                          pwndTemp;
+                          pwndTemp = pwndTemp->spwndNext )
+                    {
+                       RECTL rect;
+                       // Only the windows that overlap will be redrawn.
+                       if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
+                       {
+                          co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
+                       }
+                    }
+                 }
+              }
+              sizingRect = newRect;
+         }
+      }
+   }
+
+   pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
+
+   IntReleaseCapture();
+
+   if ( iconic )
+   {
+      if ( moved ) /* restore cursors, show icon title later on */
+      {
+         UserShowCursor( FALSE );
+         IntSetCursor( hOldCursor );
+      }
+      IntDestroyCursor( hDragCursor, FALSE );
+   }
+   else if ( moved && !DragFullWindows )
+      UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+
+   UserReleaseDC(NULL, hdc, FALSE);
+
+   //// This causes the mdi child window to jump up when it is moved.
+   //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
+
+   if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
+   {
+      ERR("DoSizeMove : WH_CBT Call Hook return!\n");
+      moved = FALSE;
+   }
+
+   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
+
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
+   //// wine mdi hack
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
+   ////
+   /* window moved or resized */
+   if (moved)
+   {
+      /* if the moving/resizing isn't canceled call SetWindowPos
+       * with the new position or the new size of the window
+       */
+      if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
+      {
+         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
+         if (!DragFullWindows || iconic )
+         {
+           co_WinPosSetWindowPos( pwnd,
+                                  0,
+                                  sizingRect.left,
+                                  sizingRect.top,
+                                  sizingRect.right - sizingRect.left,
+                                  sizingRect.bottom - sizingRect.top,
+                                 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+          }
+      }
+      else
+      { /* restore previous size/position */
+       if ( DragFullWindows )
+       {
+         co_WinPosSetWindowPos( pwnd,
+                                0,
+                                origRect.left,
+                                origRect.top,
+                                origRect.right - origRect.left,
+                                origRect.bottom - origRect.top,
+                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+        }
+      }
+   }
+
+   if ( IntIsWindow(UserHMGetHandle(pwnd)) )
+     if ( iconic )
+     {
+       /* Single click brings up the system menu when iconized */
+       if ( !moved )
+        {
+           if( Style & WS_SYSMENU )
+             co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
+        }
+     }
 }
 
 }
 
+//
+// Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
+//
 LRESULT FASTCALL
 DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
 {
 LRESULT FASTCALL
 DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
 {
@@ -227,15 +739,58 @@ DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
    {
       case SC_MOVE:
       case SC_SIZE:
    {
       case SC_MOVE:
       case SC_SIZE:
-        //DefWndDoSizeMove(pWnd, wParam);
-        ERR("SC_MOVESIZE\n");
+        DefWndDoSizeMove(pWnd, wParam);
+        break;
+
+      case SC_MINIMIZE:
+        if (UserHMGetHandle(pWnd) == UserGetActiveWindow())
+            IntShowOwnedPopups(pWnd,FALSE); // This is done in ShowWindow! Need to retest!
+        co_WinPosShowWindow( pWnd, SW_MINIMIZE );
         break;
 
         break;
 
+      case SC_MAXIMIZE:
+        if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow())
+            IntShowOwnedPopups(pWnd,TRUE);
+        co_WinPosShowWindow( pWnd, SW_MAXIMIZE );
+        break;
+
+      case SC_RESTORE:
+        if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow())
+            IntShowOwnedPopups(pWnd,TRUE);
+        co_WinPosShowWindow( pWnd, SW_RESTORE );
+        break;
+
+      case SC_CLOSE:
+        return co_IntSendMessage(UserHMGetHandle(pWnd), WM_CLOSE, 0, 0);
+
       case SC_SCREENSAVE:
         ERR("Screensaver Called!\n");
         UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure
         break;
 
       case SC_SCREENSAVE:
         ERR("Screensaver Called!\n");
         UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure
         break;
 
+      case SC_HOTKEY:
+        {
+           USER_REFERENCE_ENTRY Ref;
+
+           pWnd = ValidateHwndNoErr((HWND)lParam);
+           if (pWnd)
+           {
+              if (pWnd->spwndLastActive)
+              {
+                 pWnd = pWnd->spwndLastActive;
+              }
+              UserRefObjectCo(pWnd, &Ref);
+              co_IntSetForegroundWindow(pWnd);
+              UserDerefObjectCo(pWnd);
+              if (pWnd->style & WS_MINIMIZE)
+              {
+                 UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_RESTORE, 0);
+              }
+           }
+        }
+        break;
+
+
       default:
    // We do not support anything else here so we should return normal even when sending a hook.
         return 0;
       default:
    // We do not support anything else here so we should return normal even when sending a hook.
         return 0;
@@ -244,6 +799,39 @@ DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
    return(Hook ? 1 : 0); // Don't call us again from user space.
 }
 
    return(Hook ? 1 : 0); // Don't call us again from user space.
 }
 
+VOID FASTCALL DefWndPrint( PWND pwnd, HDC hdc, ULONG uFlags)
+{
+  /*
+   * Visibility flag.
+   */
+  if ( (uFlags & PRF_CHECKVISIBLE) &&
+       !IntIsWindowVisible(pwnd) )
+      return;
+
+  /*
+   * Unimplemented flags.
+   */
+  if ( (uFlags & PRF_CHILDREN) ||
+       (uFlags & PRF_OWNED)    ||
+       (uFlags & PRF_NONCLIENT) )
+  {
+    FIXME("WM_PRINT message with unsupported flags\n");
+  }
+
+  /*
+   * Background
+   */
+  if ( uFlags & PRF_ERASEBKGND)
+    co_IntSendMessage(UserHMGetHandle(pwnd), WM_ERASEBKGND, (WPARAM)hdc, 0);
+
+  /*
+   * Client area
+   */
+  if ( uFlags & PRF_CLIENT)
+    co_IntSendMessage(UserHMGetHandle(pwnd), WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
+}
+
+
 /*
    Win32k counterpart of User DefWindowProc
  */
 /*
    Win32k counterpart of User DefWindowProc
  */
@@ -304,6 +892,10 @@ IntDefWindowProc(
          UserDerefObjectCo(Wnd->spwndParent);
          break;
 
          UserDerefObjectCo(Wnd->spwndParent);
          break;
 
+      case WM_CLOSE:
+         co_UserDestroyWindow(Wnd);
+         break;
+
       case WM_CTLCOLORMSGBOX:
       case WM_CTLCOLOREDIT:
       case WM_CTLCOLORLISTBOX:
       case WM_CTLCOLORMSGBOX:
       case WM_CTLCOLOREDIT:
       case WM_CTLCOLORLISTBOX:
@@ -316,6 +908,51 @@ IntDefWindowProc(
       case WM_CTLCOLOR:
            return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
 
       case WM_CTLCOLOR:
            return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
 
+      case WM_ACTIVATE:
+       /* The default action in Windows is to set the keyboard focus to
+        * the window, if it's being activated and not minimized */
+         if (LOWORD(wParam) != WA_INACTIVE &&
+              !(Wnd->style & WS_MINIMIZE))
+         {
+            //ERR("WM_ACTIVATE %p\n",hWnd);
+            co_UserSetFocus(Wnd);
+         }
+         break;
+
+      case WM_MOUSEWHEEL:
+         if (Wnd->style & WS_CHILD)
+         {
+            HWND hwndParent;
+            PWND pwndParent = IntGetParent(Wnd);
+            hwndParent = pwndParent ? UserHMGetHandle(pwndParent) : NULL;
+            return co_IntSendMessage( hwndParent, WM_MOUSEWHEEL, wParam, lParam);
+         }
+         break;
+
+      case WM_ERASEBKGND:
+      case WM_ICONERASEBKGND:
+      {
+         RECT Rect;
+         HBRUSH hBrush = Wnd->pcls->hbrBackground;
+         if (!hBrush) return 0;
+         if (hBrush <= (HBRUSH)COLOR_MENUBAR)
+         {
+            hBrush = IntGetSysColorBrush((INT)hBrush);
+         }
+         if (Wnd->pcls->style & CS_PARENTDC)
+         {
+            /* can't use GetClipBox with a parent DC or we fill the whole parent */
+            IntGetClientRect(Wnd, &Rect);
+            GreDPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
+         }
+         else
+         {
+            GdiGetClipBox((HDC)wParam, &Rect);
+         }
+         FillRect((HDC)wParam, &Rect, hBrush);
+         return (1);
+      }
+
       case WM_GETHOTKEY:
          //ERR("WM_GETHOTKEY\n");
          return DefWndGetHotKey(Wnd);
       case WM_GETHOTKEY:
          //ERR("WM_GETHOTKEY\n");
          return DefWndGetHotKey(Wnd);
@@ -331,6 +968,46 @@ IntDefWindowProc(
          return GetNCHitEx(Wnd, Point);
       }
 
          return GetNCHitEx(Wnd, Point);
       }
 
+      case WM_PRINT:
+      {
+         DefWndPrint(Wnd, (HDC)wParam, lParam);
+         return (0);
+      }
+
+      case WM_PAINTICON:
+      case WM_PAINT:
+      {
+         PAINTSTRUCT Ps;
+         HDC hDC;
+
+         /* If already in Paint and Client area is not empty just return. */
+         if (Wnd->state2 & WNDS2_STARTPAINT && !RECTL_bIsEmptyRect(&Wnd->rcClient))
+         {
+            ERR("In Paint and Client area is not empty!\n");
+            return 0;
+         }
+
+         hDC = IntBeginPaint(Wnd, &Ps);
+         if (hDC)
+         {
+             HICON hIcon;
+             if (((Wnd->style & WS_MINIMIZE) != 0) && (hIcon = Wnd->pcls->hIcon))
+             {
+                 RECT ClientRect;
+                 INT x, y;
+                 PCURICON_OBJECT pIcon;
+                 if (!(pIcon = UserGetCurIconObject(hIcon))) return 0;
+                 ERR("Doing Paint and Client area is empty!\n");
+                 IntGetClientRect(Wnd, &ClientRect);
+                 x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2;
+                 y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2;
+                 UserDrawIconEx( hDC, x, y, pIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );
+             }
+             IntEndPaint(Wnd, &Ps);
+         }
+         return (0);
+      }
+
       case WM_SYNCPAINT:
       {
          HRGN hRgn;
       case WM_SYNCPAINT:
       {
          HRGN hRgn;
@@ -430,7 +1107,6 @@ HICON FASTCALL NC_IconForWindow( PWND pWnd )
    {
       if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
       if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
    {
       if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
       if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
-      hIcon = (HICON)1;
    }
    return hIcon;
 }
    }
    return hIcon;
 }