📄 nonclient.c
字号:
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 + -