对话框的OnCtrlcolor里if(this==pWnd)
{
CPen pen(PS_SOLID, 3,RGB(255,0,0));
pDC->SelectObject(&pen);
pDC->MoveTo(0,0);
pDC->LineTo(100,29);
}结果绘制曲线失败, 什么原因?
求破

解决方案 »

  1.   

    干嘛在OnCtrlcolor.应该在OnPaint()里绘制
      

  2.   

    要先定义一个DC 例如CClientDC 才能操作pen的。
      

  3.   


    onctlcolor已经有pdc这个参数了,我干嘛要重新定义呢?
      

  4.   

    afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );
    是这个吗?
    如果是 这个里面的pdc是需要和当前的DC相关联才可以,调用GetDC().
      

  5.   


    应说了,不需要直接用pdc
      

  6.   

    在OnPaint 中绘制。。onctlcolor中只是设置,字体,画刷等颜色
      

  7.   

    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函数中
      

  8.   

     都说了,  onpaint里什么都没有做,仅仅是无效区域变为有效,并且把 wm_paint从消息队列中移除掉。消息顺序为: 
    wm_ctlcolor---->wm_paint所以按照这个道理,规律,那么我的的法子是可行的, 结果却什么看不到,怎么回事?
      

  9.   

    OnCtrlcolor是在窗口显现之前响应的,当窗口正式显现时要进行重绘,你在OnCtrlcolor函数里画的线肯定被抹去了
      

  10.   

    wm_ctlcolor---->wm_paint 这两个消息之间还有擦除背影的消息等,或者其他的消息。
      

  11.   

    wm_erasebkgnd--->wm_ctlcolor-->wm_paint试验可以测试不管如何,谢谢大家的热心顶贴,希望有大神解答
      

  12.   

    wm_erasebkgnd--->wm_ctlcolor-->wm_paint试验可以测试不管如何,谢谢大家的热心顶贴,希望有大神解答

    12楼啊
      

  13.   

    OnCtlColor( CDC* pDC
    这个DC 是不是 本窗口的 DC ?
      

  14.   

    OnCtlColor是用来设置的,比如设置文字颜色,文本背景色,背景色等等;OnEraBgColor使用OnCtlColor的刷子绘制控件的背景,然后调用OnPaint绘制控件的内容。所以要在控件内绘图的话,重控件派生一个类,重载OnPain,在OnPaint里绘图。
      

  15.   


    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;
    }
      

  16.   

    过程:
    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; 
      

  17.   

    画图的效果是不停调用画图语句,比如lineto(),放在Onpaint中的目的就是能够保证不停的调用,当窗口被覆盖需要更新时。所有要保证画图语句,当窗口需要更新时,能够被调用。
      

  18.   


    深深的震撼了。windows 的wm_erasebkgnd还有在背后做工作, 这一点确实没有想到。可能是系统拿到刷子做的吧。所以,不能发出wm_ctlcolordlg这个消息来解决问题。题外话:与刷子相关的问题------------在onctlcolor中贴图, 刷子不会去覆盖掉你贴的图, 但是绘制的曲线却被覆盖了。呵呵
      

  19.   

    这样做实验:
    建一个对话框工程,删除 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次。
      

  20.   

    刚一一验证了代码,确实,有些意料onctlcolor竟然会调用2次,一直以为wm_ctlcolordlg是wm_erasegkdn发出的, 所以只要你重写了
    函数onerasebkgdn之后,wm_ctlcolordlg的代码是不会执行的。所以在这种情况下,想调用onctlcolor中的wm_ctlcolordlg的代码,那么只能显示的调用了。所以只是一次调用而已, 并且最重要的是: 你主要显示的调用onctlcolodlg,那么是不会绘制背景的。试验现象表明:以上2点都错误了。看来windows确实诡异无比,难度很大
      

  21.   

    跟踪一下 “CDialog::OnCtlColor(pDC, pWnd, nCtlColor);”发现 对于对话框 这个 函数 真正调用的是:
    DefWindowProc
    其 参数 为 :
    (WM_ERASEBKGND,hDC,0)
    就是说 又 做了一次 WM_ERASEBKGND !!
      

  22.   


    又做了一次wm_erasebkgnd的话,   afxdump<<"onerasebkgnd" 岂不是应该出现2次?
    而非一次
      

  23.   

    是DefWindowProc 自己做, 不是响应 OnEraseBkgnd BOOL CCtrlColorDlg::OnEraseBkgnd(CDC* pDC) 
    {
    afxDump << "OnEraseBkgnd\n";
    CCtrlColorDlg::OnCtlColor(pDC, this, CTLCOLOR_DLG);
    // 其实是因为 这里没做完 !
    return TRUE;
    }
      

  24.   

    现在我们自己做:
    // 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中 绘制不是一个好办法,还是按规矩办 为好。 
      

  25.   


    多谢,很高深, 不知掉这个帖子,  过几年后,能否搞懂 wm-ctlcolordlg执行2次的原因。发分