【问题标题】:Create CWnd in library在库中创建 CWnd
【发布时间】:2019-11-02 12:35:08
【问题描述】:

我将以下代码从基于 MFC 对话框的项目移至 MFC 库 dll:

CWnd dummyWnd;
standard = new Gdiplus::Font(dummyWnd.GetDC()->GetSafeHdc(), &logfont); //GetDC() returns null, which did not happen in an MFC dialog-based app

我需要一个临时 DC 来创建 gdiplus 字体、测量字符串和其他实用程序功能。

我的问题:

  • 是否可以像我在基于对话框的应用程序中所做的那样使用 CWnd?
  • 或者我可以通过其他方式简单地为此目的获得 DC 吗?

【问题讨论】:

  • 请仔细检查您的原始代码:CWnd dummyWnd; 创建一个未附加的(无窗口)CWnd 对象;然后dummyWnd.GetDC(); 尝试获取没有附加窗口的客户区设备上下文。这应该失败。请参阅:docs.microsoft.com/en-us/cpp/mfc/reference/…docs.microsoft.com/en-us/cpp/mfc/reference/…
  • 感谢您的回复。我现在想知道为什么代码在基于对话框的项目中确实有效。我也没有在那里创建()它。
  • @RichardCritten 将代码更新为我使用的确切代码。为什么这在基于对话框的 mfc 应用程序中起作用?
  • CDC::GetSafeHdc: 文档中的奇怪评论 "...此成员函数也适用于空指针..." 您对这意味着什么的猜测是和我一样好。来源:docs.microsoft.com/en-us/cpp/mfc/reference/…
  • 使用CClientDC dc(NULL)获取桌面dc,后跟CreateCompatibleDC...见example

标签: c++ mfc


【解决方案1】:

要创建一个临时 dc:

//create memory dc 
CClientDC dc(NULL);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, width, height);
memdc.SelectObject(bitmap);

但在这种情况下,您可能不需要临时 dc。您可以简单地使用桌面直流,只要您不在桌面直流上书写,或者不选择桌面直流中的任何内容。

使用 Windows API 获取桌面 dc:

HDC hdc = ::GetDC(0);
standard = new Gdiplus::Font(hdc, &logfont);
...
ReleaseDC(0, hdc); //cleaup

或者,使用 MFC

CClientDC dc(NULL);
standard = new Gdiplus::Font(dc.GetSafeHdc(), &logfont);

对于临时窗口,dummyWnd.GetDC()->GetSafeHdc() 在调试模式下失败并引发错误,因为 MFC 将检查窗口句柄是否有效。

在发布模式下,它实际上可能会工作,因为它最终会调用有效的::GetDC(NULL)。然而,它将以资源泄漏告终,因为从未调用过 ReleaseDC

【讨论】:

    【解决方案2】:

    由于字体将在特定窗口上绘制,因此正确绘制需要窗口的设备上下文。您将 CWnd* 作为参数发送给您的函数,该函数将由您的动态库导出。

    // MyMfcLibrary.cpp
    void InitializeFont(CWnd* pWnd)
    {
       CClientDC dc(pWnd);
       Gdiplus::Font myfont(dc.GetSafeHdc()->GetSafeHdc(), &logfont);
       /**/
    }
    

    【讨论】:

    • CPaintDC 仅应在覆盖 CWnd::OnPaint 时使用。这里应该是CClientDC
    猜你喜欢
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多