求教CDC画图方法,倾我所有分,求大神指点下!!!

sharp0077 2016-01-15 10:27:04
简要说明下
在准备picture控件上画点图。
点的数据源是(时间,距离),如果图的坐标横向代表时间,则纵向代表距离。
小弟已知的画点方法如下
CDC *pdc = GetDlgItem(IDC_Pic)->GetDC();
pdc->LineTo(100,50); → 默认从pic左上角到100,50的两点连线
pdc->MoveTo(100,80); →只是移动没有做任何画图动作?
pdc->SetPixel(100,80,RGB(255,0,0)); →在该位置画有颜色的点

问题来了
因为pic是有大小限定的,
如果横向我设定时间是0-10000 秒,纵向是0-1000米
假如数据源是(1000秒,100米),我不可能是moveto(1000,100)吧? 会超出pic的范围,
所以
问题1:怎么按已知的坐标值来按比例移动、画点。

问题2:既然按比例来画点,如果像上面那样横坐标范围0-1万,但实际PIC假如只有100的长度,
当我准备画(1000,xxx)的时候是不是Moveto(100的十分之一也就是10,xxx),
SetPixel(10,xxx,RGB) XXX:暂且不论。
那么,数据(1001,xxx)怎么办,也是Moveto(10,xxx)吗,直到数据(1100,xxx)才
会moveto到(11,xxx)吗,也就是说有100秒的数据画在一个点?

还有个难点是坐标轴的数据范围是可变得,变换时要重画,当范围变小后可能都不需要按比例来

分不在多,望指教!
...全文
398 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-02-16
  • 打赏
  • 举报
回复
搜“GDI泄露检测”
vtison 2016-02-14
  • 打赏
  • 举报
回复
我还真没读懂你想表达什么,想做出一个什么样的效果
  • 打赏
  • 举报
回复
所有你create的都要 .DeleteObject(); 不管是什么pen brush font 等等。那里创建,用完就那里释放。绝不会泄漏 CFont font1; font1.CreateFont(15,6,0,0,FW_REGULAR,FALSE,FALSE,0,ANSI_CHARSET,OUT_STROKE_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_SWISS,"Arial"); CFont* def_font1=pDC->SelectObject(&font1); pDC->TextOut(width/2,height-20,"时间(h)"); pDC->TextOut(m_rowX-m_x_x-8,height-22,"(A)"); pDC->TextOut(m_rowX-8,height-22,"(V)"); pDC->SelectObject(def_font1); font1.DeleteObject();没有这句绝对泄漏。创建竟然没释放。和蛇一样,不管多贪吃,整个吞掉。也得蜕皮啊 宋世鹏宇宙信息网
schlafenhamster 2016-01-22
  • 打赏
  • 举报
回复
直接使用 CScrollView 更好。
schlafenhamster 2016-01-22
  • 打赏
  • 举报
回复
void CCsvPaintView::DoDrawPos() { //USES_CONVERSION; CPaintDC dc(this); 怎么 又是一个 CPaintDC ? 通过 参数 传递 !
Eleven 2016-01-22
  • 打赏
  • 举报
回复
引用 9 楼 sharp0077 的回复:
[quote=引用 8 楼 paschen 的回复:] 在一些画图控件里画 如TeeChart
目前状况: 雏形画图雏形已有,但碰到一个问题,就是刷新画面问题, 调用Invalidate(), 重新描绘,看断点是在走Onpaint 前两次描绘没问题,多次Invalidate后 整个对话框上的控件都无效了(button,edit,picture等) 点击一下按钮的位置,按钮显示出来了 求大神们指点下 [/quote] 你的代码中是不是存在GDI资源泄露的情况,自己好好检查一下~
sharp0077 2016-01-22
  • 打赏
  • 举报
回复
17楼补充解释: onpaint里画的都是固定的,不做变动的 真正需要重画的时最后调用的DoDrawPos();
sharp0077 2016-01-22
  • 打赏
  • 举报
回复
引用 16 楼 schlafenhamster 的回复:
你是 在 对话框上 重绘 IDC_PosPic, CPaintDC dc(this); 已经使IDC_PosPic 窗口无效, 但 IDC_PosPic 窗口重绘 在 对话框 OnPaint 后。 CWnd *pWndPos = GetDlgItem(IDC_PosPic); CDC *pdcPos = pWndPos->GetDC();// 这是 客户区 DC,这时的 重绘 会 无效。 1. 派生 CStatic 在 CYourStatic 的 OnPaint 中 重绘 2 对话框上 重绘 要 CWnd *pWndPos = GetDlgItem(IDC_PosPic); pWndPos->UpdateWindow();// 强迫 IDC_PosPic 窗口 有效 CDC *pdcPos = pWndPos->GetDC();// 这是 客户区 DC
单文档工程,在formVIEW上画的,之前代码有点乱
void CCsvPaintView::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	int nPicLength = 450;
	int nPicHeight = 100;
	int nPicVelHeight = 102;
	int nPosRow = 5;
	CWnd *pWndPos = GetDlgItem(IDC_PosPic);
	CDC *pdcPos = pWndPos->GetDC();
	pWndPos->SetWindowPos(NULL,0,0,nPicLength,nPicHeight,SWP_NOMOVE|SWP_NOREDRAW);
	for(int i = 1; i<nPosRow;i++)
	{
		pdcPos->MoveTo(0,nPicHeight/nPosRow*i-1);
		pdcPos->LineTo(nPicLength- 1,nPicHeight/nPosRow*i-1);
	}

	for(int i = 1;i<6;i++)
	{
		pdcPos->MoveTo(nPicLength-1,nPicHeight/6*i);
		pdcPos->LineTo(nPicLength-5,nPicHeight/6*i);
	}

	int nVelRow = 6;
	CWnd *pWndVel = GetDlgItem(IDC_VelPic);
	pWndVel->SetWindowPos(NULL,0,0,nPicLength,nPicVelHeight,SWP_NOMOVE|SWP_NOREDRAW);
	CDC *pdcVel = pWndVel->GetDC();
	for(int i = 1; i<nVelRow;i++)
	{
		pdcVel->MoveTo(0,nPicVelHeight/nVelRow*i-1);
		pdcVel->LineTo(nPicLength- 1,nPicVelHeight/nVelRow*i-1);
	}

	int nAccRow = 5;
	CWnd *pWndAcc = GetDlgItem(IDC_AccPic);
	CDC *pdcAcc = pWndAcc->GetDC();
	pWndAcc->SetWindowPos(NULL,0,0,nPicLength,nPicHeight,SWP_NOMOVE|SWP_NOREDRAW);
	for(int i = 1; i<nAccRow;i++)
	{
		pdcAcc->MoveTo(0,nPicHeight/nAccRow*i-1);
		pdcAcc->LineTo(nPicLength- 1,nPicHeight/nAccRow*i-1);
	}
	for(int i = 1;i<6;i++)
	{
		pdcAcc->MoveTo(nPicLength-1,nPicHeight/6*i);
		pdcAcc->LineTo(nPicLength-5,nPicHeight/6*i);
	}

	DoDrawPos();
}
void CCsvPaintView::DoDrawPos()
{
	//USES_CONVERSION;
	CPaintDC dc(this);
	CDC *pdc = GetDlgItem(IDC_PosPic)->GetDC();
	CString strTimeMin;
	CString strTimeMax;
	CString strPosMin;
	CString strPosMax;
	int nTimeMin=0;
	int nTimeMax=0;
	int nPosMin=0;
	int nPosMax=0;
	GetDlgItemText(IDC_Time_Pos_Min,strTimeMin);
	GetDlgItemText(IDC_Time_Pos_Max,strTimeMax);
	GetDlgItemText(IDC_PosMin,strPosMin);
	GetDlgItemText(IDC_PosMax,strPosMax);
	nTimeMin = atoi(strTimeMin);
	nTimeMax = atoi(strTimeMax);
	nPosMin = atoi(strPosMin);
	nPosMax = atoi(strPosMax);
	int nPeriod = GetDocument()->GetPeriod();
	int nStart =0;
	int nEnd =0;
	nStart =  nTimeMin*1000/nPeriod;
	nEnd =  nTimeMax*1000/nPeriod;
	for(int i = nStart;i<nEnd;i++)
	{
		if(i>=m_vActPos.size())
		{
			break;
		}
		int nActPosVal = m_vActPos[i];
		if(nActPosVal>nPosMax || nActPosVal < nPosMin)
		{
			continue;
		}
		int nTransPicPos =  (nPosMax-nActPosVal)*100/*Height*//(nPosMax-nPosMin);
		//int nPosTime =  nStart;
		int nTransPicTime = (i-nStart)*450/(nEnd-nStart);
		//if(nTransPicTime != 0)
		//{
		//	break;
		//}
		//pdc->SetPixel(nTransPicTime,nTransPicPos,RGB(255,0,0));
		HPEN hp;
		hp= CreatePen(0,1,RGB(0,0,255));
		pdc->SelectObject(hp);
		pdc->LineTo(nTransPicTime,nTransPicPos);

	}
}
schlafenhamster 2016-01-21
  • 打赏
  • 举报
回复
你是 在 对话框上 重绘 IDC_PosPic, CPaintDC dc(this); 已经使IDC_PosPic 窗口无效, 但 IDC_PosPic 窗口重绘 在 对话框 OnPaint 后。 CWnd *pWndPos = GetDlgItem(IDC_PosPic); CDC *pdcPos = pWndPos->GetDC();// 这是 客户区 DC,这时的 重绘 会 无效。 1. 派生 CStatic 在 CYourStatic 的 OnPaint 中 重绘 2 对话框上 重绘 要 CWnd *pWndPos = GetDlgItem(IDC_PosPic); pWndPos->UpdateWindow();// 强迫 IDC_PosPic 窗口 有效 CDC *pdcPos = pWndPos->GetDC();// 这是 客户区 DC
sharp0077 2016-01-21
  • 打赏
  • 举报
回复
引用 13 楼 paschen 的回复:
[quote=引用 9 楼 sharp0077 的回复:]
[quote=引用 8 楼 paschen 的回复:]
在一些画图控件里画 如TeeChart


目前状况:

雏形画图雏形已有,但碰到一个问题,就是刷新画面问题,
调用Invalidate(),
重新描绘,看断点是在走Onpaint
前两次描绘没问题,多次Invalidate后 整个对话框上的控件都无效了(button,edit,picture等)
点击一下按钮的位置,按钮显示出来了

求大神们指点下
[/quote]

nvalidateRect() 无效区域仅设置为你作图区域[/quote]


好的,我试试看
sharp0077 2016-01-21
  • 打赏
  • 举报
回复
引用 12 楼 schlafenhamster 的回复:
上 OnPaint 代码吧,


CPaintDC dc(this); // device context for painting

int nPicLength = 450;
int nPicHeight = 100;
int nPicVelHeight = 102;
int nPosRow = 5;
CWnd *pWndPos = GetDlgItem(IDC_PosPic);
CDC *pdcPos = pWndPos->GetDC();
pWndPos->SetWindowPos(NULL,0,0,nPicLength,nPicHeight,SWP_NOMOVE|SWP_NOREDRAW);
for(int i = 1; i<nPosRow;i++)
{
pdcPos->MoveTo(0,nPicHeight/nPosRow*i-1);
pdcPos->LineTo(nPicLength- 1,nPicHeight/nPosRow*i-1);
}

for(int i = 1;i<6;i++)
{
pdcPos->MoveTo(nPicLength-1,nPicHeight/6*i);
pdcPos->LineTo(nPicLength-5,nPicHeight/6*i);
}

int nVelRow = 6;
CWnd *pWndVel = GetDlgItem(IDC_VelPic);
pWndVel->SetWindowPos(NULL,0,0,nPicLength,nPicVelHeight,SWP_NOMOVE|SWP_NOREDRAW);
CDC *pdcVel = pWndVel->GetDC();
for(int i = 1; i<nVelRow;i++)
{
pdcVel->MoveTo(0,nPicVelHeight/nVelRow*i-1);
pdcVel->LineTo(nPicLength- 1,nPicVelHeight/nVelRow*i-1);
}

int nAccRow = 5;
CWnd *pWndAcc = GetDlgItem(IDC_AccPic);
CDC *pdcAcc = pWndAcc->GetDC();
pWndAcc->SetWindowPos(NULL,0,0,nPicLength,nPicHeight,SWP_NOMOVE|SWP_NOREDRAW);
for(int i = 1; i<nAccRow;i++)
{
pdcAcc->MoveTo(0,nPicHeight/nAccRow*i-1);
pdcAcc->LineTo(nPicLength- 1,nPicHeight/nAccRow*i-1);
}
for(int i = 1;i<6;i++)
{
pdcAcc->MoveTo(nPicLength-1,nPicHeight/6*i);
pdcAcc->LineTo(nPicLength-5,nPicHeight/6*i);
}
//上面的时画图用的坐标画面
DoDrawPos();
}
//下面函数是真正要重画的地方
void CCsvPaintView::DoDrawPos()
{
//USES_CONVERSION;
CPaintDC dc(this);
CDC *pdc = GetDlgItem(IDC_PosPic)->GetDC();
CString strTimeMin;
CString strTimeMax;
CString strPosMin;
CString strPosMax;
int nTimeMin=0;
int nTimeMax=0;
int nPosMin=0;
int nPosMax=0;
GetDlgItemText(IDC_Time_Pos_Min,strTimeMin);
GetDlgItemText(IDC_Time_Pos_Max,strTimeMax);
GetDlgItemText(IDC_PosMin,strPosMin);
GetDlgItemText(IDC_PosMax,strPosMax);
nTimeMin = atoi(strTimeMin);
nTimeMax = atoi(strTimeMax);
nPosMin = atoi(strPosMin);
nPosMax = atoi(strPosMax);
int nPeriod = GetDocument()->GetPeriod();
int nStart =0;
int nEnd =0;
nStart = nTimeMin*1000/nPeriod;
nEnd = nTimeMax*1000/nPeriod;
for(int i = nStart;i<nEnd;i++)
{
if(i>=m_vActPos.size())
{
break;
}
int nActPosVal = m_vActPos[i];
if(nActPosVal>nPosMax || nActPosVal < nPosMin)
{
continue;
}
int nTransPicPos = (nPosMax-nActPosVal)*100/*Height*//(nPosMax-nPosMin);
//int nPosTime = nStart;
int nTransPicTime = (i-nStart)*450/(nEnd-nStart);
HPEN hp;
hp= CreatePen(0,1,RGB(0,0,255));
pdc->SelectObject(hp);
pdc->LineTo(nTransPicTime,nTransPicPos);

}
}
paschen 2016-01-21
  • 打赏
  • 举报
回复
引用 9 楼 sharp0077 的回复:
[quote=引用 8 楼 paschen 的回复:] 在一些画图控件里画 如TeeChart
目前状况: 雏形画图雏形已有,但碰到一个问题,就是刷新画面问题, 调用Invalidate(), 重新描绘,看断点是在走Onpaint 前两次描绘没问题,多次Invalidate后 整个对话框上的控件都无效了(button,edit,picture等) 点击一下按钮的位置,按钮显示出来了 求大神们指点下 [/quote] nvalidateRect() 无效区域仅设置为你作图区域
schlafenhamster 2016-01-21
  • 打赏
  • 举报
回复
上 OnPaint 代码吧,
schlafenhamster 2016-01-21
  • 打赏
  • 举报
回复
还是 Onpaint 问题
sharp0077 2016-01-21
  • 打赏
  • 举报
回复
引用 10 楼 schlafenhamster 的回复:
还是 Onpaint 问题


前3次没问题,多次后出错,走到CPaintDC dc(this); 时 走进AfxCallWndProc的异常处理里面了
sharp0077 2016-01-21
  • 打赏
  • 举报
回复
引用 8 楼 paschen 的回复:
在一些画图控件里画 如TeeChart


目前状况:

雏形画图雏形已有,但碰到一个问题,就是刷新画面问题,
调用Invalidate(),
重新描绘,看断点是在走Onpaint
前两次描绘没问题,多次Invalidate后 整个对话框上的控件都无效了(button,edit,picture等)
点击一下按钮的位置,按钮显示出来了

求大神们指点下
paschen 2016-01-18
  • 打赏
  • 举报
回复
在一些画图控件里画 如TeeChart
搬砖的奶霸 2016-01-18
  • 打赏
  • 举报
回复
重写个控件吧 时间轴和距离轴可以调的 我这里前后2图鼠标移动双击改变起始坐标点轴步进单位
搬砖的奶霸 2016-01-18
  • 打赏
  • 举报
回复
chat 控件 CSDN有资源能下载
sharp0077 2016-01-17
  • 打赏
  • 举报
回复
人工顶上,望更多的建议和帮助
加载更多回复(4)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧