[MFC] Cum punem o imagine in zona MDI client?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)

[MFC] Cum punem o imagine in zona MDI client?

Mesajde Ovidiu Cucu » 29 Iul 2011, 12:00

Intrebare
Cum punem o imagine in zona client a unui frame MDI?

Image in MDI client.jpg
Image in MDI client.jpg (19.16 KiB) Vizualizat de 7440 ori

Rezolvare
Pe fundalul (zona client) unui frame MDI se afla o fereastra al carui handle este pastrat intr-un membru public al clasei CMDIFrameWnd, m_hWndMDIClient. Daca subclasam aceasta fereastra intr-o clasa pe care o definim noi, atunci putem customiza zona MDI client, inclusiv sa pictam o imagine.

Pasii de urmat ar fi urmatorii:
  1. Definim o clasa derivata din CWnd, si-i zicem CMDIClientWnd.
  2. In CMainFrame adaugam un membru de tip CMDIClientWnd, m_wndMDIClient.
    Cod: Selectaţi tot
    #include "MDIClientWnd.h"

    class CMainFrame : public CMDIFrameWnd
    {
       CMDIClientWnd m_wndMDIClient;
    // ...
    };

  3. In CMainFrame::OnCreate subclasam ferastra MDI client lui CMDIClientWnd.
    Cod: Selectaţi tot
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
       // ...
       // NOTE: m_hWndMDIClient is a public member of CMDIFrameWnd
       m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
       // ...
       return 0;
    }

  4. In hadlerul din CMDIClientWnd al mesajului WM_PAINT, desenam imaginea dorita.
    Exemplu
    Cod: Selectaţi tot
    void CMDIClientWnd::OnPaint()
    {
       CPaintDC dc(this);
       CRect rcClient;
       GetClientRect(rcClient);

       CDC dcMem1; // memory DC for double buffering
       dcMem1.CreateCompatibleDC(&dc);
       CBitmap bitmap1;
       bitmap1.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
       CBitmap* pOldBitmap1 = dcMem1.SelectObject(&bitmap1);
       // fill memory device context with the desired brush
       // COLOR_APPWORKSPACE is for default MDI client color
       CBrush backBrush;
       backBrush.CreateSolidBrush(::GetSysColor(COLOR_APPWORKSPACE));
       dcMem1.FillRect(rcClient, &backBrush);

       CDC dcMem2; // memory DC for the bitmap to draw
       dcMem2.CreateCompatibleDC(&dc);
       CBitmap bitmap2;
       bitmap2.LoadBitmap(IDB_LOGO);
       CBitmap* pOldBitmap2 = dcMem2.SelectObject(&bitmap2);

       BITMAP bmp;
       bitmap2.GetBitmap(&bmp);
       int nWidth  = bmp.bmWidth;
       int nHeight = bmp.bmHeight;
       // NOTE: place the picture in bootom-left side;
       //       you may place the picture in any other place.
       int x       = rcClient.left + 10;
       int y       = rcClient.bottom - bmp.bmHeight - 10;
       // copy the bitmap in memory device context
       dcMem1.BitBlt(x, y, nWidth, nHeight, &dcMem2, 0, 0, SRCCOPY);

       CRect rcClip;
       dc.GetClipBox(rcClip);

       nWidth  = rcClip.Width();
       nHeight = rcClip.Height();
       x       = rcClip.left;
       y       = rcClip.top;
       // copy memory device context in client device context
       dc.BitBlt(x, y, nWidth, nHeight, &dcMem1, x, y, SRCCOPY);

       dcMem1.SelectObject(pOldBitmap1);
       dcMem2.SelectObject(pOldBitmap2);
    }

  5. Pe WM_SIZE, invalidam zona client pentru a forta redesenarea.
    Cod: Selectaţi tot
    void CMDIClientWnd::OnSize(UINT nType, int cx, int cy)
    {
       CWnd::OnSize(nType, cx, cy);
       Invalidate();
    }

  6. In fine, pentru a evita flicker-ul atunci cand se face resize, tratam WM_ERASEBKGND si intoarcem FALSE.
    Cod: Selectaţi tot
    BOOL CMDIClientWnd::OnEraseBkgnd(CDC* pDC)
    {   
       return FALSE;
    }

Vezi si

<< Back to MFC index
Avatar utilizator
Ovidiu Cucu
Fondator
Fondator
 
Mesaje: 3776
Membru din: 11 Iul 2007, 16:10
Localitate: Iasi
Judet: Iaşi

[MFC] Cum punem o imagine in zona MDI client? (2)

Mesajde Ovidiu Cucu » 28 Ian 2013, 14:02

In cazul cand clasa frame-ului este derivata din CMDIFrameWndEx, simplu si eficient este sa se suprascrie functia virtuala CMDIFrameWndEx::OnEraseMDIClientBackground.

Exemplu
Cod: Selectaţi tot
// MainFrm.h

class CMainFrame : public CMDIFrameWndEx
{
   // ...
   // Overrides
public:
   virtual BOOL OnEraseMDIClientBackground(CDC* pDC);
   // ...
};
Cod: Selectaţi tot
// MainFrm.cpp

BOOL CMainFrame::OnEraseMDIClientBackground(CDC* pDC)
{
   CRect rcClient;
   GetClientRect(rcClient);

   // draw background
   CBrush* pOldBrush = pDC->SelectObject(&m_brushMDIBack);
   pDC->PatBlt(0, 0, rcClient.right, rcClient.bottom, PATCOPY);

   // draw logo
   CDC dcMem;
   dcMem.CreateCompatibleDC(pDC);
   BITMAP bmp;
   m_bmpSiteLogo.GetBitmap(&bmp);
   CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmpSiteLogo);
   pDC->BitBlt(5, 5, bmp.bmWidth, bmp.bmHeight, &dcMem, 0, 0, SRCCOPY);

   // free GDI objects
   pDC->SelectObject(pOldBrush);
   pDC->SelectObject(pOldBitmap);

   // let CMFCVisualManager doing its job
   CMFCVisualManager::GetInstance()->OnEraseMDIClientArea(pDC, rcClient);

   return TRUE; // no further default processing
}


Alte amanunte cat si un proiect demo, gasiti pe codexpert blog: Custom Paint in MDI Client
Avatar utilizator
Ovidiu Cucu
Fondator
Fondator
 
Mesaje: 3776
Membru din: 11 Iul 2007, 16:10
Localitate: Iasi
Judet: Iaşi


Înapoi la MFC / ATL / WTL / WMI / GDI+

Cine este conectat

Utilizatorii ce navighează pe acest forum: Niciun utilizator înregistrat şi 1 vizitator

cron