#include <atlbase.h>
#include <atlwin.h>
#include <shellscalingapi.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
#pragma comment(lib, "Shcore.lib")
#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
const int kTitlebarHeight = 40;
class MainWindow : public CWindowImpl<MainWindow> {
public:
BEGIN_MSG_MAP(MainWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_NCCALCSIZE, OnNCCalcSize)
MESSAGE_HANDLER(WM_NCACTIVATE, OnNCActivate)
MESSAGE_HANDLER(WM_NCHITTEST, OnNCHitTest)
MESSAGE_HANDLER(WM_NCPAINT, OnNCPaint)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL&) {
ATLASSERT(GetStyle() & WS_THICKFRAME);
return 0;
}
LRESULT OnNCCalcSize(UINT uMsg, WPARAM wparam, LPARAM l_param, BOOL&) {
BOOL mode = wparam;
RECT* client_rect =
mode ? &(reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0])
: reinterpret_cast<RECT*>(l_param);
HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL);
if (!monitor) {
monitor = MonitorFromRect(client_rect, MONITOR_DEFAULTTONULL);
if (!monitor) {
return 0;
}
}
RECT insets;
if (GetClientAreaInsets(monitor, & insets)) {
client_rect->left += insets.left;
client_rect->top += insets.top;
client_rect->bottom -= insets.bottom;
client_rect->right -= insets.right;
}
return 0;
}
LRESULT OnNCActivate(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL& handled) {
RedrawWindow();
return 0;
}
LRESULT OnNCHitTest(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL& handled) {
POINT pt{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
::MapWindowPoints(HWND_DESKTOP, m_hWnd, &pt, 1);
if (pt.y <= kTitlebarHeight) {
return HTCAPTION;
}
return ::DefWindowProc(m_hWnd, WM_NCHITTEST, 0, lparam);
}
LRESULT OnNCPaint(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL& handled) {
HDC hdc = ::GetWindowDC(m_hWnd);
if (hdc) {
RECT rcclient;
::GetClientRect(m_hWnd, &rcclient);
RECT rcwin;
::GetWindowRect(m_hWnd, &rcwin);
POINT ptupleft;
ptupleft.x = rcwin.left;
ptupleft.y = rcwin.top;
::MapWindowPoints(0, m_hWnd, (LPPOINT)&rcwin,
(sizeof(RECT) / sizeof(POINT)));
::OffsetRect(&rcclient, -rcwin.left, -rcwin.top);
::OffsetRect(&rcwin, -rcwin.left, -rcwin.top);
HRGN rgntemp = NULL;
if (wparam == NULLREGION || wparam == ERROR) {
::ExcludeClipRect(hdc, rcclient.left, rcclient.top, rcclient.right,
rcclient.bottom);
} else {
rgntemp = ::CreateRectRgn(
rcclient.left + ptupleft.x, rcclient.top + ptupleft.y,
rcclient.right + ptupleft.x, rcclient.bottom + ptupleft.y);
if (::CombineRgn(rgntemp, (HRGN)wparam, rgntemp, RGN_DIFF) ==
NULLREGION) {
// nothing to paint
}
::OffsetRgn(rgntemp, -ptupleft.x, -ptupleft.y);
::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
}
::FillRect(hdc, &rcwin,
reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
::ReleaseDC(m_hWnd, hdc);
if (rgntemp != 0) {
::DeleteObject(rgntemp);
}
}
handled = FALSE;
return 0;
}
LRESULT OnPaint(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL&) {
PAINTSTRUCT ps;
HDC display_dc = ::BeginPaint(m_hWnd, &ps);
if (!IsRectEmpty(&ps.rcPaint)) {
HBRUSH brush = brush =
reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
::FillRect(ps.hdc, &ps.rcPaint, brush);
RECT rcclient;
GetClientRect(&rcclient);
RECT r{rcclient.left, rcclient.top, rcclient.right,
rcclient.top + kTitlebarHeight};
::FillRect(ps.hdc, &r,
reinterpret_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)));
}
::EndPaint(m_hWnd, &ps);
return 0;
}
LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wparam, LPARAM lparam, BOOL&) {
return 1;
}
LRESULT OnWindowPosChanged(UINT uMsg,
WPARAM wparam,
LPARAM lparam,
BOOL& handled) {
UpdateDwmFrame();
handled = false;
return 0;
}
bool GetClientAreaInsets(HMONITOR monitor, RECT* insets) const {
UINT monitor_dpi_x, monitor_dpi_y;
::GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &monitor_dpi_x,
&monitor_dpi_y);
const int frame_thickness =
::GetSystemMetricsForDpi(SM_CXSIZEFRAME, monitor_dpi_x) +
::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, monitor_dpi_x);
insets->left = frame_thickness;
insets->top = ::IsZoomed(m_hWnd) ? frame_thickness : 0;
insets->right = frame_thickness;
insets->bottom = frame_thickness;
return true;
}
void UpdateDwmFrame() {
MARGINS margins = {.cxLeftWidth = 0,
.cxRightWidth = 0,
.cyTopHeight = 0,
.cyBottomHeight = 0};
::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
}
};
int main(int argc, char** argv) {
MainWindow main_window;
RECT rc{
.left = 0,
.top = 0,
.right = 800,
.bottom = 600,
};
main_window.Create(nullptr, rc, nullptr, WS_OVERLAPPEDWINDOW | WS_THICKFRAME);
main_window.CenterWindow(::GetDesktopWindow());
main_window.ShowWindow(SW_NORMAL);
MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return 0;
}