[NtUser]
[reactos.git] / reactos / win32ss / user / ntuser / nonclient.c
index 325c17b..3ce9cff 100644 (file)
@@ -67,7 +67,7 @@ UserDrawMovingFrame(HDC hdc,
  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
  * but without the borders (if any).
  */
-void FASTCALL
+void FASTCALL // Previously known as "UserGetInsideRectNC"
 NC_GetInsideRect(PWND Wnd, RECT *rect)
 {
     ULONG Style;
@@ -83,27 +83,22 @@ NC_GetInsideRect(PWND Wnd, RECT *rect)
     if (Style & WS_ICONIC) return;
 
     /* Remove frame from rectangle */
-    if (UserHasThickFrameStyle(Style, ExStyle ))
+    if (UserHasThickFrameStyle(Style, ExStyle))
     {
         RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
     }
-    else
+    else if (UserHasDlgFrameStyle(Style, ExStyle))
     {
-        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));
-            }
-        }
+        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))
@@ -219,6 +214,7 @@ DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
                case VK_ESCAPE:
                  return 0;
                }
+              break;
             default:
               IntTranslateKbdMessage( &msg, 0 );
               pti->TIF_flags |= TIF_MOVESIZETRACKING;
@@ -477,7 +473,12 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
                      UserDrawMovingFrame( hdc, &newRect, thickframe );
                  else
                  {  // Moving the whole window now!
-                    PWND pwndTemp;
+                    HRGN hrgnNew;
+                    HRGN hrgnOrig = GreCreateRectRgnIndirect(&pwnd->rcWindow);
+
+                    if (pwnd->hrgnClip != NULL)
+                       NtGdiCombineRgn(hrgnOrig, hrgnOrig, pwnd->hrgnClip, RGN_AND);
+
                     //// This causes the mdi child window to jump up when it is moved.
                     //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
                    co_WinPosSetWindowPos( pwnd,
@@ -488,18 +489,29 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
                                           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 )
+                    hrgnNew = GreCreateRectRgnIndirect(&pwnd->rcWindow);
+                    if (pwnd->hrgnClip != NULL)
+                       NtGdiCombineRgn(hrgnNew, hrgnNew, pwnd->hrgnClip, RGN_AND);
+
+                    if (hrgnNew)
+                    {
+                       if (hrgnOrig)
+                          NtGdiCombineRgn(hrgnOrig, hrgnOrig, hrgnNew, RGN_DIFF);
+                    }
+                    else
                     {
-                       RECTL rect;
-                       // Only the windows that overlap will be redrawn.
-                       if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
+                       if (hrgnOrig)
                        {
-                          co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_NOCHILDREN);
+                          GreDeleteObject(hrgnOrig);
+                          hrgnOrig = 0;
                        }
                     }
+
+                    // Update all the windows after the move or size, including this window.
+                    UpdateThreadWindows(UserGetDesktopWindow()->spwndChild, pti, hrgnOrig);
+
+                    if (hrgnOrig) GreDeleteObject(hrgnOrig);
+                    if (hrgnNew) GreDeleteObject(hrgnNew);
                  }
               }
               sizingRect = newRect;
@@ -601,31 +613,27 @@ PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
     PCURICON_OBJECT pIcon = NULL;
     HICON hIcon;
 
-   //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
-   //FIXME: Hence we must return a pointer with no reference count.
-   //FIXME: This is bad and we should feel bad.
-   //FIXME: Stop whining over wine code.
-
-   hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
-   if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
+   hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp, TRUE);
+   if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp, TRUE);
 
    if (!hIcon && pWnd->pcls->spicnSm)
        return pWnd->pcls->spicnSm;
    if (!hIcon && pWnd->pcls->spicn)
        return pWnd->pcls->spicn;
 
-   if (!hIcon && (pWnd->style & DS_MODALFRAME))
+   // WARNING: Wine code has this test completely wrong. The following is how
+   // Windows behaves for windows having the WS_EX_DLGMODALFRAME style set:
+   // it does not use the default icon! And it does not check for DS_MODALFRAME.
+   if (!hIcon && !(pWnd->ExStyle & WS_EX_DLGMODALFRAME))
    {
       if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
       if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
    }
    if (hIcon)
    {
-       pIcon = UserGetCurIconObject(hIcon);
-       if (pIcon)
-       {
-           UserDereferenceObject(pIcon);
-       }
+       pIcon = (PCURICON_OBJECT)UserGetObjectNoErr(gHandleTable,
+                                                   hIcon,
+                                                   TYPE_CURSOR);
    }
    return pIcon;
 }
@@ -640,70 +648,19 @@ UserDrawSysMenuButton(PWND pWnd, HDC hDC, LPRECT Rect, BOOL Down)
    {
       UserReferenceObject(WindowIcon);
 
-      Ret = UserDrawIconEx( hDC,
-                            Rect->left + 2,
-                            Rect->top + 2,
-                            WindowIcon,
-                            UserGetSystemMetrics(SM_CXSMICON),
-                            UserGetSystemMetrics(SM_CYSMICON),
-                            0, NULL, DI_NORMAL);
+      Ret = UserDrawIconEx(hDC,
+                           Rect->left + 2,
+                           Rect->top + 2,
+                           WindowIcon,
+                           UserGetSystemMetrics(SM_CXSMICON),
+                           UserGetSystemMetrics(SM_CYSMICON),
+                           0, NULL, DI_NORMAL);
 
       UserDereferenceObject(WindowIcon);
    }
    return Ret;
 }
 
-void
-UserGetInsideRectNC(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));
-    }
-}
-
 BOOL
 IntIsScrollBarVisible(PWND pWnd, INT hBar)
 {
@@ -716,17 +673,11 @@ IntIsScrollBarVisible(PWND pWnd, INT hBar)
   return !(sbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN);
 }
 
-BOOL
-UserHasMenu(PWND pWnd, ULONG Style)
-{
-   return (!(Style & WS_CHILD) && UlongToHandle(pWnd->IDMenu) != 0);
-}
-
 /*
  * FIXME:
  * - Cache bitmaps, then just bitblt instead of calling DFC() (and
  *   wasting precious CPU cycles) every time
- * - Center the buttons verticaly in the rect
+ * - Center the buttons vertically in the rect
  */
 VOID
 UserDrawCaptionButton(PWND pWnd, LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hDC, BOOL bDown, ULONG Type)
@@ -788,8 +739,7 @@ UserDrawCaptionButton(PWND pWnd, LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hD
           PMENU pSysMenu = IntGetSystemMenu(pWnd, FALSE);
           UINT MenuState = IntGetMenuState(UserHMGetHandle(pSysMenu), SC_CLOSE, MF_BYCOMMAND); /* in case of error MenuState==0xFFFFFFFF */
 
-         /* FIXME: A tool window has a smaller Close button */
-
+         /* A tool window has a smaller Close button */
          if (ExStyle & WS_EX_TOOLWINDOW)
          {
             TempRect.left = TempRect.right - UserGetSystemMetrics(SM_CXSMSIZE);
@@ -890,7 +840,7 @@ VOID UserDrawCaptionBar(
 
    if (!(Flags & DC_NOVISIBLE) && !IntIsWindowVisible(pWnd)) return;
 
-   ERR("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd, hDC, Flags);
+   TRACE("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd, hDC, Flags);
 
    Style = pWnd->style;
    ExStyle = pWnd->ExStyle;
@@ -950,9 +900,8 @@ VOID UserDrawCaptionBar(
       }
 
       if (!(Flags & DC_ICON)               &&
-           (Style & WS_SYSMENU)            &&
           !(Flags & DC_SMALLCAP)           &&
-          !(ExStyle & WS_EX_DLGMODALFRAME) && 
+           (Style & WS_SYSMENU)            &&
           !(ExStyle & WS_EX_TOOLWINDOW) )
       {
          pIcon = NC_IconForWindow(pWnd); // Force redraw of caption with icon if DC_ICON not flaged....
@@ -988,6 +937,15 @@ VOID UserDrawCaptionBar(
 
    if (!(Style & WS_MINIMIZE))
    {
+      /* Draw menu bar */
+      if (pWnd->state & WNDS_HASMENU && pWnd->IDMenu) // Should be pWnd->spmenu
+      {
+          PMENU menu = UserGetMenuObject(UlongToHandle(pWnd->IDMenu)); // FIXME!
+          TempRect = CurrentRect;
+          TempRect.bottom = TempRect.top + menu->cyMenu; // Should be pWnd->spmenu->cyMenu;
+          CurrentRect.top += MENU_DrawMenuBar(hDC, &TempRect, pWnd, FALSE);
+      }
+
       if (ExStyle & WS_EX_CLIENTEDGE)
       {
           DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
@@ -1014,7 +972,6 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
    PWND Parent;
    RECT WindowRect, CurrentRect, TempRect;
    BOOL Active = FALSE;
-   PCURICON_OBJECT pIcon = NULL;
 
    if (!IntIsWindowVisible(pWnd) ||
        (pWnd->state & WNDS_NONCPAINT && !(pWnd->state & WNDS_FORCEMENUDRAW)) ||
@@ -1041,9 +998,11 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
       {
          Active = (gpqForeground == pWnd->head.pti->MessageQueue);
       }
+      Flags = DC_NC; // Redraw everything!
    }
+   else
+      Flags |= DC_NC;
 
-   Flags = DC_NC; // Redraw everything!
 
    IntGetWindowRect(pWnd, &WindowRect);
 
@@ -1094,11 +1053,12 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
 
       if (Active)
       {
-         if (!(pWnd->state & WNDS_ACTIVEFRAME))
+         if (pWnd->state & WNDS_ACTIVEFRAME)
+            Flags |= DC_ACTIVE;
+         else
          {
             ERR("Wnd is active and not set active!\n");
          }
-         Flags |= DC_ACTIVE;
       }
 
       TempRect = CurrentRect;
@@ -1115,7 +1075,7 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
          CurrentRect.top += UserGetSystemMetrics(SM_CYCAPTION);
       }
 
-      UserDrawCaption(pWnd, hDC, &TempRect, NULL, pIcon ? UserHMGetHandle(pIcon) : NULL, NULL, Flags);
+      UserDrawCaption(pWnd, hDC, &TempRect, NULL, NULL, NULL, Flags);
 
       /* Draw buttons */
       if (Style & WS_SYSMENU)
@@ -1146,13 +1106,16 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
 
    if (!(Style & WS_MINIMIZE))
    {
-     PMENU menu = UserGetMenuObject(UlongToHandle(pWnd->IDMenu));
      /* Draw menu bar */
-     if (menu && !(Style & WS_CHILD))
+     if (pWnd->state & WNDS_HASMENU && pWnd->IDMenu) // Should be pWnd->spmenu
      {
-         TempRect = CurrentRect;
-         TempRect.bottom = TempRect.top + menu->cyMenu;
-         CurrentRect.top += MENU_DrawMenuBar(hDC, &TempRect, pWnd, FALSE);
+         if (!(Flags & DC_NOSENDMSG))
+         {
+             PMENU menu = UserGetMenuObject(UlongToHandle(pWnd->IDMenu)); // FIXME!
+             TempRect = CurrentRect;
+             TempRect.bottom = TempRect.top + menu->cyMenu; // Should be pWnd->spmenu->cyMenu;
+             CurrentRect.top += MENU_DrawMenuBar(hDC, &TempRect, pWnd, FALSE);
+         }
      }
 
      if (ExStyle & WS_EX_CLIENTEDGE)
@@ -1203,7 +1166,7 @@ NC_DoNCPaint(PWND pWnd, HDC hDC, INT Flags)
    return 0; // For WM_NCPAINT message, return 0.
 }
 
-LRESULT NC_HandleNCCalcSize( PWND Wnd, WPARAM wparam, RECTL *Rect )
+LRESULT NC_HandleNCCalcSize( PWND Wnd, WPARAM wparam, RECTL *Rect, BOOL Suspended )
 {
    LRESULT Result = 0;
    SIZE WindowBorders;
@@ -1253,7 +1216,7 @@ LRESULT NC_HandleNCCalcSize( PWND Wnd, WPARAM wparam, RECTL *Rect )
             Rect->top += UserGetSystemMetrics(SM_CYCAPTION);
       }
 
-      if (Wnd->IDMenu && ((Wnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD))
+      if (HAS_MENU(Wnd, Style))
       {
          HDC hDC = UserGetDCEx(Wnd, 0, DCX_USESTYLE | DCX_WINDOW);
 
@@ -1266,7 +1229,7 @@ LRESULT NC_HandleNCCalcSize( PWND Wnd, WPARAM wparam, RECTL *Rect )
            CliRect.right -= OrigRect.left;
            CliRect.left -= OrigRect.left;
            CliRect.top -= OrigRect.top;
-           Rect->top += MENU_DrawMenuBar(hDC, &CliRect, Wnd, TRUE);
+           if (!Suspended) Rect->top += MENU_DrawMenuBar(hDC, &CliRect, Wnd, TRUE);
            UserReleaseDC(Wnd, hDC, FALSE);
          }
       }
@@ -1408,8 +1371,8 @@ LRESULT NC_HandleNCActivate( PWND Wnd, WPARAM wParam, LPARAM lParam )
       wParam = DC_CAPTION;
    }
 
-   if (Wnd->state & WNDS_NONCPAINT || !(Wnd->style & WS_VISIBLE))
-      return 0;
+   if ((Wnd->state & WNDS_NONCPAINT) || !(Wnd->style & WS_VISIBLE))
+      return TRUE;
 
    /* This isn't documented but is reproducible in at least XP SP2 and
     * Outlook 2007 depends on it
@@ -1559,7 +1522,7 @@ NC_HandleNCLButtonDown(PWND pWnd, WPARAM wParam, LPARAM lParam)
               {
                 RECT rect;
                 HDC hDC = UserGetWindowDC(pWnd);
-                UserGetInsideRectNC(pWnd, &rect);
+                NC_GetInsideRect(pWnd, &rect);
                 UserDrawSysMenuButton(pWnd, hDC, &rect, TRUE);
                 UserReleaseDC( pWnd, hDC, FALSE );
               }
@@ -1691,6 +1654,229 @@ LRESULT NC_HandleNCRButtonDown( PWND pwnd, WPARAM wParam, LPARAM lParam )
 }
 
 
+#if 0 // Old version, kept there for reference, which is also used
+      // almost unmodified in uxtheme.dll (in nonclient.c)
+/*
+ * FIXME:
+ * - Check the scrollbar handling
+ */
+LRESULT
+DefWndNCHitTest(HWND hWnd, POINT Point)
+{
+   RECT WindowRect, ClientRect, OrigWndRect;
+   POINT ClientPoint;
+   SIZE WindowBorders;
+   DWORD Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
+   DWORD ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
+
+   GetWindowRect(hWnd, &WindowRect);
+   if (!PtInRect(&WindowRect, Point))
+   {
+      return HTNOWHERE;
+   }
+   OrigWndRect = WindowRect;
+
+   if (UserHasWindowEdge(Style, ExStyle))
+   {
+      LONG XSize, YSize;
+
+      UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
+      InflateRect(&WindowRect, -WindowBorders.cx, -WindowBorders.cy);
+      XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
+      YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
+      if (!PtInRect(&WindowRect, Point))
+      {
+         BOOL ThickFrame;
+
+         ThickFrame = (Style & WS_THICKFRAME);
+         if (Point.y < WindowRect.top)
+         {
+            if(Style & WS_MINIMIZE)
+              return HTCAPTION;
+            if(!ThickFrame)
+              return HTBORDER;
+            if (Point.x < (WindowRect.left + XSize))
+               return HTTOPLEFT;
+            if (Point.x >= (WindowRect.right - XSize))
+               return HTTOPRIGHT;
+            return HTTOP;
+         }
+         if (Point.y >= WindowRect.bottom)
+         {
+            if(Style & WS_MINIMIZE)
+              return HTCAPTION;
+            if(!ThickFrame)
+              return HTBORDER;
+            if (Point.x < (WindowRect.left + XSize))
+               return HTBOTTOMLEFT;
+            if (Point.x >= (WindowRect.right - XSize))
+               return HTBOTTOMRIGHT;
+            return HTBOTTOM;
+         }
+         if (Point.x < WindowRect.left)
+         {
+            if(Style & WS_MINIMIZE)
+              return HTCAPTION;
+            if(!ThickFrame)
+              return HTBORDER;
+            if (Point.y < (WindowRect.top + YSize))
+               return HTTOPLEFT;
+            if (Point.y >= (WindowRect.bottom - YSize))
+               return HTBOTTOMLEFT;
+            return HTLEFT;
+         }
+         if (Point.x >= WindowRect.right)
+         {
+            if(Style & WS_MINIMIZE)
+              return HTCAPTION;
+            if(!ThickFrame)
+              return HTBORDER;
+            if (Point.y < (WindowRect.top + YSize))
+               return HTTOPRIGHT;
+            if (Point.y >= (WindowRect.bottom - YSize))
+               return HTBOTTOMRIGHT;
+            return HTRIGHT;
+         }
+      }
+   }
+   else
+   {
+      if (ExStyle & WS_EX_STATICEDGE)
+         InflateRect(&WindowRect,
+            -GetSystemMetrics(SM_CXBORDER),
+            -GetSystemMetrics(SM_CYBORDER));
+      if (!PtInRect(&WindowRect, Point))
+         return HTBORDER;
+   }
+
+   if ((Style & WS_CAPTION) == WS_CAPTION)
+   {
+      if (ExStyle & WS_EX_TOOLWINDOW)
+         WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
+      else
+         WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
+      if (!PtInRect(&WindowRect, Point))
+      {
+         if (Style & WS_SYSMENU)
+         {
+            if (ExStyle & WS_EX_TOOLWINDOW)
+            {
+               WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE);
+            }
+            else
+            {
+               // if(!(ExStyle & WS_EX_DLGMODALFRAME))
+               // FIXME: The real test should check whether there is
+               // an icon for the system window, and if so, do the
+               // rect.left increase.
+               // See dll/win32/uxtheme/nonclient.c!DefWndNCHitTest
+               // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
+               // the test better.
+                  WindowRect.left += GetSystemMetrics(SM_CXSIZE);
+               WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
+            }
+         }
+         if (Point.x < WindowRect.left)
+            return HTSYSMENU;
+         if (WindowRect.right <= Point.x)
+            return HTCLOSE;
+         if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
+            WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
+         if (Point.x >= WindowRect.right)
+            return HTMAXBUTTON;
+         if (Style & WS_MINIMIZEBOX)
+            WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
+         if (Point.x >= WindowRect.right)
+            return HTMINBUTTON;
+         return HTCAPTION;
+      }
+   }
+
+   if(!(Style & WS_MINIMIZE))
+   {
+     ClientPoint = Point;
+     ScreenToClient(hWnd, &ClientPoint);
+     GetClientRect(hWnd, &ClientRect);
+
+     if (PtInRect(&ClientRect, ClientPoint))
+     {
+        return HTCLIENT;
+     }
+
+     if (GetMenu(hWnd) && !(Style & WS_CHILD))
+     {
+        if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
+           return HTMENU;
+     }
+
+     if (ExStyle & WS_EX_CLIENTEDGE)
+     {
+        InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
+           -2 * GetSystemMetrics(SM_CYBORDER));
+     }
+
+     if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
+         (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
+     {
+        RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
+        HWND Parent = GetParent(hWnd);
+
+        TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
+        if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+           TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
+        else
+           TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
+        if (PtInRect(&TempRect, Point))
+           return HTVSCROLL;
+
+        TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
+        if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+           TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
+        else
+           TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
+        if (PtInRect(&TempRect2, Point))
+           return HTHSCROLL;
+
+        TempRect.top = TempRect2.top;
+        TempRect.bottom = TempRect2.bottom;
+        if(Parent)
+          GetClientRect(Parent, &ParentRect);
+        if (PtInRect(&TempRect, Point) && HASSIZEGRIP(Style, ExStyle,
+            GetWindowLongPtrW(Parent, GWL_STYLE), OrigWndRect, ParentRect))
+        {
+           if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+              return HTBOTTOMLEFT;
+           else
+              return HTBOTTOMRIGHT;
+        }
+     }
+     else
+     {
+        if (Style & WS_VSCROLL)
+        {
+           RECT TempRect = WindowRect;
+
+           if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+              TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
+           else
+              TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
+           if (PtInRect(&TempRect, Point))
+              return HTVSCROLL;
+        } else
+        if (Style & WS_HSCROLL)
+        {
+           RECT TempRect = WindowRect;
+           TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
+           if (PtInRect(&TempRect, Point))
+              return HTHSCROLL;
+        }
+     }
+   }
+
+   return HTNOWHERE;
+}
+#endif
+
 DWORD FASTCALL
 GetNCHitEx(PWND pWnd, POINT pt)
 {
@@ -1764,6 +1950,8 @@ GetNCHitEx(PWND pWnd, POINT pt)
             RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
         else if (HAS_THINFRAME( Style, ExStyle ))
             RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+        else if (HAS_CLIENTFRAME( Style, ExStyle ))
+            RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
         if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y  )) return HTBORDER;
     }