Работа с GDI - помогите справиться с проблемой

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Аватара пользователя
MDCI
Сообщения: 47
Зарегистрирован: 28 фев 2006, 15:25
Откуда: Симферополь
Контактная информация:

Помогите справиться с проблемой.
Создаю элемент управления, который будет строить графики.

Код: Выделить всё

class GraphWindow: public CStatic
{
public:
	GraphWindow();
	~GraphWindow();
	void CreateGraph();
	CDC* dc;
};


void GraphWindow::CreateGraph()
{
	CWnd* globalWindow=this->GetParent();
	CRect rc;
	globalWindow->GetClientRect(&rc);
	dc=this->GetDC();
	dc->BeginPath();
	POINT pt;
	pt.x=pt.y=10;
	LOGBRUSH logBrush;
	logBrush.lbStyle=BS_SOLID;
	logBrush.lbColor=RGB(0, 0, 255);
	CPen pn(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_ROUND, 16, &logBrush);
	CPen* pOldPen=dc->SelectObject(&pn);
	dc->MoveTo(pt);
	pt.x=pt.y=100;
	dc->LineTo(pt);
	dc->EndPath();
	dc->StrokePath();
	dc->SelectObject(pOldPen);

	CBrush pBrush(RGB(0, 0, 255));
	dc->FillRect(&rc, &pBrush);
	InvalidateRect(rc, FALSE);
}
При этом ничего не отображается. Класс инициализируется как переменная в функции DoDataExchange
В CView вроде должно работать, в CDialog видимо возникает проблема.
Подскажите, как исправить проблему.
Аватара пользователя
Decoder
Сообщения: 308
Зарегистрирован: 19 фев 2008, 23:11
Откуда: Moscow

Здесь непонятно, в какой момент вызывается метод GraphWindow::CreateGraph().
Для прорисовки чего-либо в окне используется обработчик сообщения WM_PAINT.
В MFC это метод OnPaint() (или OnDraw() для классов, производных от CView).
Если используешь метод OnPaint(), то для в нём нужно использовать класс CPaintDC вместо CDC.
Поумнеть несложно, куда труднее от дури избавиться.
Аватара пользователя
MDCI
Сообщения: 47
Зарегистрирован: 28 фев 2006, 15:25
Откуда: Симферополь
Контактная информация:

Все спасибо, проблема решена...
Аватара пользователя
MDCI
Сообщения: 47
Зарегистрирован: 28 фев 2006, 15:25
Откуда: Симферополь
Контактная информация:

Еще один вопрос:
При работе с элементом графиков (все уже прорисовывается) панель инструментов не реагирует на мышь, а при выборе пунктов меню программа вообще зависает. Может прорисовку отправить в поток (даже не знаю, как будет работать - из OnPaint постоянно запускать поток?...)
Пробывал ставить Sleep(1) - не помогает.
Никто не может сказать, в чем причина?
Аватара пользователя
Decoder
Сообщения: 308
Зарегистрирован: 19 фев 2008, 23:11
Откуда: Moscow

Не должно быть так. Выкладывай код - посмотрим.
Поумнеть несложно, куда труднее от дури избавиться.
Аватара пользователя
MDCI
Сообщения: 47
Зарегистрирован: 28 фев 2006, 15:25
Откуда: Симферополь
Контактная информация:

В прорисовке - ничего необычного - создается координатная сетка.
У меня окно разделено на две вкладки - на первой нет прорисовки, на второй соответсвенно прорисовка графика.
добавил событие Dlg::OnSetFocus(CWnd* pOldWnd) чтобы окно обновлялось при восстановлении (без этого не обновляется)
приведу код прорисовки:

Код: Выделить всё

class GraphWindow: public CStatic
{
	DECLARE_DYNAMIC(GraphWindow)

public:
	GraphWindow();
	~GraphWindow();
	void CreateGraph();
	//CDC* dc;
	bool updateGraph;
	afx_msg void OnPaint();
	void UpdateGraphicNet(CDC* pdc);

	double CenterX, CenterY;
	double GraphStep;
protected:
	DECLARE_MESSAGE_MAP()

};


GraphWindow::GraphWindow()
{
	updateGraph=true;
	CenterX=CenterY=0;
	GraphStep=10;
}

GraphWindow::~GraphWindow()
{
}

IMPLEMENT_DYNAMIC(GraphWindow, CStatic)

BEGIN_MESSAGE_MAP(GraphWindow, CStatic)
	ON_WM_PAINT()
END_MESSAGE_MAP()


void GraphWindow::CreateGraph()
{
}

void GraphWindow::OnPaint()
{
	static int sv=-1;
	//if (updateGraph)
	{
		//dc=this->GetDC();
		CPaintDC dc(this);
		if (sv!=-1) dc.RestoreDC(sv);
		UpdateGraphicNet(&dc);
		sv=dc.SaveDC();
		updateGraph=false;
	}
}

void GraphWindow::UpdateGraphicNet(CDC* pdc)
{
	CRect rc, rc1;
	GetClientRect ( rc );

	CDC cdcMemory;
	CBitmap cBmpMemory;
	CBitmap *pOldMemBmp = NULL;
	cdcMemory.CreateCompatibleDC(pdc);
	VERIFY(cBmpMemory.CreateCompatibleBitmap(pdc, rc.Width(), rc.Height()));
	pOldMemBmp = cdcMemory.SelectObject(&cBmpMemory);


	CBrush pBrush(RGB(255, 255, 255));
	cdcMemory.FillRect(&rc, &pBrush);
	GetWindowRect(&rc1);
	//cdcMemory.SetBkColor(RGB(255, 255, 255));
	POINT pt, pt1;
	int _step=0;
	int i=0, j=0, k=0;
	double xnum=0;
	LOGBRUSH logBrush;
	logBrush.lbStyle=BS_SOLID;
	logBrush.lbColor=RGB(0, 0, 0);
	CPen pen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_ROUND, 2, &logBrush);
	CPen* pOldPen=cdcMemory.SelectObject(&pen);
	pt.x=0; pt.y=rc1.Height()/2;
	cdcMemory.MoveTo(pt);
	pt.x=rc1.Width();
	cdcMemory.LineTo(pt);
	_step=(rc1.Width() > rc1.Height() ? rc1.Height() : rc1.Width()) / (2*GraphStep);
	j=rc1.Width()/_step;
	k=rc1.Height()/_step;

	
	pt.x=rc1.Width()/2; pt.y=rc1.Height()/2;
	for (i=1;i<=j;i++)
	{
		pt1.x=pt.x+i*_step; pt1.y=pt.y-10;
		cdcMemory.MoveTo(pt1);
		pt1.x=pt.x+i*_step; pt1.y=pt.y+10;
		cdcMemory.LineTo(pt1);
	}
	for (i=1;i<=j;i++)
	{
		pt1.x=pt.x-i*_step; pt1.y=pt.y-10;
		cdcMemory.MoveTo(pt1);
		pt1.x=pt.x-i*_step; pt1.y=pt.y+10;
		cdcMemory.LineTo(pt1);
	}

	pt.x=rc1.Width()/2; pt.y=0;
	cdcMemory.MoveTo(pt);
	pt.y=rc1.Height();
	cdcMemory.LineTo(pt);

	pt.x=rc1.Width()/2; pt.y=rc1.Height()/2;
	for (i=1;i<=k;i++)
	{
		pt1.y=pt.y+i*_step; pt1.x=pt.x-10;
		cdcMemory.MoveTo(pt1);
		pt1.y=pt.y+i*_step; pt1.x=pt.x+10;
		cdcMemory.LineTo(pt1);
	}
	for (i=1;i<=k;i++)
	{
		pt1.y=pt.y-i*_step; pt1.x=pt.x-10;
		cdcMemory.MoveTo(pt1);
		pt1.y=pt.y-i*_step; pt1.x=pt.x+10;
		cdcMemory.LineTo(pt1);
	}
	//dc->EndPath();
	//cdcMemory.StrokePath();
	cdcMemory.SelectObject(pOldPen);

	CFont font;
	font.CreateFont(10, 10, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, 
		OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T("Times New Roman"));
	CFont* pOldFont=cdcMemory.SelectObject(&font);
	cdcMemory.SetTextColor(RGB(0, 0, 0));

	pt.x=rc1.Width()/2; pt.y=rc1.Height()/2;
	LPWSTR wstrNum=NULL;
	for (i=1;i<=j;i++)
	{
		pt1.x=pt.x+i*_step; pt1.y=pt.y+20;
		//pdc->MoveTo(pt1);
		xnum=CenterX+i*GraphStep;
		wstrNum=_toWSTR(xnum);
		cdcMemory.TextOut(pt1.x, pt1.y, wstrNum, wcslen(wstrNum));
	}
	for (i=1;i<=j;i++)
	{
		pt1.x=pt.x-i*_step; pt1.y=pt.y+20;
		//pdc->MoveTo(pt1);
		xnum=CenterX-i*GraphStep;
		wstrNum=_toWSTR(xnum);
		cdcMemory.TextOut(pt1.x, pt1.y, wstrNum, wcslen(wstrNum));
	}



	for (i=1;i<=k;i++)
	{
		pt1.y=pt.y+i*_step; pt1.x=pt.x-40;
		//pdc->MoveTo(pt1);
		xnum=CenterY+i*GraphStep;
		wstrNum=_toWSTR(xnum);
		cdcMemory.TextOut(pt1.x, pt1.y, wstrNum, wcslen(wstrNum));
	}
	for (i=1;i<=k;i++)
	{
		pt1.y=pt.y-i*_step; pt1.x=pt.x-40;
		//pdc->MoveTo(pt1);
		xnum=CenterY-i*GraphStep;
		wstrNum=_toWSTR(xnum);
		cdcMemory.TextOut(pt1.x, pt1.y, wstrNum, wcslen(wstrNum));
	}

	cdcMemory.SelectObject(pOldFont);


	//this->ReleaseDC(dc);
	//this->UpdateWindow();
	//this->EndPaint(&paint);
	InvalidateRect(rc, FALSE);

	pdc->BitBlt(0, 0, rc.Width(), rc.Height(), &cdcMemory, 0, 0, SRCCOPY);
	if (pOldMemBmp) cdcMemory.SelectObject( pOldMemBmp );
	cBmpMemory.DeleteObject();      // can be skiped, will be done by destructor
	cdcMemory.DeleteDC();           // can be skiped, will be done by destructor
	Sleep(1);
}



На первой вкладке с панелью иструментов и меню все нормально - реакция есть, на второй - нету (только меню открывается, при выборе пункта меню (если вызывается диалоговое окно) программа зависает)
Аватара пользователя
Decoder
Сообщения: 308
Зарегистрирован: 19 фев 2008, 23:11
Откуда: Moscow

В методе UpdateGraphicNet(CDC* pdc) нужно убрать строчку InvalidateRect(rc, FALSE);
Sleep(1) тоже здесь не нужен.
А в методе OnPaint() ты перепутал местами SaveDC() и RestoreDC(), лучше пока вообще их закомментируй.

Это пока то, что лежит на поверхности, более детально в код не вникал.
Поумнеть несложно, куда труднее от дури избавиться.
Аватара пользователя
MDCI
Сообщения: 47
Зарегистрирован: 28 фев 2006, 15:25
Откуда: Симферополь
Контактная информация:

Прирорисовку я в поток пустил - пока все работает (меню и панель иструментов отвечают)
Ответить