无法在 WM_NCPAINT 上的标题栏中绘制?
Can't draw in title bar on WM_NCPAINT?
我试图在标题栏区域绘制一些东西来表示 X,因为没有 WS_CAPTION
,它只使用 WS_EX_TOOLWINDOW | WS_EX_TOPMOST
和 WS_POPUP|WS_THICKFRAME
。但是我无法在任何地方画任何东西。我在下面做了一个测试,把它全部填成红色,但没有任何改变。我做错了什么或遗漏了什么?
case WM_NCACTIVATE:
case WM_NCPAINT:
{
// call default handler (I've tried it both ways, with and without DefWindowProc)
::DefWindowProc(hwnd, umsg, wparam, lparam);
HDC hdc;
if ((hdc=::GetWindowDC(hwnd))!=NULL) {
// Paint into this DC
RECT rcwin;
if (::GetWindowRect(hwnd, &rcwin)) {
HBRUSH hbrush=::CreateSolidBrush(RGB(255, 0, 0));
if (hbrush) {
rcwin.right-=rcwin.left;
rcwin.bottom-=rcwin.top;
rcwin.left=rcwin.top=0;
::FillRect(hdc, &rcwin, hbrush);
::DeleteObject(hbrush);
}
}
::ReleaseDC(hwnd, hdc);
}
return 0;
}
不要直接在WM_NCACTIVATE
中绘制。如果你需要触发重绘,你可以使用 RedrawWindow()
。在 WM_PAINT
/WM_NCPAINT
.
中完成所有实际绘图
在WM_NCPAINT
中绘图时,documentation says to use GetDCEx()
to get the HDC
to draw on. The wParam
is an HRGN
that you can draw within. You can use GetRgnBox()
获取HRGN
的外接矩形,如果需要的话。
case WM_NCPAINT: {
::DefWindowProc(hwnd, umsg, wparam, lparam);
HRGN hrgn = (HRGN)wParam;
HDC hdc = ::GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN);
HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
::FillRgn(hdc, hrgn, hbrush);
::DeleteObject(hbrush);
::ReleaseDC(hwnd, hdc);
return 0;
}
基于 Remy 的 Link 关于邪恶 WM_NCPAINT 的文章,从 pascal 版本转换为下面的 C++ 版本。它与 Whosebug 中的 link 一样有效,但同样,仅当提供 WS_CAPTION
时。我只是为了完整性而在这里发帖。
case WM_NCPAINT:
{
#ifndef DCX_USESTYLE
#define DCX_USESTYLE 0x00010000
#endif
HDC hdc=::GetDCEx(hwnd, 0, DCX_WINDOW|DCX_USESTYLE);
if (hdc) {
RECT rcclient;
::GetClientRect(hwnd, &rcclient);
RECT rcwin;
::GetWindowRect(hwnd, &rcwin);
POINT ptupleft;
ptupleft.x=rcwin.left;
ptupleft.y=rcwin.top;
::MapWindowPoints(0, 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);
}
HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
::FillRect(hdc, &rcwin, hbrush);
::DeleteObject(hbrush);
::ReleaseDC(hwnd, hdc);
if (rgntemp!=0) {
::DeleteObject(rgntemp);
}
}
return 0;
}
我试图在标题栏区域绘制一些东西来表示 X,因为没有 WS_CAPTION
,它只使用 WS_EX_TOOLWINDOW | WS_EX_TOPMOST
和 WS_POPUP|WS_THICKFRAME
。但是我无法在任何地方画任何东西。我在下面做了一个测试,把它全部填成红色,但没有任何改变。我做错了什么或遗漏了什么?
case WM_NCACTIVATE:
case WM_NCPAINT:
{
// call default handler (I've tried it both ways, with and without DefWindowProc)
::DefWindowProc(hwnd, umsg, wparam, lparam);
HDC hdc;
if ((hdc=::GetWindowDC(hwnd))!=NULL) {
// Paint into this DC
RECT rcwin;
if (::GetWindowRect(hwnd, &rcwin)) {
HBRUSH hbrush=::CreateSolidBrush(RGB(255, 0, 0));
if (hbrush) {
rcwin.right-=rcwin.left;
rcwin.bottom-=rcwin.top;
rcwin.left=rcwin.top=0;
::FillRect(hdc, &rcwin, hbrush);
::DeleteObject(hbrush);
}
}
::ReleaseDC(hwnd, hdc);
}
return 0;
}
不要直接在WM_NCACTIVATE
中绘制。如果你需要触发重绘,你可以使用 RedrawWindow()
。在 WM_PAINT
/WM_NCPAINT
.
在WM_NCPAINT
中绘图时,documentation says to use GetDCEx()
to get the HDC
to draw on. The wParam
is an HRGN
that you can draw within. You can use GetRgnBox()
获取HRGN
的外接矩形,如果需要的话。
case WM_NCPAINT: {
::DefWindowProc(hwnd, umsg, wparam, lparam);
HRGN hrgn = (HRGN)wParam;
HDC hdc = ::GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN);
HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
::FillRgn(hdc, hrgn, hbrush);
::DeleteObject(hbrush);
::ReleaseDC(hwnd, hdc);
return 0;
}
基于 Remy 的 Link 关于邪恶 WM_NCPAINT 的文章,从 pascal 版本转换为下面的 C++ 版本。它与 Whosebug 中的 link 一样有效,但同样,仅当提供 WS_CAPTION
时。我只是为了完整性而在这里发帖。
case WM_NCPAINT:
{
#ifndef DCX_USESTYLE
#define DCX_USESTYLE 0x00010000
#endif
HDC hdc=::GetDCEx(hwnd, 0, DCX_WINDOW|DCX_USESTYLE);
if (hdc) {
RECT rcclient;
::GetClientRect(hwnd, &rcclient);
RECT rcwin;
::GetWindowRect(hwnd, &rcwin);
POINT ptupleft;
ptupleft.x=rcwin.left;
ptupleft.y=rcwin.top;
::MapWindowPoints(0, 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);
}
HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
::FillRect(hdc, &rcwin, hbrush);
::DeleteObject(hbrush);
::ReleaseDC(hwnd, hdc);
if (rgntemp!=0) {
::DeleteObject(rgntemp);
}
}
return 0;
}