I understand that the onDraw() function is virtual void which is called automatically via OnPaint(), which is itself triggered by the WM_PAINT message.
My declaration goes something like this:
myDialog.cpp
void myDialog::OnDraw(CDC* dc)
{
CCustomMemDC pDC(dc);
CExampleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
myDialog.h
afx_msg void OnDraw(CDC* dc);
and in my OnPaint()
CDialog::OnPaint();
However I could not get OnDraw to be triggered at all... Could anyone enlighten if this method is correct?
Thanks!
A dialog has no OnDraw. This is a virtual function in views to allow printing and drawing to a screen.
In a dialog just use OnPaint. There isno redirection to a virtual OnDraw function in a dialog.
It is not correct. As others have pointed out, OnDraw() is a virtual method of CView and not CDialog. Therefore, your OnDraw() method will never be called.
I don't know why your dialog would have a flicker problem that you would need to mitigate it. If you have a custom control on the dialog that is causing flicker, then you probably need to fix the drawing code in it and possibly add WS_CLIPCHILDREN as a Window Style to your dialog. That will make sure that the background of the custom control is not erased when the dialog executes its WM_ERASEBKGND message.
It makes no sense to override the WM_PAINT of the dialog unless you are really planning to do custom drawing on it. Unless you have a very good reason, don't do it.
If you choose to ignore the advice then add an ON_WM_PAINT() to your message handler to the dialog, and then draw the dialog yourself:
void myDialog::OnPaint()
{
CPaintDC dc(this);
CCustomMemDC pDC(&dc);
// do your specialized code knowing you are responsible for drawing the whole dialog
}
If you really want to use your OnDraw() method, then you could also write OnPaint() like this:
void myDialog::OnPaint()
{
CPaintDC dc(this);
OnDraw(&dc);
}
But, the first thing I would do in your situation is try adding the style WS_CLIPCHILDREN to your dialog style.
Related
I'm trying to implement the OnPaint() method in the subclass of the CButton MFC class.
class CImageButton : public CButton
public:
using CButton::CButton;
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CImageButton, CButton)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CImageButton::OnPaint()
{ /* Draws an image; Doesn't call the CButton::OnPaint(). */ }
Then, I have a dialog. In the resource editor, I placed the button on its form. In the dialog declaration, I wrote
CImageButton m_btn;
and
DDX_Control(pdc, IDC_BUTTON, m_btn);
in the DoDataExchange(). So, I think, I done all in order to my painting routine be working. But I got the strange thing: when my dialog is opening the image is painted OK (without the button's border, as I implemented in my method). But, if I'm trying to click on it, the image disappears the button's border is drawn as well a text which I specified in the VS resource editor. I.e., it looks like the superclass'es OnPaint() method is called by some way. I even was placing a debugging output on the entry of my method -- it is really not called. Then, if I switch the focus to some other control, my button is being redrawn with image.
Please, don't suggest me to use other ways to draw the image on the button. I need to get an answer on the question asked.
Thank you!
I am writing my own CStatic subclass right now, and I am a bit stuck on how to change its background color.
From previous experience I am used to reacting to the "CTLCOLORSTATIC" message with the color I want.
However, this is my subclass at the moment:
class LocationPane : public CWindowImpl<LocationPane, CStatic>
{
DECLARE_WND_CLASS(L"LocationPane");
public:
BEGIN_MSG_MAP_EX(LocationPane)
MSG_WM_PAINT(OnPaint)
MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic);
END_MSG_MAP()
LocationPane();
~LocationPane();
private:
HBRUSH OnCtlColorStatic(CDCHandle cd, CWindow wnd);
//Paint routine
void OnPaint(CDCHandle dc);
};
I tried to listen for said message, but I am not receiving it at all. I do receive the paint message however, so I can't blame my custom control for not working at all.
Is it a legit solution to try to handle the background color in the paint routine? I don't really like solving it this way, but I am not receiving the other message which I am used to work with.
If additional code is needed, feel free to ask, I will gladly provide you with additional resources.
Thanks in advance.
I think you want to be catching WM_CTLCOLORSTATIC in the parent window that hosts your control. That's typically used for when you want to have a text control have a different background color.
But if you are going to be overriding WM_PAINT, you might as well let your OnPaint draw the background color.
I have a MFC Application with Dialog Based. I created a GDI+ Object from resource by using this.
MyDlg.cpp:
BOOL CSetupDlg::OnInitDialog()
{
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
...
}
void MyFunction():
CGdiPlusBitmapResource* pBitmap = new CGdiPlusBitmapResource;
if (pBitmap->Load(ID_SPL_LG))
{
CPaintDC dc(this);
Gdiplus::Graphics graphics(dc);
graphics.DrawImage(*pBitmap, 0, 0);
//It is loaded . I checked with messagebox and its in here.
}
Invalidate(); //Not sure if necessary.
Now, Form/Dialog shows nothing. No image inserted nor attached.
Now, i tried few things to add this image to the dialog but i am unable to do it.
What i tried is GDIObject.Create(), CStatic.Create() and PictureControl.Create()
All i want to do is insert this image to the dialog.
Any idea or showing path is appreciated.
You will need to override the OnPaint method that responds to the WM_PAINT message in your dialog. Normally you don't need to do this because the dialog doesn't need to paint anything, it just lets the controls that are contained on it paint themselves.
Move the code you show into the OnPaint handler.
Do not call the default OnPaint from your own handler.
Do not call Invalidate from within the OnPaint handler or you will get an infinite loop.
As the title says.
Even with CPaintDC in the derived class the GDI drawing is not cut off.
Thanks in advance.
void CGraph::OnPaint ()
{
CPaintDC dc(this);
dc.SetViewportOrg (0, 400);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(1000, 800);
dc.SetViewportExt(1000, -800);
// MessageBox(L"OnPaint");
ProcessData ();
DrawCoordinateSystem (&dc);
DrawGrid (&dc);
DrawGraph (&dc);
}
So, your CGraph is derived from CStatic, and the drawing code you show draws outside of the CStatic control, onto the dialog it is on? That's impossible, a control can only draw on itself. Are you sure the control isn't bigger than you think it is, and what you think is off-control actually isn't? Use spy++ to select your cstatic, it'll show you the border of the window.
Maybe what you are seeing is improper invalidation. Try dragging another window over your control, see what that does.
Otherwise, the methods to restrict the drawing area are
You manually track where to draw. Tedious.
Use SetClipRgn() to set the area to which to restrict drawing.
Not quite the same, but symptoms sometimes look similar: check the WS_CLIPSIBLINGS and WS_CLIPCHILDREN flags of your control and the dialog it's on.
Here is the way I solved the problem
CDC* pDC = GetDC();
CRect rClient(0,0,1000,800);
//GetClientRect(rClient);
CRgn ClipRgn;
if (ClipRgn.CreateRectRgnIndirect(&rClient))
{
pDC->SelectClipRgn(&ClipRgn);
}
pDC->SelectObject (PenBlack);
pDC->MoveTo (-leftMargin*zoomWidth, setPointsCorrected);
pDC->LineTo (1000*zoomWidth, setPointsCorrected);
pDC->SelectClipRgn(NULL);
ReleaseDC(pDC);
I am creating a MFC application in which there is a skin library which handles the UI effect of rendering the controls (it gets called in oninitdialog). But, meanwhile, I have also the requirement of displaying an icon on the buttons. For this, I am marking the buttons as ownerdrawn=true, and able to display icon, but in this case, skin effect is not taking place on those buttons whose ownerdrawing is done by me. So, my question is, how do I ensure that a control gets ownedrawn by me, and also by any other library.
Call the default handler for OnPaint to make sure the skinning library has a chance to draw the button, then draw your own content over the top.
void OnPaint()
{
Default();
CClientDC dc(this);
// your painting code goes here
}
You don't need owner-draw to display icons in buttons !