为啥 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制?

Posted

技术标签:

【中文标题】为啥 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制?【英文标题】:Why CDC::LineTo() doesn't draw in Visual C++ 2015 MFC Dialog?为什么 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制? 【发布时间】:2016-04-08 03:30:05 【问题描述】:

我正在学习 MFC,我正在尝试在基于 MFC 对话框的应用程序主窗口上绘制一些线条,这应该是一项相当简单的任务,但在运行时我看不到对话框上的线条。

下面是我写的方法:

// draw corner of a rectangle on specified device context
void CTestDrawCornerDlg::DrawCorner(
    CDC* pDC,
    const CornerType& type,
    const CPoint& position,
    const unsigned int& size
    )

    CPen pen(PS_SOLID, 5, RGB(0, 0, 0));
    CPen* pOldPen = pDC->SelectObject(&pen);

    CPoint pH, pV;
    // I could make following lines simply with a 2-lines block,
    //  but I'd leave it as it was to make it easier to understand.
    switch (type)
    
    case LEFT_TOP:
        pH.x = position.x + size;
        pH.y = position.y;
        pV.x = position.x;
        pV.y = position.y + size;
        break;
    case LEFT_BOTTOM:
        pH.x = position.x - size;
        pH.y = position.y;
        pV.x = position.x;
        pV.y = position.y + size;
        break;
    case RIGHT_TOP:
        pH.x = position.x + size;
        pH.y = position.y;
        pV.x = position.x;
        pV.y = position.y - size;
        break;
    case RIGHT_BOTTOM:
        pH.x = position.x - size;
        pH.y = position.y;
        pV.x = position.x;
        pV.y = position.y - size;
        break;
    default: break;
    
    pDC->MoveTo(position);
    pDC->LineTo(pH);
    pDC->MoveTo(position);
    pDC->LineTo(pV);

    pDC->SelectObject(pOldPen);

我在Dialog类的OnPaint方法中调用了这个方法:

void CTestDrawCornerDlg::OnPaint()

    if (IsIconic())
    
        CPaintDC dc(this); // device context for painting
        // lines generated automatically when creating
        // MFC project are truncated for brevity
    
    else
    
        CDialogEx::OnPaint();
    

    CPaintDC pDC(this);
    DrawCorner(&pDC, LEFT_TOP, CPoint(50, 50), 50);

我猜这是一个新手错误,但我只是不知道错误是什么。感谢您的帮助!

附:请从以下链接下载 MFC 项目以重新创建此问题: https://www.dropbox.com/s/exeehci9kopvgsn/TestDrawCorner.zip?dl=0

【问题讨论】:

你的代码没问题。也许你没有ON_WM_PAINT ON_WM_PAINT 在创建对话框项目时默认声明。我试图将一个小型演示项目上传到这篇文章。但现在还没有弄清楚如何做到这一点...... 我通过将 DrawCorner 调用移至 OnPaint() 方法的最开始处(即在调用 CDialogEx::OnPaint() 之前)使其工作。然后我可以在对话框中得到预期的线条。仍然开放谁可以回答为什么...... 您的 cmets 与您的问题不符。不要同时使用CDialogEx::OnPaint() + CPaintDC。顺便说一句,避免上传您的项目并添加外部链接。改为显示Minimal, Complete, and Verifiable example。 感谢迈克尔编辑我的帖子以明确问题。嗨 Barmak,我上传的项目实际上是一个最小的项目,它只包含默认生成的 MFC 代码和我在这篇文章中粘贴的代码,可以运行它来验证这个问题。感谢分享链接,很有帮助。 【参考方案1】:

您可以将代码更改为使用CDialogEx::OnPaint() + CClientDC,如下所示:

void CTestDrawCornerDlg::OnPaint()

    CDialogEx::OnPaint();
    CClientDC pDC(this);
    DrawCorner(&pDC, LEFT_TOP, CPoint(50, 50), 50);

或者直接使用CPaintDC:

void CTestDrawCornerDlg::OnPaint()

    CPaintDC pDC(this);
    DrawCorner(&pDC, LEFT_TOP, CPoint(50, 50), 50);

但不要使用OnPaint + CPaintDC

要查看问题,请注意在 MFC 中如何定义 OnPaintCPaintDC

void CDialog::OnPaint()

    CPaintDC dc(this);
    if (PaintWindowlessControls(&dc))
       return;
    Default();


CPaintDC::CPaintDC(CWnd* pWnd)

    if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
        AfxThrowResourceException();

::BeginPaint 是一个核心的 WinAPI 函数。它应该只被调用一次以响应WM_PAINT,并且不能在其他任何地方使用。

另一方面,CClientDC 使用::GetDC,它几乎可以在任何地方使用,只要窗口句柄可用。

【讨论】:

绝妙的答案!我真的不明白为什么我不应该使用 OnPaint + CPaintDC 而这个答案澄清了原因。我尝试了该解决方案,它现在可以工作了。

以上是关于为啥 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制?的主要内容,如果未能解决你的问题,请参考以下文章

使用MFC编制基于对话框的Windows应用程序,实现画图功能

visua studio 自定义路径宏

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥 printf 不在这里打印?

为啥反射不在 Struct 中设置属性?

为啥 + 仅在客户端是 NaN?为啥不在 Node.js 中?