Cum punem o imagine in zona client a unui frame MDI?
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:
- Definim o clasa derivata din CWnd, si-i zicem CMDIClientWnd.
- In CMainFrame adaugam un membru de tip CMDIClientWnd, m_wndMDIClient.
Code: Select all
#include "MDIClientWnd.h" class CMainFrame : public CMDIFrameWnd { CMDIClientWnd m_wndMDIClient; // ... };
- 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; }
- In hadlerul din CMDIClientWnd al mesajului WM_PAINT, desenam imaginea dorita.
ExempluCode: 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); }
- 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(); }
- 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; }