[MFC] Cum punem o imagine in toolbar?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Cum punem o imagine in toolbar?

Post by Ovidiu Cucu » 28 Jul 2011, 16:39

Problema
Cum punem o imagine in toolbar-ul unei aplicatii SDI/MDI?
Toolbar application logo.gif
Toolbar application logo.gif (7.32 KiB) Viewed 2691 times
Solutie
  1. Derivam din CToolBar o clasa, sa-i zicem CAppToolBar.

    Code: Select all

    class CAppToolBar : public CToolBar
    {
       CBitmap m_bmpImage;
    // ...
    // Operations
    public:
       void SetImage(UINT nImageID);
    // ...
       afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
       DECLARE_MESSAGE_MAP()
    
    // Implementation
    private:
       CSize _CalcSizes(CSize& sizeImage);
       void _DrawImage(HDC hDC, const RECT& rc);
    };
    
  2. Adaugam o functie care sa insereze un separator, care va servi ca placeholder pentru imagine. De notat ca pentru separator, TBBUTTON::iBitmap tine latimea in pixeli.

    Code: Select all

    void CAppToolBar::SetImage(UINT nImageID)
    {
       VERIFY(m_bmpImage.LoadBitmap(nImageID));
    
       CSize sizeImage;
       _CalcSizes(sizeImage);
    
       TBBUTTON tbb = {0};
       tbb.fsStyle = TBSTYLE_SEP;
       tbb.iBitmap = sizeImage.cx;
    
       CToolBarCtrl& toolBarCtrl = GetToolBarCtrl();
       toolBarCtrl.InsertButton(0, &tbb);
    }
  3. Mapam mesajul de notificare reflectat =NM_CUSTOMDRAW. De notat ca pentru dwDrawStage CDDS_PREPAINT, se intoarce CDRF_NOTIFYPOSTPAINT pentru a cere si o notificare post-paint; altfel acea bara desenata pentru separator s-ar suprapune peste imagine.

    Code: Select all

    // ...
       ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
    END_MESSAGE_MAP()
    
    void CAppToolBar::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    {
       LPNMCUSTOMDRAW pNMCD = (LPNMCUSTOMDRAW)pNMHDR;
       switch(pNMCD->dwDrawStage)
       {
       case CDDS_PREPAINT: 
          // request post-paint notification
          *pResult = CDRF_NOTIFYPOSTPAINT;
          break;
       case CDDS_POSTPAINT:
          // draw image and skip default
          _DrawImage(pNMCD->hdc, pNMCD->rc);
          *pResult = CDRF_SKIPDEFAULT;
          break;
       default:
          *pResult = CDRF_DODEFAULT;
          break;
       }
    }
  4. In CMainFrame inlocuim CToolBar cu CAppToolBar.

    Code: Select all

    // MainFrm.h
    #include "AppToolBar.h"
    
    class CMainFrame : public CMDIFrameWnd
    {
    // ...
    protected:  // control bar embedded members
       CAppToolBar m_wndToolBar;
    // ...
    };
    << Back to MFC index
  5. In fine, apelam CAppToolBar::SetImage dupa ce toolbarul a fost incarcat.

    Code: Select all

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    // ...
       m_wndToolBar.SetImage(IDB_LOGO);
       return 0;
    }
In continuare, un exemplu de implementare pentru CAppToolBar::_CalcSizes si CAppToolBar::_DrawImage

Code: Select all

CSize CAppToolBar::_CalcSizes(CSize& sizeImage)
{
   _ASSERTE(NULL != m_bmpImage.GetSafeHandle());

   BITMAP bmp = {0};
   m_bmpImage.GetBitmap(&bmp);
   CSize sizeBitmap(bmp.bmWidth, bmp.bmHeight);

   CToolBarCtrl& toolBarCtrl = GetToolBarCtrl();
   const DWORD dwSizes = toolBarCtrl.GetButtonSize();
   const int nHeight = HIWORD(dwSizes) - 2;

   sizeImage.cx = (int)(sizeBitmap.cx * ((double)nHeight / sizeBitmap.cy));
   sizeImage.cy = nHeight;

   return sizeBitmap;
}

Code: Select all

void CAppToolBar::_DrawImage(HDC hDC, const RECT& rc)
{
   CSize sizeImage;
   CSize sizeBitmap = _CalcSizes(sizeImage);

   CDC dcMem;
   CDC* pDC = CDC::FromHandle(hDC);
   dcMem.CreateCompatibleDC(pDC);
   CBitmap* pOldBitmap = (CBitmap*)dcMem.SelectObject(&m_bmpImage);

   const int nOldMode = pDC->SetStretchBltMode(HALFTONE);
   pDC->StretchBlt(rc.left, rc.top + 1, sizeImage.cx, sizeImage.cy,
      &dcMem, 0, 0, sizeBitmap.cx, sizeBitmap.cy, SRCCOPY);

   pDC->SetStretchBltMode(nOldMode);
   dcMem.SelectObject(pOldBitmap);   
}
Vezi si



Post Reply