DwmDefWindowProc
başlık düğmeler işlemek için gereklidir. başlığı düğme isabet testi için msdn:
itibaren DWM DwmDefWindowProc
fonksiyonunu sağlar. Özel çerçeve senaryolarında altyazı düğmelerini uygun bir şekilde sınamak için, iletilerin ilk olarak kullanımı için DwmDefWindowProc
'a geçirilmesi gerekir. DwmDefWindowProc
, bir ileti işlendiyse ve FALSE
değilse TRUE
döndürür. İleti, DwmDefWindowProc
, tarafından işlenmezse, uygulamanız iletinin kendisini işlemeli veya iletisini DefWindowProc
'a iletmelidir. aşağıdaki gibi
MFC dışarı çalışabilirsiniz:
LRESULT cframeWnd::OnNcHitTest(CPoint p)
{
BOOL dwm_enabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled)))
{
LRESULT result = 0;
if (!DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(p.x, p.y), &result))
result = HitTestNCA(m_hWnd, p);
if (result == HTNOWHERE && GetForegroundWindow() != this)
{
return HTCAPTION;
}
return result;
}
return CWnd::OnNcHitTest(p);
}
MSDN örnekten HitTestNCA
işlevi yanlış olduğu için zaman olması gerektiği, bu HTCLIENT
dönmez, GetForegroundWindow()
ile bir düzeltme eklendi. Başka bir pencere odaklandığında, istemci alanında fare tıklamasıyla pencereleri değiştirmez. GetWindowDC()
bunu çalıştırıldığı her defasında
CDC* dc = GetWindowDC();
ReleaseDC
tarafından takip edilmelidir:
Ayrıca OnNcPaint
bir kaçak var. Veya otomatik temizleme özelliğine sahip CWindowDC
kullanın. Çerçeve "istemci alanı" için genişletildiğinden, aslında OnNcPaint
geçersiz kılmanız gerekmez.
class cglassWnd : public CWnd
{
void OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS FAR*);
LRESULT OnNcHitTest(CPoint p);
void OnNcMouseLeave();
int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnActivate(UINT state, CWnd* otherWnd, BOOL minimized);
void OnPaint();
CRect borders;
int titlebar_height;
DECLARE_MESSAGE_MAP()
public:
cglassWnd();
};
BEGIN_MESSAGE_MAP(cglassWnd, CWnd)
ON_WM_NCHITTEST()
ON_WM_NCCALCSIZE()
ON_WM_NCMOUSELEAVE()
ON_WM_ACTIVATE()
ON_WM_CREATE()
ON_WM_PAINT()
END_MESSAGE_MAP()
cglassWnd::cglassWnd()
{
BOOL dwm_enabled = FALSE;
DwmIsCompositionEnabled(&dwm_enabled);
if (!dwm_enabled)
TRACE("Error: don't use this class, add error handling...");
//modified height for the new title bar
titlebar_height = 60;
}
int cglassWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
int res = CWnd::OnCreate(lpCreateStruct);
//find border thickness
borders = { 0,0,0,0 };
if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_THICKFRAME)
{
AdjustWindowRectEx(&borders,
GetWindowLongPtr(m_hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
borders.left = abs(borders.left);
borders.top = abs(borders.top);
}
else if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_BORDER)
{
borders = { 1,1,1,1 };
}
//Extend caption in to client area
MARGINS margins = { 0 };
margins.cyTopHeight = titlebar_height;
DwmExtendFrameIntoClientArea(m_hWnd, &margins);
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
return res;
}
void cglassWnd::OnPaint()
{
CPaintDC dc(this);
//paint titlebar area (this used to be the non-client area)
CRect rc;
GetClientRect(&rc);
rc.bottom = titlebar_height;
//see MSDN reference for explanation of this code
//upside-down bitmap is for the sake of DrawThemeTextEx
CDC memdc;
memdc.CreateCompatibleDC(&dc);
BITMAPINFOHEADER infhdr = { sizeof(infhdr), rc.right, -rc.bottom, 1, 32 };
HBITMAP hbitmap = CreateDIBSection(dc,(BITMAPINFO*)(&infhdr),DIB_RGB_COLORS,0,0,0);
auto oldbitmap = memdc.SelectObject(hbitmap);
//do extra titlebar painting here
//for example put DrawThemeTextEx for window's name
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
memdc.SelectObject(oldbitmap);
DeleteObject(hbitmap);
//begin normal paint
//The new client area begins below titlebar_height which we define earlier
GetClientRect(&rc);
rc.top = titlebar_height;
dc.FillSolidRect(&rc, RGB(128, 128, 255));
}
void cglassWnd::OnNcCalcSize(BOOL validate, NCCALCSIZE_PARAMS FAR* sz)
{
if (validate)
{
sz->rgrc[0].left += borders.left;
sz->rgrc[0].right -= borders.right;
sz->rgrc[0].bottom -= borders.bottom;
}
else
{
CWnd::OnNcCalcSize(validate, sz);
}
}
LRESULT cglassWnd::OnNcHitTest(CPoint pt)
{
LRESULT result = 0;
//handle close/minimize/maximize button
if (DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y), &result))
return result;
//cursor is over the frame or client area:
result = CWnd::OnNcHitTest(pt);
if (result == HTCLIENT)
{
ScreenToClient(&pt);
if (pt.y < borders.top) return HTTOP;
if (pt.y < titlebar_height) return HTCAPTION;
}
return result;
}
void cglassWnd::OnNcMouseLeave()
{
//This is for close/minimize/maximize/help buttons
LRESULT result;
DwmDefWindowProc(m_hWnd, WM_NCMOUSELEAVE, 0, 0, &result);
CWnd::OnNcMouseLeave();
}
void cglassWnd::OnActivate(UINT state, CWnd* otherWnd, BOOL minimized)
{
CWnd::OnActivate(state, otherWnd, minimized);
Invalidate(FALSE);
}
Kendini fare hareketlerini takip etmek zorunda ve bunu yapmak:
İşte tam örnektir. –