⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nonclient.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
            GetWindowLongW(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;
}

VOID
DefWndDoButton(HWND hWnd, WPARAM wParam)
{
   MSG Msg;
   HDC WindowDC;
   BOOL Pressed = TRUE, OldState;
   WPARAM SCMsg;
   ULONG ButtonType, Style;

   Style = GetWindowLongW(hWnd, GWL_STYLE);
   switch (wParam)
   {
      case HTCLOSE:
         if (!(Style & WS_SYSMENU))
            return;
         ButtonType = DFCS_CAPTIONCLOSE;
         SCMsg = SC_CLOSE;
         break;
      case HTMINBUTTON:
         if (!(Style & WS_MINIMIZEBOX))
            return;
         ButtonType = DFCS_CAPTIONMIN;
         SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
         break;
      case HTMAXBUTTON:
         if (!(Style & WS_MAXIMIZEBOX))
            return;
         ButtonType = DFCS_CAPTIONMAX;
         SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
         break;

      default:
         ASSERT(FALSE);
         return;
   }

   /*
    * FIXME: Not sure where to do this, but we must flush the pending
    * window updates when someone clicks on the close button and at
    * the same time the window is overlapped with another one. This
    * looks like a good place for now...
    */
   UpdateWindow(hWnd);

   WindowDC = GetWindowDC(hWnd);
   UserDrawCaptionButtonWnd(hWnd, WindowDC, TRUE, ButtonType);

   SetCapture(hWnd);

   for (;;)
   {
      if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
         break;

      if (Msg.message == WM_LBUTTONUP)
         break;

      if (Msg.message != WM_MOUSEMOVE)
         continue;

      OldState = Pressed;
      Pressed = (DefWndNCHitTest(hWnd, Msg.pt) == wParam);
      if (Pressed != OldState)
         UserDrawCaptionButtonWnd(hWnd, WindowDC, Pressed, ButtonType);
   }

   if (Pressed)
      UserDrawCaptionButtonWnd(hWnd, WindowDC, FALSE, ButtonType);
   ReleaseCapture();
   ReleaseDC(hWnd, WindowDC);
   if (Pressed)
      SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
}


LRESULT
DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
        case HTCAPTION:
        {
	        HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
	        if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
	        {
	            SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
	        }
	        break;
        }
        case HTSYSMENU:
        {
	  if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
            {
	      SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
			   lParam);
	    }
	  break;
        }
        case HTMENU:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
            break;
        }
        case HTHSCROLL:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
            break;
        }
        case HTVSCROLL:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
            break;
        }
        case HTMINBUTTON:
        case HTMAXBUTTON:
        case HTCLOSE:
        {
          DefWndDoButton(hWnd, wParam);
          break;
        }
        case HTLEFT:
        case HTRIGHT:
        case HTTOP:
        case HTBOTTOM:
        case HTTOPLEFT:
        case HTTOPRIGHT:
        case HTBOTTOMLEFT:
        case HTBOTTOMRIGHT:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT - WMSZ_LEFT), lParam);
            break;
        }
    }
    return(0);
}


LRESULT
DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  ULONG Style;

  Style = GetWindowLongW(hWnd, GWL_STYLE);
  switch(wParam)
  {
    case HTCAPTION:
    {
      /* Maximize/Restore the window */
      if((Style & WS_CAPTION) == WS_CAPTION && (Style & WS_MAXIMIZEBOX))
      {
        SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
      }
      break;
    }
    case HTSYSMENU:
    {
      SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
      break;
    }
    default:
      return DefWndNCLButtonDown(hWnd, wParam, lParam);
  }
  return(0);
}

VOID
DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point)
{
   INT ScrollBar;

   if ((wParam & 0xfff0) == SC_HSCROLL)
   {
      if ((wParam & 0x0f) != HTHSCROLL)
         return;
      ScrollBar = SB_HORZ;
   }
   else
   {
      if ((wParam & 0x0f) != HTVSCROLL)
         return;
      ScrollBar = SB_VERT;
   }

   /* FIXME */
}

/* PUBLIC FUNCTIONS ***********************************************************/

/*
 * @implemented
 */
BOOL STDCALL
AdjustWindowRectEx(LPRECT lpRect,
		   DWORD dwStyle,
		   BOOL bMenu,
		   DWORD dwExStyle)
{
   SIZE BorderSize;

   if (bMenu)
   {
      lpRect->top -= GetSystemMetrics(SM_CYMENU);
   }
   if ((dwStyle & WS_CAPTION) == WS_CAPTION)
   {
      if (dwExStyle & WS_EX_TOOLWINDOW)
         lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
      else
         lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
   }
   UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
   InflateRect(
      lpRect,
      BorderSize.cx,
      BorderSize.cy);

   return TRUE;
}


/*
 * @implemented
 */
BOOL STDCALL
AdjustWindowRect(LPRECT lpRect,
		 DWORD dwStyle,
		 BOOL bMenu)
{
   return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
}

// Enabling this will cause captions to draw smoother, but slower:
#define DOUBLE_BUFFER_CAPTION

/*
 * @implemented
 */
BOOL WINAPI
DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
{
 return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
}

/*
 * @implemented
 */
BOOL
STDCALL
DrawCaptionTempW(
		 HWND        hWnd,
		 HDC         hDC,
		 const RECT *rect,
		 HFONT       hFont,
		 HICON       hIcon,
		 LPCWSTR     str,
		 UINT        uFlags
		 )
{
   UNICODE_STRING Text = {0};
   RtlInitUnicodeString(&Text, str);
   return NtUserDrawCaptionTemp(hWnd, hDC, rect, hFont, hIcon, &Text, uFlags);
}

/*
 * @implemented
 */
BOOL
STDCALL
DrawCaptionTempA(
		 HWND        hwnd,
		 HDC         hdc,
		 const RECT *rect,
		 HFONT       hFont,
		 HICON       hIcon,
		 LPCSTR      str,
		 UINT        uFlags
		 )
{
  LPWSTR strW;
  INT len;
  BOOL ret = FALSE;

  if (!(uFlags & DC_TEXT) || !str)
    return DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, NULL, uFlags);

  len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
  if ((strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
  {
    MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len );
    ret = DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
    HeapFree(GetProcessHeap(), 0, strW);
  }
  return ret;
}

/***********************************************************************
 *           NcGetInsideRect
 *
 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
 * but without the borders (if any).
 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
 */
static void FASTCALL
NcGetInsideRect(HWND Wnd, RECT *Rect)
{
  DWORD Style;
  DWORD ExStyle;

  GetWindowRect(Wnd, Rect);
  Rect->right = Rect->right - Rect->left;
  Rect->left = 0;
  Rect->bottom = Rect->bottom - Rect->top;
  Rect->top = 0;

  Style = GetWindowLongW(Wnd, GWL_STYLE);
  if (0 != (Style & WS_ICONIC))
    {
      return;
    }

  /* Remove frame from rectangle */
  ExStyle = GetWindowLongW(Wnd, GWL_EXSTYLE);
  if (HAS_THICKFRAME(Style, ExStyle))
    {
      InflateRect(Rect, - GetSystemMetrics(SM_CXFRAME), - GetSystemMetrics(SM_CYFRAME));
    }
  else if (HAS_DLGFRAME(Style, ExStyle))
    {
      InflateRect(Rect, - GetSystemMetrics(SM_CXDLGFRAME), - GetSystemMetrics(SM_CYDLGFRAME));
    }
  else if (HAS_THINFRAME(Style, ExStyle))
    {
      InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
    }

  /* We have additional border information if the window
   * is a child (but not an MDI child) */
  if (0 != (Style & WS_CHILD)
      && 0 == (ExStyle & WS_EX_MDICHILD))
    {
      if (0 != (ExStyle & WS_EX_CLIENTEDGE))
        {
          InflateRect(Rect, - GetSystemMetrics(SM_CXEDGE), - GetSystemMetrics(SM_CYEDGE));
        }
      if (0 != (ExStyle & WS_EX_STATICEDGE))
        {
          InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
        }
    }
}

/***********************************************************************
 *           NcGetSysPopupPos
 */
void FASTCALL
NcGetSysPopupPos(HWND Wnd, RECT *Rect)
{
  RECT WindowRect;

  if (IsIconic(Wnd))
    {
      GetWindowRect(Wnd, Rect);
    }
  else
    {
      NcGetInsideRect(Wnd, Rect);
      GetWindowRect(Wnd, &WindowRect);
      OffsetRect(Rect, WindowRect.left, WindowRect.top);
      if (0 != (GetWindowLongW(Wnd, GWL_STYLE) & WS_CHILD))
        {
          ClientToScreen(GetParent(Wnd), (POINT *) Rect);
        }
      Rect->right = Rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
      Rect->bottom = Rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -