Pot sa fac un desen dinamic intr-un dialog?

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 15:18

Vreau sa fac niste diagrame intr-o fereastra de dialog (un semicerc si niste diagrame pe el), si am gasit niste functii in CDC care stiu sa deseneze puncte, linii, etc. Intrebarea e: pot sa fac desenul intr-o fereastra de dialog, si nu in fereastra programului? si ar mai fi ceva... as vrea sa creez si un "guguloi", care sa fie pe semicerc, si pe care sa-l pot muta cu mouseul, ca sa aflu valorile din diagrama, in orice punct de pe cerc. E facubila treaba, sau sa ma las?
Mersi.

http://a.imagehost.org/0303/diagrame.png (scuze, dar n-am stiut cum altfel sa pun poza, tinand cont ca era un pic cam maricica)

Edit: CWindowDC, nu CDC :)



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by Ovidiu Cucu » 16 May 2010, 16:11

adi0149 wrote: E facubila treaba, sau sa ma las?
E facubila, nu te lasa! ;)
O mica observatie de inceput. Desi ca in orice alta fereastra poti picta daca asa vrea muschii tai, totusi un dialog e o ferestra ceva mai speciala careia ii sta bine cu controale (butonele, ediboxuri, etc) si nu-i o idee prea grozava sa pictezi direct in ea.
Deci un pic mai bine e sa pui acele grafice contraole custom sau ActiveX.
Daca astea-ti suna prea exotic, poti incerca si in controale de tip static (picture).
Deci derivezi din CStatic, handluiesti WM_PAINT di incepi sa desenazi, sa zicem...

Code: Select all

void CMyStatic::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    CRect rc;
    GetClientRect(rc);
    dc.Ellipse(rc);
    // etc...
}
Guguloiul il muti pe handlerele de la mouse.
Bafta si la treaba! :D

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 16:14

Am incercat asa:

Am facut o fereastra de dialog maaaare (IDD_TEST_DLG) si in ea am pus un GroupBox (IDC_TEST) tot foarte mare (sa fiu sigur ca nu desenez pe langa).

Apoi, in OnInitDialog al lui TestDlg, am bagat

Code: Select all

myDC = GetDlgItem(IDC_TEST)->GetDC();
CRect rect;
GetDlgItem(IDC_TEST)->GetWindowRect(&rect);
ScreenToClient(&rect);
myDC->DrawTextW(_T("TEEEEEEEEEEEEEEEEEXT"),20,rect,0);             //     unde CDC *myDC;

	CPoint points[1000],points2[2001],points3[1000]; int count=0;
	for (float i=0; i<M_PI; i=i+0.001*M_PI)
	{
		points[count].x=100+10*sinf(i);
		points[count].y=100+10*cosf(i);

			points3[count].x=100+(10-(15*cosf(i)+25)*sinf(i))*sinf(i);
			points3[count].y=100+(10-(15*cosf(i)+25)*sinf(i))*cosf(i);

		count++;
	}
	myDC->Polyline(points,1000);
	myDC->Polyline(points3,1000);
Am incercat sa printez si text, si polylinii, nu se vede nimic.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by Ovidiu Cucu » 16 May 2010, 16:22

adi0149 wrote:Am incercat asa:

Am facut o fereastra de dialog maaaare (IDD_TEST_DLG) si in ea am pus un GroupBox (IDC_TEST) tot foarte mare (sa fiu sigur ca nu desenez pe langa).

Apoi, in OnInitDialog al lui TestDlg, am bagat
[...]
Am incercat sa printez si text, si polylinii, nu se vede nimic.
Pai, dialogul devine vizibil si implicit se picteaza cu ce vrea el abia dupa ce iese in OnInitDialog.
In general nu e bine sa pictezi in alta parte decat in handlerul lui WM_PAINT (OnPaint).
Fa cum ti-am spus eu si-ai sa vezi c-o sa inceapa sa se vada...

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 16:24

@Ovidiu: Nu vazusem raspunsul tau can am postat a doua oara.

Hai sa-ti zic ce-am inteles:

Fac o clasa care sa deseneze intr-un control static, iar apoi incerc sa chem OnPaint in clasa dialogului meu, atribuindu-i IDC-ul controlului in care vreau sa apara desenul (Group Box sau Picture Control).

Sper ca e bine. Oricum... chiar si-asa nici nu stiu cum sa-ncep :P
O sa-mi prind un pic urechile... nu ma las!
Mersi

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by Ovidiu Cucu » 16 May 2010, 16:32

adi0149 wrote:Fac o clasa care sa deseneze intr-un control static, iar apoi incerc sa chem OnPaint in clasa dialogului meu, atribuindu-i IDC-ul controlului in care vreau sa apara desenul (Group Box sau Picture Control).
Never ever call OnPaint!
In plus, e putin mai inginereste sa-ti faci un control si respectiv o clasa pentru grafic, care sa-si vada singura de treaba si sa lase dialogul tatic (care deja vad din poza ca-i foarte ocupat) sa mai rasufle.

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 18:12

Am inclus afx_msg void OnPaint(); in header si am bagat

Code: Select all

void CTestDlg::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	CPoint PtLine[] = { CPoint( 50,  50), CPoint(670,  50),
			  CPoint(670, 310), CPoint(490, 310),
			  CPoint(490, 390), CPoint(220, 390),
			  CPoint(220, 310), CPoint( 50, 310), 
			  CPoint( 50,  50) };

	dc.MoveTo(PtLine[0]);
	dc.LineTo(PtLine[1]);
	dc.LineTo(PtLine[2]);
	dc.LineTo(PtLine[3]);
	dc.LineTo(PtLine[4]);
	dc.LineTo(PtLine[5]);
	dc.LineTo(PtLine[6]);
	dc.LineTo(PtLine[7]);
	dc.LineTo(PtLine[8]);
}
in .cpp si nu deseneaza nimic. Am pus un breakpoint in el si nu se opreste. Cum il fac sa intre in OnPaint()-ul creat de mine?

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 19:46

A... m-am prins... Uitam sa declar ON_WM_PAINT(). Merge acum :)
Ar mai fi ceva... pot sa fac in asa fel incat device contextul sa nu fie fereastra de dialog, ci un static control din ea? Adica... daca printez un punct in 0,0 sa nu fie in stanga sus al ferestrei, ci in stanga sus al controlului.
Mersi.

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 22:26

M-am prins si de asta. Se pare ca o zi de scarpinat in crestet a dat roade :) Am facut asa:

Code: Select all

void CTestDlg::OnPaint()
{
	CPaintDC dc(this); // device context for painting

    CRect rect;
    GetDlgItem(IDC_STATIC_TEST)->GetWindowRect(&rect);  // Unde IDC_STATIC_TEST e IDul controlului static de tip Group Box
    ScreenToClient(&rect);

	CPoint points[1000]; int count=0;
	for (float i=0; i<M_PI; i=i+0.001*M_PI)                          // bucla pentru desenarea unui semicerc cu centrul in centrul controlului 
	{                                                                //si cu raza fiind minimul dintre rec.Height si rec. Width supra 3.
		points[count].x=rect.CenterPoint().x+(min((float)rect.Width(),(float)rect.Height())/(3.0f))*sinf(i);
		points[count].y=rect.CenterPoint().y+(min((float)rect.Width(),(float)rect.Height())/(3.0f))*cosf(i);

		count++;
	}
	dc.Polyline(points,1000);
}

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by cristianamarie » 16 May 2010, 22:29

adi0149 wrote:A... m-am prins... Uitam sa declar ON_WM_PAINT(). Merge acum :)
Ar mai fi ceva... pot sa fac in asa fel incat device contextul sa nu fie fereastra de dialog, ci un static control din ea? Adica... daca printez un punct in 0,0 sa nu fie in stanga sus al ferestrei, ci in stanga sus al controlului.
Mersi.
derivezi o clasa din CStatic, la fel ON_WM_PAINT si cu staticul, si folosit in dialog.
Nuclear launch detected

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 16 May 2010, 22:50

excat asta fac acum. Imi creez o clasa, derivata din CStatic, care sa contina functiile pe care o sa le folosesc eu la desenarea diagramelor. Si apoi o chem in dialogu meu. Sper sa-mi iasa. :)

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 17 May 2010, 10:18

S-ar parea ca lucrurile nu sunt asa de simple cum am crezut :)

Am facut o clasa CDiagramCtrl derivata din CStatic. Scuze, dar o sa pun tot headerul si .cpp-ul, pentru ca nu stiu de unde vine eroarea...

header:

Code: Select all

#pragma once

// CDiagramCtrl

class CDiagramCtrl : public CStatic
{
	DECLARE_DYNAMIC(CDiagramCtrl)

public:
	CDiagramCtrl();
	virtual ~CDiagramCtrl();

	virtual void OnFinalRelease();
	float teta;
	CRect rect;
	int nID;
	void DrawPipe(CPaintDC PDC, CRect rect);
	void DrawPositionLine(CPaintDC PDC, CRect rect, float teta);

protected:
	float GetRadius(CRect rect);
	DECLARE_MESSAGE_MAP()
	afx_msg void OnPaint();
	DECLARE_DISPATCH_MAP()
	DECLARE_INTERFACE_MAP()
};
.cpp:

Code: Select all

// DiagramCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "PipeDoctor.h"
#include "DiagramCtrl.h"
#include "math.h"

#define M_PI       3.14159265358979323846	// PI
#define M_1_PI     0.318309886183790671538	// 1/PI


// CDiagramCtrl

IMPLEMENT_DYNAMIC(CDiagramCtrl, CStatic)

CDiagramCtrl::CDiagramCtrl()
{
#ifndef _WIN32_WCE
	EnableActiveAccessibility();
#endif

	EnableAutomation();
}

CDiagramCtrl::~CDiagramCtrl()
{
}

void CDiagramCtrl::OnFinalRelease()
{
	CStatic::OnFinalRelease();
}


BEGIN_MESSAGE_MAP(CDiagramCtrl, CStatic)
	ON_WM_PAINT()
END_MESSAGE_MAP()


BEGIN_DISPATCH_MAP(CDiagramCtrl, CStatic)
END_DISPATCH_MAP()

// {C3156248-B41B-4A03-851C-86F6290E09B8}
static const IID IID_IDiagramCtrl =
{ 0xC3156248, 0xB41B, 0x4A03, { 0x85, 0x1C, 0x86, 0xF6, 0x29, 0xE, 0x9, 0xB8 } };

BEGIN_INTERFACE_MAP(CDiagramCtrl, CStatic)
	INTERFACE_PART(CDiagramCtrl, IID_IDiagramCtrl, Dispatch)
END_INTERFACE_MAP()


// CDiagramCtrl message handlers

void CDiagramCtrl::DrawPipe(CPaintDC PDC, CRect rect)
{
	CPoint points[500];
	int count=0;
	for (float i=0; i<M_PI; i=i+(1.0f/500)*M_PI)
	{
		points[count].x=rect.CenterPoint().x+GetRadius(rect)*sinf(i);
		points[count].y=rect.CenterPoint().y+GetRadius(rect)*cosf(i);

		count++;
	}
	PDC.Polyline(points,500);
}

void CDiagramCtrl::DrawPositionLine(CPaintDC PDC, CRect rect, float teta)
{
	CPoint points[2];
	float xc = rect.CenterPoint().x, yc = rect.CenterPoint().y;

	points[0].x=xc;
	points[0].y=yc;

	points[1].x=xc+sinf(teta)*GetRadius(rect);
	points[1].y=yc+cosf(teta)*GetRadius(rect);

	//HPEN hpen = CreatePen(PS_SOLID, 10, RGB(255, 0, 0));
 
	PDC.MoveTo(points[0]);
	PDC.LineTo(points[1]);

	//DeleteObject(hpen);
}

float CDiagramCtrl::GetRadius(CRect rect)
{
	return	(min((float)rect.Width(),(float)rect.Height())/(3.0f));
}

void CDiagramCtrl::OnPaint()
{
	CPaintDC PDC(this);
	GetDlgItem(nID)->GetWindowRect(&rect);
    ScreenToClient(&rect);
	DrawPipe(PDC,rect);
	DrawPositionLine(PDC,rect,teta);
}
iar atunci cand compilez, zice asa:

1>c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afxwin.h(963) : error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'
1> c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(561) : see declaration of 'CObject::CObject'
1> c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(532) : see declaration of 'CObject'
1> This diagnostic occurred in the compiler generated function 'CDC::CDC(const CDC &)'

Fac o greseala usor de corectat, sau intreaga abordare e gresita?
Ideea ar fi ca eu sa instantiez clasa asta in dialogul in care vreau s-o folosesc, sa atribui valori lui float teta si int nID; (unde nID ar fi ID-ul controlului static in care vreau sa desenez), iar el sa deseneze pentru mine. Si as mai crea o functie care sa-mi deseneze niste puncte luate dintr-un vector<structura definita de mine>v;
Probabil ca intrebarile mele par foarte stupide, dar nu am niciun fel de pregatire in programare si lucrurile mi se par foarte abigui.
Multumesc.

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 17 May 2010, 10:47

...am rezolvat si eroarea asta :)

DrawPipe(CPaintDC& PDC etc...
DrawPositionLine(CPaintDC& PDC etc...

Oricum... orice recomandare despre cum sa continui sau ce sa modific e bine venita :D

User avatar
adi0149
Membru
Membru
Posts: 65
Joined: 04 Aug 2009, 16:42
Judet: Bucureşti
Location: Bucuresti
Contact:

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by adi0149 » 17 May 2010, 12:03

Incerc sa creez controlul static facut in clasa CDiagramCtrl, in CDiagramsDlg::OnInitDialog() asa:

Code: Select all

   CPaintDC dc(this);
	m_Diagram.nID = IDC_AXIAL_DIAGRAMS;
	GetDlgItem(IDC_AXIAL_DIAGRAMS)->GetWindowRect(&m_Diagram.rect);
   ScreenToClient(&m_Diagram.rect);
	m_Diagram.Create(_T(""), WS_CHILD | WS_VISIBLE ,m_Diagram.rect,parent,IDC_AXIAL_DIAGRAMS);
compileaza, dar cand rulez si incerc sa deschid fereastra crapa:
Image

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Pot sa fac un desen dinamic intr-un dialog?

Post by cristianamarie » 17 May 2010, 12:29

adi0149 wrote:Incerc sa creez controlul static facut in clasa CDiagramCtrl, in CDiagramsDlg::OnInitDialog() asa:

Code: Select all

   CPaintDC dc(this);
	m_Diagram.nID = IDC_AXIAL_DIAGRAMS;
	GetDlgItem(IDC_AXIAL_DIAGRAMS)->GetWindowRect(&m_Diagram.rect);
   ScreenToClient(&m_Diagram.rect);
	m_Diagram.Create(_T(""), WS_CHILD | WS_VISIBLE ,m_Diagram.rect,parent,IDC_AXIAL_DIAGRAMS);
compileaza, dar cand rulez si incerc sa deschid fereastra crapa:
Image
Fara stack trace nu cred ca te poate ajuta cineva.
Nuclear launch detected

Post Reply