Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
Hi,
 
I have this bit of code to draw, for testing purposes, a line in a picture control (ID = IDC_GRAPH_D_GRAPH) located in a dialog box:
 
void CGraphDlg::ShowGraph(void)
{
	m_iCount++;
	CPaintDC dc (GetDlgItem(IDC_GRAPH_D_GRAPH));
	CSize cs = dc.GetWindoxExt();
	CPen lpen(PS_SOLID, 1, RGB(255, 0, 0));
	dc.SelectObject(&lpen);
	dc.LineTo(100,m_iCount);
}
 
It works OK because it does draw the line as expected in the picture control so the declaration of dc and the link from it to the picture control in question clearly works.
 
Oddly enough though the member function "GetWindowExt" of "CClientDC dc" always returns a CSize with values cx = 1 and cy = 1 while the actual picture control size is several hundred pixels each way.
I am not using cx and cy for now but I would like to.
 
Obviously I must be missing something, anybody have an idea what it might be?
 
I am using: Visual studio 2010, and its a very basic MFC dialog box application.
 
Any help much appreciated.
Posted 18-Dec-12 4:22am
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

A CPaintDC object can only be used when responding to a WM_PAINT message.
 
So I'm guessing that you're not calling this during the processing of the WM_PAINT message for the picture control.
 
Regards
Espen Harlinn
  Permalink  
v2
Comments
Filip Dossche at 18-Dec-12 10:06am
   
Unfortunately I am calling "ShowGraph" from within the OnPaint() function which does get triggered by means of WM_PAINT.
Espen Harlinn at 18-Dec-12 10:17am
   
Which WM_PAINT? WM_PAINT for the dialog or the picture control?
Filip Dossche at 18-Dec-12 10:25am
   
the WM_PAINT for the dialog
Espen Harlinn at 18-Dec-12 10:42am
   
Then you can't use CPaintDC for the picture control
Filip Dossche at 18-Dec-12 10:55am
   
Fair enough but why does the "LineTo" work then and what is the alternative ?
 
Oh yes, I have found out it only works once. if you trigger WM_PAINT for the dialog using Invalidate() or SendMessage(WM_PAINT) nothing happens any more except for erasing the drawing when using invalidate.
 
I am really new to this and I am getting more and more confused.
Espen Harlinn at 18-Dec-12 11:00am
   
You can see how to create subclass at the bottom of hwincontrol.h and hwinstdctrls.h/.cpp in - this capability is also available with MFC
http://www.codeproject.com/Articles/498251/A-Cplusplus-String-class
 
You can then handle the WM_PAINT message for the picture control. This is window subclassing, not C++ subclassing.
Filip Dossche at 18-Dec-12 12:42pm
   
Hi Espen,
Thanks for the info. I'll check it out tomorrow.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

According to MSDN documentation CPaintDC can only be used when responding to a WM_PAINT message, usually in the OnPaint message handler. It emits internally a BeginPaint - EndPaint sequence, which requests the invalid window area and, at the end, validates that region.
 
If you called ShowGraph from any other place, it can't work.
 
Either use CClientDC, or make sure your ShowGraph function is called inside the WM_Paint message handling.
 
ADDED:
 
When you want to retrieve the size of the window, use GetWindowRect or GetClientRect. GetWindowExt delivers something else, namely the target size of the viewport mapping. You have to explicitly set those. I think to recall that they be default are set to 1.
  Permalink  
v2
Comments
Espen Harlinn at 18-Dec-12 9:52am
   
That does sound about right, I initially wrote some gibberish ...
nv3 at 18-Dec-12 10:44am
   
Thanks Espen!
Filip Dossche at 18-Dec-12 10:09am
   
Too bad, I am calling "ShowGraph" from within the OnPaint() message handler which does get triggered by means of WM_PAINT. The "LineTo" works fine so that should be OK.
nv3 at 18-Dec-12 10:43am
   
Please, see my additions above.
Filip Dossche at 18-Dec-12 12:39pm
   
Hi nv3,
I was beginning to suspect that was the case. In the mean time I have successfully used GetWindowRect to get the size.
Thanks for the info.
nv3 at 18-Dec-12 13:11pm
   
Alright then. Problem solved.
jibesh at 18-Dec-12 15:05pm
   
nice nv3 5+!!
nv3 at 18-Dec-12 16:14pm
   
thanks!
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Hi,
 
It took a while to sort things out but I have finally cracked it.
 
Based on the info I got from nv3 and Espen Harlin and a very instructive video I found http://msdn.microsoft.com/en-us/vstudio/cc843613 I introduced a custom dialog control Called CGraph based on class Cwnd and integrated it into my dialog box application.
Integrating it into the dialog box is ultimately dead easy once you know how. Simply adding a custom control to the dialog and specify its class to be "GraphClass" (see c++ code) does the trick.
 
It works very well now and does everything I want and expect it to do.
In reality its just another case of "Glaringly obvious once pointed out".
 
What really tricked me is that when the dialog box initialises windows is capable of and does work on the basis of the dialog box's main WM_PAINT message and subsequent OnPaint() function, it just never repeats it afterwards.
The result was that I did get the expected graph, the code faithfully executed again without any error but it did no more redraw.
 
Thanks for all the help.
 
This is the header file for the new class:
 
#pragma once
#include "ToolBox.h"
#include "Data.h"

class CGraph : public CWnd
{
	DECLARE_DYNAMIC(CGraph)
public:
	CGraph();
	virtual ~CGraph();
 
	CWorkData workData;	
protected:
	BOOL CGraph::RegisterWndClass();
	static TCHAR m_szWndClass[];
	afx_msg void OnPaint();
	DECLARE_MESSAGE_MAP()
private:
	void ShowGraph(void);
	int m_iCount;
};
 
This is the bit of c++ code that handles it:
 
// GraphDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Eerste.h"
#include "Graph.h"

IMPLEMENT_DYNAMIC(CGraph, CWnd)
 
TCHAR CGraph::m_szWndClass[] = _T("GraphClass");
 
BEGIN_MESSAGE_MAP(CGraph, CWnd)
	ON_WM_PAINT()
END_MESSAGE_MAP()
 
CGraph::CGraph()
{
	RegisterWndClass();
	m_iCount = 0;
}
 
CGraph::~CGraph()
{
}
 
BOOL CGraph::RegisterWndClass()
{
	WNDCLASS wndclass;
	if (::GetClassInfo(AfxGetInstanceHandle(),m_szWndClass, &wndclass))
		return TRUE;
	wndclass.style = 0;
	wndclass.lpfnWndProc = ::DefWindowProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = ::AfxGetInstanceHandle();
	wndclass.hIcon = NULL;
	wndclass.hCursor = NULL;
	wndclass.hbrBackground = NULL;
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = m_szWndClass;
	return::AfxRegisterClass(&wndclass);
}
 
void CGraph::OnPaint()
{
	ShowGraph();
	CWnd::OnPaint();
	int fdtest =1;
}
 
void CGraph::ShowGraph(void)
{
	RECT rect;
	GetClientRect(&rect);
	CPaintDC dc (this);
	dc.SetWindowExt(rect.left,rect.bottom);
	CPen lpen(PS_SOLID, 1, RGB(255, 0, 0));
	dc.SelectObject(&lpen);
	m_iCount +=10;
	dc.LineTo(100,m_iCount);
}
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 195
1 ProgramFOX 130
2 Maciej Los 105
3 Sergey Alexandrovich Kryukov 85
4 Afzaal Ahmad Zeeshan 82
0 OriginalGriff 6,564
1 Sergey Alexandrovich Kryukov 6,048
2 DamithSL 5,228
3 Manas Bhardwaj 4,717
4 Maciej Los 4,150


Advertise | Privacy | Mobile
Web01 | 2.8.1411022.1 | Last Updated 19 Dec 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100