这么简单的代码,也无法绘制曲线,郁闷

combobox2013 2013-05-27 12:10:17
对话框的OnCtrlcolor里

if(this==pWnd)
{
CPen pen(PS_SOLID, 3,RGB(255,0,0));
pDC->SelectObject(&pen);
pDC->MoveTo(0,0);
pDC->LineTo(100,29);
}

结果绘制曲线失败, 什么原因?
求破
...全文
218 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
combobox2013 2013-05-29
  • 打赏
  • 举报
回复
引用 24 楼 schlafenhamster 的回复:
现在我们自己做: // CDialog::OnCtlColor(pDC, pWnd, nCtlColor);// 因为我们知道 对于对话框 最后是调: _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); DefWindowProc(pThreadState->m_lastSentMsg.message,// 0x14=WM_ERASEBKGND pThreadState->m_lastSentMsg.wParam,// hDC pThreadState->m_lastSentMsg.lParam);// 0 // 这里的 m_lastSentMsg.message=0x14=WM_ERASEBKGND, 就是OnEraseBkgnd时留下的lastSentMsg (上次送出的消息) 总之在OnCtlColor中 绘制不是一个好办法,还是按规矩办 为好。
多谢,很高深, 不知掉这个帖子, 过几年后,能否搞懂 wm-ctlcolordlg执行2次的原因。 发分
schlafenhamster 2013-05-29
  • 打赏
  • 举报
回复
现在我们自己做: // CDialog::OnCtlColor(pDC, pWnd, nCtlColor);// 因为我们知道 对于对话框 最后是调: _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); DefWindowProc(pThreadState->m_lastSentMsg.message,// 0x14=WM_ERASEBKGND pThreadState->m_lastSentMsg.wParam,// hDC pThreadState->m_lastSentMsg.lParam);// 0 // 这里的 m_lastSentMsg.message=0x14=WM_ERASEBKGND, 就是OnEraseBkgnd时留下的lastSentMsg (上次送出的消息) 总之在OnCtlColor中 绘制不是一个好办法,还是按规矩办 为好。
schlafenhamster 2013-05-29
  • 打赏
  • 举报
回复
是DefWindowProc 自己做, 不是响应 OnEraseBkgnd BOOL CCtrlColorDlg::OnEraseBkgnd(CDC* pDC) { afxDump << "OnEraseBkgnd\n"; CCtrlColorDlg::OnCtlColor(pDC, this, CTLCOLOR_DLG); // 其实是因为 这里没做完 ! return TRUE; }
combobox2013 2013-05-29
  • 打赏
  • 举报
回复
引用 21 楼 schlafenhamster 的回复:
跟踪一下 “CDialog::OnCtlColor(pDC, pWnd, nCtlColor);”发现 对于对话框 这个 函数 真正调用的是: DefWindowProc 其 参数 为 : (WM_ERASEBKGND,hDC,0) 就是说 又 做了一次 WM_ERASEBKGND !!
又做了一次wm_erasebkgnd的话, afxdump<<"onerasebkgnd" 岂不是应该出现2次? 而非一次
schlafenhamster 2013-05-29
  • 打赏
  • 举报
回复
跟踪一下 “CDialog::OnCtlColor(pDC, pWnd, nCtlColor);”发现 对于对话框 这个 函数 真正调用的是: DefWindowProc 其 参数 为 : (WM_ERASEBKGND,hDC,0) 就是说 又 做了一次 WM_ERASEBKGND !!
schlafenhamster 2013-05-28
  • 打赏
  • 举报
回复
OnCtlColor( CDC* pDC 这个DC 是不是 本窗口的 DC ?
combobox2013 2013-05-28
  • 打赏
  • 举报
回复
刚一一验证了代码,确实, 有些意料 onctlcolor竟然会调用2次, 一直以为wm_ctlcolordlg是wm_erasegkdn发出的, 所以只要你重写了 函数onerasebkgdn之后,wm_ctlcolordlg的代码是不会执行的。 所以在这种情况下,想调用onctlcolor中的wm_ctlcolordlg的代码,那么只能显示的调用了。 所以只是一次调用而已, 并且最重要的是: 你主要显示的调用onctlcolodlg,那么是不会绘制背景的。 试验现象表明:以上2点都错误了。 看来windows确实诡异无比,难度很大
引用 19 楼 schlafenhamster 的回复:
这样做实验: 建一个对话框工程,删除 ok,cancel 响应: void CCtrlColorDlg::OnPaint() { afxDump << "OnPaint\n"; CPaintDC dc(this); } BOOL CCtrlColorDlg::OnEraseBkgnd(CDC* pDC) { afxDump << "OnEraseBkgnd\n"; CCtrlColorDlg::OnCtlColor(pDC, this, CTLCOLOR_DLG); return TRUE; } HBRUSH CCtrlColorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if(this==pWnd) { afxDump << "OnCtlColor\n"; CPen pen(PS_SOLID, 3,RGB(255,0,0)); pDC->SelectObject(&pen); pDC->MoveTo(0,0); pDC->LineTo(450,280); } return hbr; } // 输出: OnEraseBkgnd OnCtlColor OnCtlColor OnPaint 注意有 2个 OnCtlColor !!!! 然后修改: HBRUSH hbr = 0;//CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 这时就一个 OnCtlColor 了 // 再改改: CDialog::OnCtlColor(pDC, pWnd, nCtlColor); HBRUSH hbr = CreateSolidBrush(RGB(0,255,255)); 注意 背景已经是 RGB(0,255,255) 了 !! 我们没有画背景 !! 2个 OnCtlColor 时 ,可以发现 是第二个 OnCtlColor 画的 结果。 有点 出于 意料, OnCtlColor 会画 背景,而且 CTLCOLOR_DLG 会 有2次。
combobox2013 2013-05-28
  • 打赏
  • 举报
回复
引用 11 楼 combobox2013 的回复:
[quote=引用 10 楼 jerry_dqh 的回复:] wm_ctlcolor---->wm_paint 这两个消息之间还有擦除背影的消息等,或者其他的消息。
wm_erasebkgnd--->wm_ctlcolor-->wm_paint 试验可以测试 不管如何,谢谢大家的热心顶贴,希望有大神解答 [/quote] 12楼啊
schlafenhamster 2013-05-28
  • 打赏
  • 举报
回复
这样做实验: 建一个对话框工程,删除 ok,cancel 响应: void CCtrlColorDlg::OnPaint() { afxDump << "OnPaint\n"; CPaintDC dc(this); } BOOL CCtrlColorDlg::OnEraseBkgnd(CDC* pDC) { afxDump << "OnEraseBkgnd\n"; CCtrlColorDlg::OnCtlColor(pDC, this, CTLCOLOR_DLG); return TRUE; } HBRUSH CCtrlColorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if(this==pWnd) { afxDump << "OnCtlColor\n"; CPen pen(PS_SOLID, 3,RGB(255,0,0)); pDC->SelectObject(&pen); pDC->MoveTo(0,0); pDC->LineTo(450,280); } return hbr; } // 输出: OnEraseBkgnd OnCtlColor OnCtlColor OnPaint 注意有 2个 OnCtlColor !!!! 然后修改: HBRUSH hbr = 0;//CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 这时就一个 OnCtlColor 了 // 再改改: CDialog::OnCtlColor(pDC, pWnd, nCtlColor); HBRUSH hbr = CreateSolidBrush(RGB(0,255,255)); 注意 背景已经是 RGB(0,255,255) 了 !! 我们没有画背景 !! 2个 OnCtlColor 时 ,可以发现 是第二个 OnCtlColor 画的 结果。 有点 出于 意料, OnCtlColor 会画 背景,而且 CTLCOLOR_DLG 会 有2次。
combobox2013 2013-05-28
  • 打赏
  • 举报
回复
引用 16 楼 schlafenhamster 的回复:
过程: wm_erasebkgnd--->wm_ctlcolor问题在这里-->wm_paint wm_erasebkgnd 调用 wm_ctlcolor 是为了得到一个画刷,得到画刷后 它还有工作要做 (就是用这个画刷刷 背景),一旦 让这个函数再接着工作下去, 你画的东西就没有了(覆盖了)。 为此 必须 在 wm_erasebkgnd 自己调 wm_ctlcolor (即你画的东西),然后就退出。 代码: BOOL CaaaDlg::OnEraseBkgnd(CDC* pDC) { CaaaDlg::OnCtlColor(pDC, this, WM_CTRLCLOR_DLG); return TRUE; }
深深的震撼了。 windows 的wm_erasebkgnd还有在背后做工作, 这一点确实没有想到。 可能是系统拿到刷子做的吧。 所以,不能发出wm_ctlcolordlg这个消息来解决问题。 题外话: 与刷子相关的问题------------在onctlcolor中贴图, 刷子不会去覆盖掉你贴的图, 但是绘制的曲线却被覆盖了。 呵呵
xfxTianyi 2013-05-28
  • 打赏
  • 举报
回复
画图的效果是不停调用画图语句,比如lineto(),放在Onpaint中的目的就是能够保证不停的调用,当窗口被覆盖需要更新时。所有要保证画图语句,当窗口需要更新时,能够被调用。
schlafenhamster 2013-05-28
  • 打赏
  • 举报
回复
过程: wm_erasebkgnd--->wm_ctlcolor问题在这里-->wm_paint wm_erasebkgnd 调用 wm_ctlcolor 是为了得到一个画刷,得到画刷后 它还有工作要做 (就是用这个画刷刷 背景),一旦 让这个函数再接着工作下去, 你画的东西就没有了(覆盖了)。 为此 必须 在 wm_erasebkgnd 自己调 wm_ctlcolor (即你画的东西),然后就退出。 代码: BOOL CaaaDlg::OnEraseBkgnd(CDC* pDC) { CaaaDlg::OnCtlColor(pDC, this, WM_CTRLCLOR_DLG); return TRUE; }
combobox2013 2013-05-28
  • 打赏
  • 举报
回复
引用 13 楼 schlafenhamster 的回复:
OnCtlColor( CDC* pDC 这个DC 是不是 本窗口的 DC ?


void CaaaDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		//CDialog::OnPaint();

		CPaintDC dc(this) ;
	/*	CPen  pen(PS_SOLID, 3,RGB(255,0,0));
		dc.SelectObject(&pen);
		dc.MoveTo(0,0);
		dc.LineTo(100,29);*/
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CaaaDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


HBRUSH CaaaDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何属性

	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	if(this==pWnd)
	{
		CPen pen(PS_SOLID, 3,RGB(255,0,0));
		pDC->SelectObject(&pen);
		pDC->MoveTo(0,0);
		pDC->LineTo(100,29);
	}
	return hbr;
}

qiminixi 2013-05-28
  • 打赏
  • 举报
回复
OnCtlColor是用来设置的,比如设置文字颜色,文本背景色,背景色等等;OnEraBgColor使用OnCtlColor的刷子绘制控件的背景,然后调用OnPaint绘制控件的内容。所以要在控件内绘图的话,重控件派生一个类,重载OnPain,在OnPaint里绘图。
叶恭介叶恭介 2013-05-27
  • 打赏
  • 举报
回复
干嘛在OnCtrlcolor.应该在OnPaint()里绘制
combobox2013 2013-05-27
  • 打赏
  • 举报
回复
引用 10 楼 jerry_dqh 的回复:
wm_ctlcolor---->wm_paint 这两个消息之间还有擦除背影的消息等,或者其他的消息。
wm_erasebkgnd--->wm_ctlcolor-->wm_paint 试验可以测试 不管如何,谢谢大家的热心顶贴,希望有大神解答
碼上道 2013-05-27
  • 打赏
  • 举报
回复
wm_ctlcolor---->wm_paint 这两个消息之间还有擦除背影的消息等,或者其他的消息。
xzp279671691 2013-05-27
  • 打赏
  • 举报
回复
OnCtrlcolor是在窗口显现之前响应的,当窗口正式显现时要进行重绘,你在OnCtrlcolor函数里画的线肯定被抹去了
combobox2013 2013-05-27
  • 打赏
  • 举报
回复
引用 7 楼 liuli7786 的回复:
	HPEN hPen;
	HPEN hPenOld;
	hPen = CreatePen(PS_SOLID,3,RGB(255,0,0));
	hPenOld = (HPEN)SelectObject(pDC->m_hDC,hPen);
	pDC->MoveTo(20,10);
	pDC->LineTo(200,100);
	SelectObject(pDC->m_hDC,hPenOld);
	DeleteObject(hPen);
代码最好放到OnDraw函数或者OnPaint函数中
都说了, onpaint里什么都没有做,仅仅是无效区域变为有效,并且把 wm_paint从消息队列中移除掉。 消息顺序为: wm_ctlcolor---->wm_paint 所以按照这个道理,规律,那么我的的法子是可行的, 结果却什么看不到, 怎么回事?
liuli7786 2013-05-27
  • 打赏
  • 举报
回复
	HPEN hPen;
	HPEN hPenOld;
	hPen = CreatePen(PS_SOLID,3,RGB(255,0,0));
	hPenOld = (HPEN)SelectObject(pDC->m_hDC,hPen);
	pDC->MoveTo(20,10);
	pDC->LineTo(200,100);
	SelectObject(pDC->m_hDC,hPenOld);
	DeleteObject(hPen);
代码最好放到OnDraw函数或者OnPaint函数中
加载更多回复(5)

16,473

社区成员

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

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

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