i have to draw something in dialog box mfc , so , can i call a single document (because i know how to draw in single document MFC ) , from my main dialog box ?
thnx
You can use the same drawing code both in a CView and in a CDialog.
On the CView drawing works like this:
void CMyView::OnDraw(CDC* pdc)
{
// Draw something on pdc
Draw(pdc);
}
In a CDialog, override the OnPaint() handler, and draw like this:
void CMyDialog::OnPaint()
{
CPaintDC dc(this);
CPaintDC* pdc = &dc;
CDialog::OnPaint();
// Draw something on pdc
Draw(pdc);
}
Instead of a view in a dialog box, use a window derived from CStatic and make it to the size of dialog box on OnSize. It will be better than adding a view in a dialog box.
You have to override the OnPaint() event of the static control. To avoid flicker you have to override OnEraseBkgrnd() event.
class CMyStatic : public CStatic
{
public:
CMyStatic ()
~CMyStatic();
protected:
afx_msg void OnPaint();
void Draw(CDC *pDC);
};
void CMyStatic::Draw(CDC *pDC)
{
}
void CMyStatic::OnPaint()
{
CPaintDC dc(this);
Draw(&dc);
}
Related
By default the color is gray, I want to change it.I use OnEraseBkgnd in my MainFarm.h,this works, it changes color,but when somewhere further in the code mfc changes it to gray again.
BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
CBrush backBrush(RGB(0, 0, 0));
CBrush* pPrevBrush = pDC->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
PATCOPY);
pDC->SelectObject(backBrush);
return TRUE;
}
A MDI application doesn't just have frame windows and child windows. It also has a client window. The client window handles most of managing child windows.
But it also draws the client area of the frame window. This is what's drawing the grey background after you draw your background when you handle OnEraseBkgnd in the frame window.
Assuming your frame is derived from CMDIFrameWndEx, you should have a OnEraseMDIClientBackground virtual function that you can override to do the drawing you want.
If you're modifying older code, it's possible it uses an old enough version of MFC that's not present. If so, you need to create a window class and do the correct drawing in its onEraseBkgnd, create an instance of that in your frame window class, and in the frame window's onCreate, you subclass the MDI child window:
class MyBkgndErase : public CWnd {
public:
BOOL OnEraseBkgnd(CDC* pDC) {
// drawing code here
}
};
class MyFrameWnd : public CMDIFrameWnd {
MyBkgndErase eraser;
int OnCreate(LPCREATESTRUCT lpCreateStruct) {
// there's probably existing code you'll want to preserve here
eraser.SubclassWindow(m_hWndMDIClient);
return 0;
}
};
Or, if you can switch to a newer version of MFC, you can probably just change your frame window's parent class from CMDIFrameWnd to CMDIFrameWndEx, and use OnEraseMDIClientBackground (which is undoubtedly easier).
I have a MainFrame which is derived from wxFrame. The frame has a panel member m_panel of a custom class, derived from wxPanel.
I overloaded the OnPaint() function of the MainFrame to set a background image.
From the background image I only see a 5 pixel boarder. The rest is blocked by the wxPanel. And for some reason I cannot make the panel transparent. I tried m_panel->Hide() which had no effect at all and m_panel->SetBackgroundStyle(wxBG_STYLE_CUSTOM). The latter had the weird effect that I could see the desktop (however the background image was still visible in the 5px border).
I did add the wxTRANSPARENT_WINDOW style in the constructor of the wxPanel.
How can I have this panel and make it transparent?
Have a custom wxPanel where you override OnPaint to have your drawings. Then use this as the main panel of your wxFrame. Example shown below:
class BackgroundPanel: public wxPanel
{
public:
BackgroundPanel(wxFrame* parent);
void OnPaint(wxPaintEvent & evt);
private:
wxBitmap backgroundBitmap;
DECLARE_EVENT_TABLE()
};
BackgroundPanel::BackgroundPanel(wxFrame* parent)
:wxPanel(parent)
{
//Set backgroundBitmap
}
void BackgroundPanel::OnPaint(wxPaintEvent& evt)
{
wxPaintDC dc(this);
int height = GetClientRect().GetHeight() - backgroundBitmap.GetHeight();
dc.DrawBitmap(backgroundBitmap,0,height,false);
}
I have a CStatic picture control on a CDialog that I use to draw content:
CMyDrawingControl.h
CMyDrawingControl : CStatic
{
//Constructor, Destructor, other items
//End Constructor, Destructor, other items
public:
void DrawStuff(CDC *dc);
protected:
afx_msg void OnPaint();
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
}
CMyDrawingControl.cpp
CMyDrawingControl::CMyDrawingControl
{
}
BEGIN_MESSAGE_MAP(CMyDrawingControl, CStatic)
//{{AFX_MSG_MAP(CMyDrawingControl)
ON_WM_VSCROLL()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMyDrawingControl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//determine delta
ScrollWindow(0, -delta);
Invalidate();
UpdateWindow();
}
void CMyDrawingControl::OnPaint()
{
CPaint dc(this);
DrawStuff(&dc);
}
void CMyDrawingControl::DrawStuff(CDC *dc)
{
dc->SetMapMode(MM_LOMETRIC);
//draw on dc
//text, lines, shapes, etc
}
However the content is usually bigger than the control so I need to be able to scroll the content. CScrollView automatically handles by drawing to the view in OnDraw, but I can't seem to get it to work in OnPaint(). The control either will draw blank or has a lot of repeated content when scrolling.
I'm basically trying to duplicate the exact behavior of CScrollView on a CDialog; I've seen some posts that come close to this, but I don't want to implement a CDocument and a CView.
I think it is much simpler to use a read only edit control.
Beside scrolling this also makes it possible that the user can select and copy parts of the text.
I created a custom control whose class has CStatic as base class. Currently I handle the drawing using WM_PAINT event. But there is a strange behavior. When I re-enable the window after disabling it using CWnd::EnableWindow function, it refuses to draw what I written in OnPaint function. It draws the static control instead.
I agree that there is this standard method of overriding DrawItem and using SS_OWNERDRAW style. But what's wrong with WM_PAINT?
void XXControl::OnPaint()
{
CPaintDC PaintDC( this );
// ** draw the control to PaintDC**
}
Here is exactly what I have written:
class CMyStatic : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
void OnPaint(void);
};
BEGIN_MESSAGE_MAP(CMyStatic, CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CMyStatic::OnPaint(void)
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.FillSolidRect(&rect, RGB(120,255,0));
}
And subclassed:
class CMyDlg : public CDialog
{
// Construction
CMyStatic my_static;
...
};
BOOL CCMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
my_static.SubclassDlgItem(IDC_DRAW, this);
return true;
}
Where IDC_DRAW is static control on resource for this dialog. I wrote two button handlers:
void CMyDlg::OnBnClickedOk()
{
my_static.EnableWindow(FALSE);
my_static.Invalidate();
}
void CMyDlg::OnBnClickedOk2()
{
my_static.EnableWindow();
my_static.Invalidate();
}
And it works flawlessly! Remove Invalidate call and it would fail.
Try turning off Aero. I'm having a similiar problem where I'm drawing a static control and when it goes from disabled to enabled the WM_PAINT message is never received, but if I turn Aero off it works fine.
Is there a way to change the color of the background for a MDIParent windows in MFC (2005)?
I have tried intercepting ON_WM_CTLCOLOR AND ON_WM_ERASEBKGND but neither work. OnEraseBkgnd does work, but then it gets overwritten by the standard WM_CTL color.
Cheers
Create a class deriving CWnd (CClientWnd for example)
In your CWnd-derived class handle
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint(void);
afx_msg void OnSize(UINT nType, int cx, int cy);
You need the following message map entries:
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SIZE()
In OnEraseBkgnd just return TRUE, you'll do all of the work in OnPaint
In OnPaint, do whatever you like. To fill with a color, you could do
CBrush brush;
brush.CreateSolidBrush(COLORREF(RGB( 80, 160, 240 )));
CRect clientRect;
GetClientRect(clientRect);
CPaintDC dc(this);
dc.FillRect(clientRect, &brush);
In OnSize, call the base class, then invalidate to force a repaint:
CWnd::OnSize(nType, cx, cy);
Invalidate(FALSE);
In your mainframe, declare a member CClientWnd (m_clientWnd for example)
In your mainframe's OnCreate, first call the superclass, then
m_clientWnd.SubclassWindow(m_hWndMDIClient);
The CMDIFrameWnd is actually covered up by another window called the MDIClient window. Here is a Microsoft article on how to subclass this MDIClient window and change the background colour. I just tried it myself and it works great.
http://support.microsoft.com/kb/129471
There appears to be a simple solution to this problem in VS2008 at least:
In
CMainFrame::OnPaint()
{
..
// get the dc of the background window
CWnd* pWnd = CWnd::FromHandle(m_hWndMDIClient) ;
CPaintDC dc1(pWnd) ;
//and then draw or bitblt in this DC
}
Just guessing here, but try handling ON_WM_PAINT.