Click here to Skip to main content
15,880,972 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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:

C++
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

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
 
Share this answer
 
v2
Comments
fd9750 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 18-Dec-12 10:17am    
Which WM_PAINT? WM_PAINT for the dialog or the picture control?
fd9750 18-Dec-12 10:25am    
the WM_PAINT for the dialog
Espen Harlinn 18-Dec-12 10:42am    
Then you can't use CPaintDC for the picture control
fd9750 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.
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.
 
Share this answer
 
v2
Comments
Espen Harlinn 18-Dec-12 9:52am    
That does sound about right, I initially wrote some gibberish ...
nv3 18-Dec-12 10:44am    
Thanks Espen!
fd9750 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 18-Dec-12 10:43am    
Please, see my additions above.
fd9750 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.
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:

C++
#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:

C++
// 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);
}
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900