2016-01-15 13 views
8

DWM API kullanarak özel bir Aero Frame oluşturmak için aşağıdaki kılavuzu takip ettim.Asgari aydınlatma nasıl yapılır. maksimum ve kapat düğmesi

Custom Window Frame Using DWM

İşim:

void CMainFrame::OnActivate(UINT nState,CWnd* pWndOther,BOOL bMinimized) 
{ 
    CFrameWnd::OnActivate(nState,pWndOther,bMinimized); 
    BOOL fDwmEnabled = FALSE; 
    if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled))) 
    { 
     if(nState == WA_ACTIVE) 
     { 
      MARGINS margins ={-1}; 
      HRESULT hr = DwmExtendFrameIntoClientArea(m_hWnd, &margins); 
      if (!SUCCEEDED(hr)); 
     } 
    } 
} 

void CMainFrame::OnNcPaint(){ 
    RECT rcClient; 
    GetWindowRect(&rcClient); 
    // Inform the application of the frame change. 
    SetWindowPos( 
      NULL, 
      rcClient.left, rcClient.top, 
      RECTWIDTH(rcClient), RECTHEIGHT(rcClient), 
      SWP_FRAMECHANGED); 
    CFrameWnd::OnNcPaint(); 
    CDC* dc = GetWindowDC(); 
    dc->FillSolidRect(0,0,RECTWIDTH(rcClient),RECTHEIGHT(rcClient),RGB(0,0,0)); 
} 

LRESULT CMainFrame::OnNcHitTest(CPoint p) 
{ 
    LRESULT r ; 
    r = CFrameWnd::OnNcHitTest(p);  
    if(r == HTMINBUTTON || r == HTMAXBUTTON || r == HTCLOSE) 
     return r; 
    else 
     r = HitTestNCA(m_hWnd,p); // this function is direct copied from above link. 
    return r; 
} 

Sonuç: Ben fareyi hareket ettirdiğinizde parladı olmayacak minimum, maksimum ve kapatma düğmesi öğrendim

enter image description here

Bu düğmelerde.

enter image description here

Genel durum:

enter image description here

Nasıl bu sorunu çözmeye yönelik?

Saygılarımızla,

+0

Kendini fare hareketlerini takip etmek zorunda ve bunu yapmak:

İşte tam örnektir. –

cevap

6

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); 
}