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

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

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

Post by Ovidiu Cucu » 29 Jul 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) Viewed 7651 times
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.

    Code: Select all

    #include "MDIClientWnd.h"
    
    class CMainFrame : public CMDIFrameWnd
    {
       CMDIClientWnd m_wndMDIClient;
    // ...
    };
  3. In CMainFrame::OnCreate subclasam ferastra MDI client lui CMDIClientWnd.

    Code: Select all

    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

    Code: Select all

    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.

    Code: Select all

    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.

    Code: Select all

    BOOL CMDIClientWnd::OnEraseBkgnd(CDC* pDC) 
    {	
       return FALSE;
    }
Vezi si << Back to MFC index



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

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

Post by Ovidiu Cucu » 28 Jan 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

Code: Select all

// MainFrm.h

class CMainFrame : public CMDIFrameWndEx
{
   // ...
   // Overrides
public:
   virtual BOOL OnEraseMDIClientBackground(CDC* pDC);
   // ...
};

Code: Select all

// 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

Post Reply