C++ 如何正确绘制简单的非客户区(4像素红色边框)?
我正在尝试绘制一个自定义绘制的非客户端区域,而不是默认的主题边框(Windows10) 我处理了C++ 如何正确绘制简单的非客户区(4像素红色边框)?,c++,winapi,nonclient-area,C++,Winapi,Nonclient Area,我正在尝试绘制一个自定义绘制的非客户端区域,而不是默认的主题边框(Windows10) 我处理了WM\u NCCALCSIZE以将非客户端区域的大小调整为每侧4个像素,然后处理了WM\u NCPAINT以绘制红色边框 我的自定义绘制在应用程序首次显示时成功,但在应用程序调整大小或最小化并还原时无法重新绘制,尽管在调整大小或恢复窗口时调用了WM\u NCCALCSIZE和WM\u NCPAINT #pragma comment(lib, "UxTheme") #include <window
WM\u NCCALCSIZE
以将非客户端区域的大小调整为每侧4个像素,然后处理了WM\u NCPAINT
以绘制红色边框
我的自定义绘制在应用程序首次显示时成功,但在应用程序调整大小或最小化并还原时无法重新绘制,尽管在调整大小或恢复窗口时调用了WM\u NCCALCSIZE
和WM\u NCPAINT
#pragma comment(lib, "UxTheme")
#include <windows.h>
#include <uxtheme.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0,128,0));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "window";
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(
WS_EX_COMPOSITED,
"window",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
SetWindowTheme(hWnd, L"", L"");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_NCCALCSIZE:
{
RECT rect;
GetWindowRect(hWnd, &rect);
LPNCCALCSIZE_PARAMS ncParams = (LPNCCALCSIZE_PARAMS) lParam;
ncParams->rgrc[0].top = rect.top + 4;
ncParams->rgrc[0].left = rect.left + 4;
ncParams->rgrc[0].bottom = rect.bottom - 4;
ncParams->rgrc[0].right = rect.right - 4;
return 0;
}
case WM_NCPAINT:
{
RECT rect;
GetWindowRect(hWnd, &rect);
HDC dc = GetDCEx(hWnd, (HRGN) wParam, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
HPEN pen = CreatePen(PS_INSIDEFRAME, 4, RGB(255, 0, 0));
HGDIOBJ old = SelectObject(dc, pen);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Rectangle(dc, 0, 0, width, height);
SelectObject(dc, old);
DeleteObject(pen);
ReleaseDC(hWnd, dc);
return 0;
}
case WM_NCACTIVATE:
RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
#pragma注释(lib,“UxTheme”)
#包括
#包括
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、LPSTR lpCmdLine、int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=NULL;
wcex.hCursor=(HICON)LoadCursor(空,IDC_箭头);
wcex.hbrBackground=CreateSolidBrush(RGB(0128,0));
wcex.lpszMenuName=NULL;
wcex.lpszClassName=“窗口”;
wcex.hIconSm=NULL;
注册类别(&wcex);
HWND HWND=CreateWindowEx(
WS_EX_合成,
“窗口”,
无效的
WS_重叠窗口,
100,
100,
600,
400,
无效的
无效的
hInstance,
无效);
显示窗口(hWnd、nCmdShow);
味精;
while(GetMessage(&msg,NULL,0,0)){
翻译信息(&msg);
发送消息(&msg);
}
返回静态_cast(msg.wParam);
}
LRESULT回调WndProc(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg){
案例WM_创建:
设置窗口主题(hWnd,L“”,L“”);
返回0;
案例WM_销毁:
PostQuitMessage(0);
返回0;
案例WM_NCCALCSIZE:
{
RECT-RECT;
GetWindowRect(hWnd和&rect);
LPNCCALCSIZE_参数ncParams=(LPNCCALCSIZE_参数)lParam;
ncParams->rgrc[0]。top=rect.top+4;
ncParams->rgrc[0]。left=rect.left+4;
ncParams->rgrc[0]。bottom=rect.bottom-4;
ncParams->rgrc[0]。right=rect.right-4;
返回0;
}
案例WM_NCPAINT:
{
RECT-RECT;
GetWindowRect(hWnd和&rect);
HDC dc=GetDCEx(hWnd,(HRGN)wParam,DCX_窗口| DCX_缓存| DCX_交叉点rgn | DCX_锁窗口更新);
HPEN pen=CreatePen(PS_INSIDEFRAME,4,RGB(255,0,0));
HGDIOBJ old=选择对象(直流、笔);
int width=rect.right-rect.left;
int height=rect.bottom-rect.top;
矩形(dc、0、0、宽度、高度);
选择对象(dc,旧);
删除对象(笔);
释放dc(hWnd,dc);
返回0;
}
案例WM_n激活:
重画窗口(hWnd、NULL、NULL、RDW_UPDATENOW);
返回0;
打破
}
返回DefWindowProc(hWnd、uMsg、wParam、lParam);
}
WM\u NCPAINT
消息的wParam
有时返回1而不是区域的句柄(HRGN
)。在这种情况下,必须使用CreateRectRgn
函数创建HRGN
#pragma comment(lib, "UxTheme")
#include <windows.h>
#include <uxtheme.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0,128,0));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "window";
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(
NULL,
"window",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
SetWindowTheme(hWnd, L"", L"");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_NCCALCSIZE:
{
LPNCCALCSIZE_PARAMS ncParams = (LPNCCALCSIZE_PARAMS) lParam;
ncParams->rgrc[0].top += 4;
ncParams->rgrc[0].left += 4;
ncParams->rgrc[0].bottom -= 4;
ncParams->rgrc[0].right -= 4;
return 0;
}
case WM_NCPAINT:
{
RECT rect;
GetWindowRect(hWnd, &rect);
HRGN region = NULL;
if (wParam == NULLREGION) {
region = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
} else {
HRGN copy = CreateRectRgn(0, 0, 0, 0);
if (CombineRgn(copy, (HRGN) wParam, NULL, RGN_COPY)) {
region = copy;
} else {
DeleteObject(copy);
}
}
HDC dc = GetDCEx(hWnd, region, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
if (!dc && region) {
DeleteObject(region);
}
HPEN pen = CreatePen(PS_INSIDEFRAME, 4, RGB(255, 0, 0));
HGDIOBJ old = SelectObject(dc, pen);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Rectangle(dc, 0, 0, width, height);
SelectObject(dc, old);
ReleaseDC(hWnd, dc);
DeleteObject(pen);
return 0;
}
case WM_NCACTIVATE:
RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
#pragma注释(lib,“UxTheme”)
#包括
#包括
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、LPSTR lpCmdLine、int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=NULL;
wcex.hCursor=(HICON)LoadCursor(空,IDC_箭头);
wcex.hbrBackground=CreateSolidBrush(RGB(0128,0));
wcex.lpszMenuName=NULL;
wcex.lpszClassName=“窗口”;
wcex.hIconSm=NULL;
注册类别(&wcex);
HWND HWND=CreateWindowEx(
无效的
“窗口”,
无效的
WS_重叠窗口,
100,
100,
600,
400,
无效的
无效的
hInstance,
无效);
显示窗口(hWnd、nCmdShow);
味精;
while(GetMessage(&msg,NULL,0,0)){
翻译信息(&msg);
发送消息(&msg);
}
返回静态_cast(msg.wParam);
}
LRESULT回调WndProc(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg){
案例WM_创建:
设置窗口主题(hWnd,L“”,L“”);
返回0;
案例WM_销毁:
PostQuitMessage(0);
返回0;
案例WM_NCCALCSIZE:
{
LPNCCALCSIZE_参数ncParams=(LPNCCALCSIZE_参数)lParam;
ncParams->rgrc[0]。顶部+=4;
ncParams->rgrc[0]。左+=4;
ncParams->rgrc[0]。底部-=4;
ncParams->rgrc[0]。右-=4;
返回0;
}
案例WM_NCPAINT:
{
RECT-RECT;
GetWindowRect(hWnd和&rect);
HRGN区域=空;
if(wParam==NULLREGION){
region=CreateRectRgn(rect.left、rect.top、rect.right、rect.bottom);
}否则{
HRGN copy=CreateRectRgn(0,0,0,0);
if(CombineRgn(复制,(HRGN)wParam,NULL,RGN_复制)){
区域=复制;
}否则{
删除对象(副本);
}
}
HDC dc=GetDCEx(hWnd,region,DCX_窗口| DCX_缓存| DCX_INTERSECTRGN | DCX_锁窗口更新);
如果(!dc&&区域){
删除对象(区域);
}
HPEN pen=CreatePen(PS_INSIDEFRAME,4,RGB(255,0,0));
HGDIOBJ old=选择对象(直流、笔);
int wid