2016-10-13 13 views
2

キャプションのタイトルバーにアイコンを描画するために、this MSDN articleを参照し、DwmExtendFrameIntoClientAreaを呼び出してDWM APIを使用してカスタマイズしたクライアント領域を作成しました。Windows上でDWM APIを使用したAeroキャプションのタイトルバーの問題1

は私のコード:Windows 7の下

CMainFrame::CMainFrame() 
{ 
    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR   gdiplusToken; 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

    BOOL fDwmEnabled = FALSE; 
    if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled))) 
     TRACE0("DWM is enabled\n"); 

    TCHAR szLogoPath[MAX_PATH]; 
    GetModuleFileName (GetModuleHandle(NULL), szLogoPath, _countof(szLogoPath) ); 
    PathRemoveFileSpec (szLogoPath); 
    PathAppend (szLogoPath, _T("lena.bmp")); 
    m_pLogoImage = m_pLogoImage->FromFile (CT2CW(szLogoPath)); 
    if(NULL == m_pLogoImage) 
     TRACE0("load image fail\n"); 
} 

void CMainFrame::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) 
{ 
    int xFrame = 2; 
    int yFrame = 2; 
    int nTHight = 30; 
    NCCALCSIZE_PARAMS * p; 
    RECT * rc; 
    RECT aRect; 
    RECT bRect; 
    RECT acRect; 
    p = (NCCALCSIZE_PARAMS *)lpncsp; 

    CopyRect(&bRect,&p->rgrc[1]); 
    CopyRect(&aRect,&p->rgrc[0]); 

    acRect.left = aRect.left + xFrame; 
    acRect.top = aRect.top - nTHight; 
    acRect.right = aRect.right - xFrame; 
    acRect.bottom = aRect.bottom - yFrame; 
    CopyRect(&p->rgrc[0],&acRect); 
    CopyRect(&p->rgrc[1],&aRect); 
    CopyRect(&p->rgrc[2],&bRect); 
    CFrameWnd::OnNcCalcSize(TRUE, lpncsp); 
} 

LRESULT CMainFrame::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); 
} 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
{ 
    if(cs.hMenu!=NULL) 
    { 
    ::DestroyMenu(cs.hMenu);  
     cs.hMenu = NULL ;  
    } 
    if(!CFrameWnd::PreCreateWindow(cs)) 
     return FALSE; 
    // TODO: Modify the Window class or styles here by modifying 
    // the CREATESTRUCT cs 
    cs.style = WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED| WS_SYSMENU | WS_THICKFRAME; 
    cs.dwExStyle &= ~WS_EX_CLIENTEDGE; 
    cs.lpszClass = AfxRegisterWndClass(0); 

    return TRUE; 
} 

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}; 
      /*margins.cyTopHeight = 30; 
      margins.cxLeftWidth = 0; 
      margins.cxRightWidth = 0; 
      margins.cyBottomHeight = 0;*/ 
      HRESULT hr = DwmExtendFrameIntoClientArea(m_hWnd, &margins); 
      if (!SUCCEEDED(hr)) 
       TRACE0("Failed in DwmExtendFrameIntoClientArea\n"); 
     } 
    } 
} 

void CMainFrame::OnNcPaint() 
{ 
    CFrameWnd::OnPaint(); 
    CDC* dc = GetWindowDC(); 
    RECT rcClient; 
    GetWindowRect(&rcClient); 
    dc->FillSolidRect(0,0,RECTWIDTH(rcClient),RECTHEIGHT(rcClient),RGB(255,0,0)); 

    CPaintDC gdc(this); // device context for painting 
    Graphics gr(gdc.m_hDC); 
    gr.DrawImage (m_pLogoImage, 0, 0); 
    ReleaseDC(dc); 

} 

結果は罰金です。 enter image description here

はしかし、私の窓は、私は、未知のキャプションがcs.styleでWS_THICKFRAMEによって引き起こされていWindowsの10 enter image description here

enter image description here

の下に別の未知のキャプションタイトルバーを表示されます。 WS_THICKFRAMEを削除すると、未知のカチオンバーが消えますが、ウィンドウの境界線のサイズを変更することはできません。さらに、私のプログラムは、私のカスタムキャプションバーの最小、最大、閉じるボタンのメッセージをキャプチャすることはできません。 不明なタイトルバーを副作用なしで削除したい。 誰かが私に良い解決策や提案を提供できますか?

よろしく、

+1

見る - あなたは私たちに教えていない限り、あなたが必要なもの、それはおそらくないだろう発生する。あなたがしたくないことについてたくさん話しましたが、あなたが本当に必要としているものの簡潔な説明を作成したことはありませんでした。 – IInspectable

+0

不明なタイトルバーを削除したいのですが、副作用はありません。ありがとう – user2365346

答えて

1

DwmExtendFrameIntoClientAreaを使用して、それはフレームがクライアント領域の中に延長されることを意味します。それはもはやの非クライアントエリアにはありません。だから、OnNcPaintを上書きする必要はありません、あなたは境界線の太さを追跡するためにOnPaint

void CMainFrame::OnPaint() 
{ 
    CPaintDC dc(this); 

    //paint titlebar area (this used to be the non-client area) 
    CRect rc; 
    GetClientRect(&rc); 
    rc.bottom = titlebar_height; 

    CDC memdc; 
    memdc.CreateCompatibleDC(&dc); 
    BITMAPINFOHEADER bmpInfoHeader = { 
     sizeof(BITMAPINFOHEADER), rc.Width(), -rc.Height(), 1, 32 }; 
    HBITMAP hbitmap = CreateDIBSection(
     dc, (BITMAPINFO*)(&bmpInfoHeader), DIB_RGB_COLORS, NULL, NULL, 0); 
    auto oldbitmap = memdc.SelectObject(hbitmap); 

    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(0, 0, 255)); 

    Gdiplus::Image *image = Gdiplus::Image::FromFile(L"file.jpg"); 
    Gdiplus::Graphics gr(dc); 
    gr.DrawImage(image, 0, 0); 
    delete image; 
} 

使用メンバ変数CRect m_borderに絵画のすべてを行うことができます。 AdjustWindowRectExを使用して、罫線の太さを見つけることができます。

void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
{ 
    CFrameWnd::OnActivate(nState, pWndOther, bMinimized); 

    titlebar_height = 100; 
    //find border thickness 
    if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_THICKFRAME) 
    { 
     m_border = { 0,0,0,0 }; 
     AdjustWindowRectEx(&m_border, GetWindowLongPtr(m_hWnd, 
       GWL_STYLE) & ~WS_CAPTION, FALSE, NULL); 
     m_border.left = abs(m_border.left); 
     m_border.top = abs(m_border.top); 
    } 
    else if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_BORDER) 
    { 
     m_border = { 1,1,1,1 }; 
    } 
    else 
    { 
     m_border = { 0,0,0,0 }; 
    } 

    //Extend frame in to client area 
    MARGINS margins = { 0 }; 
    margins.cyTopHeight = titlebar_height; //<<=== *** edited 
    DwmExtendFrameIntoClientArea(m_hWnd, &margins); 
    SetWindowPos(NULL, 0, 0, 0, 0, 
      SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); 
} 

m_border例えば{7,7,7,7}ためであろう。

Windowsは、左、右、下の境界線でペイントを行うことができます。上部の境界線だけが変更された

void CMainFrame::OnNcCalcSize(BOOL validate, NCCALCSIZE_PARAMS FAR* lpncsp) 
{ 
    if (validate) 
    { 
     lpncsp->rgrc[0].left += m_border.left; 
     lpncsp->rgrc[0].right -= m_border.right; 
     lpncsp->rgrc[0].bottom -= m_border.bottom; 
    } 
    else 
    { 
     CFrameWnd::OnNcCalcSize(validate, lpncsp); 
    } 
} 

は*「誰もが私に良い解決策や提案を提供することができていますか?」*もHow to glow the minimum. maximum and close button?

+0

私はそれを試みたが、私のプログラムは、最小、最大と閉じるボタンのメッセージをキャプチャすることはできません。 – user2365346

+0

あなたは以前同様の質問をしていたと思います。私は完全な例を加えました、リンクを見てください。唯一の違いは、タイトルバーの高さが固定されている例、たとえば60ピクセルを追加したことです。しかし、あなたのバージョンでは、ウィンドウ全体がタイトルバーとして機能するように思えます。その場合、 'titlebar_height'を最大スクリーン高さに変更します。 'SystemParametersInfo(SPI_GETWORKAREA ....)' OnNcPaintのオーバーライドを追加しないでください –

+0

私は持っていますそれを解決しました。あなたのヒントをありがとう – user2365346

関連する問題