0

使用 C++/MFC 和 GDI(不是 GDI+),总体目标是创建一个有图案HBRUSH的 ,它将用于OnCtlColor以红色勾勒一个编辑控件,并能够打开和关闭轮廓。为此,您将位图附加到HBRUSHusing CreatePatternBrush。这是使用存储的位图资源执行此操作的代码:

CDialog::OnInitDialog();
BOOL ok = redBoxBitmap.LoadBitmap(MAKEINTRESOURCE(IDB_mespe_EditBox_Red));
ok = redBoxBrush.CreatePatternBrush(&redBoxBitmap);

并且在OnCtlColor

HBRUSH CModelEditorSpecies::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr;
    int ctrlID=pWnd->GetDlgCtrlID();
    if(ctrlID==IDC_MyEditControl)
        hbr=(HBRUSH) redBoxBrush;
    else
        hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

    return hbr;
}

上面的代码都可以按需要工作。但是,这取决于位图的大小调整到编辑控件。我现在需要的是能够在 C++ 程序中创建位图,其大小为控件的客户区,这取决于控件的设计大小(在对话框编辑器中)和用户在Windows 10 设置。

我找不到一种直接的方法来构建位图,或者更好的是,创建一个适当大小的空位图(可以做),将其选择为CDC(可以做),将红色框绘制到其中(可以做),然后从CDC(怎么办?)中提取更新位图。

任何人都可以建议如何以编程方式创建位图,或者建议一种更好的方法,在程序需要时将编辑控件以红色框起来?

为响应@Constantine Georgiou 3/9 的回答而添加:

新代码:

CBitmap redBoxBitmap; // member variables of class CModelEditorSpecies
CBrush redBoxBrush;

BOOL CModelEditorSpecies::OnInitDialog()
{
    CDialog::OnInitDialog();
    BOOL ok;
    CRect r; defaultSpecies1Ctrl.GetClientRect(&r);
    xx(r.Width(), r.Height()/*, redBoxBrush*/);
    ok = redBoxBrush.CreatePatternBrush(&redBoxBitmap);
    //...
}

void CModelEditorSpecies::xx(const int w, const int h)
{
    CDC *pDC=GetDC();
    redBoxBitmap.CreateCompatibleBitmap(pDC, w, h);
    
    // Create a red pen
    CPen redPen;
    redPen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
    
    // Draw the bitmap - red pen & default background brush
    CBitmap *pOldBitmap=pDC->SelectObject(&redBoxBitmap);
    pDC->SelectObject(&redPen);
    CBrush editBoxBrush;
    editBoxBrush.CreateSysColorBrush(COLOR_WINDOW);
    pDC->SelectObject(&editBoxBrush);
    pDC->Rectangle(0, 0, w, h);
        
    pDC->SelectObject(pOldBitmap);
    
    // Create the edit-control custom brush
    redBoxBrush.CreatePatternBrush(&redBoxBitmap);
    return;
}

此代码生成一个全黑的编辑控件,就好像正在使用的位图是单色的。如果在 dc 中绘制不会影响位图,或者如果在 dc 兼容的位图中绘制不使用 and 中的颜色,这是可以预期的redPeneditBoxBrush正如@IInspectable 所建议的那样。

4

1 回答 1

0

以下是创建画笔的方法 - 使用 Win32 函数而不是它们的 MFC 包装器,但您可以弄清楚。

BOOL CModelEditorSpecies::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Get edit-control's size
    RECT rc;
    GetDlgItem(IDC_MyEditControl)->GetClientRect(&rc);

    // Create the bitmap and a memory-DC
    HDC hDC = ::GetDC(HWND_DESKTOP);
    HDC mDC = CreateCompatibleDC(hDC);
    HBITMAP hBmp = CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
    ::ReleaseDC(HWND_DESKTOP, hDC);

    // Create a red pen
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));

    // Draw the bitmap - red pen & default background brush
    HBITMAP hOldBmp = (HBITMAP) SelectObject(mDC, hBmp);
    HPEN hOldPen = (HPEN) SelectObject(mDC, hPen);
    HBRUSH hOldBr = (HBRUSH) SelectObject(mDC, GetSysColorBrush(COLOR_WINDOW));
    Rectangle(mDC, rc.left, rc.top, rc.right, rc.bottom);
    SelectObject(mDC, hOldBr);
    SelectObject(mDC, hOldPen);
    SelectObject(mDC, hOldBmp);

    // Create the edit-control custom brush
    redBoxBrush = CreatePatternBrush(hBmp);

    // Clean-up - the SysColorBrush doesn't need to be deleted
    DeleteObject(hPen);
    DeleteObject(hBmp);
    DeleteDC(mDC);

    return TRUE;
}

HBRUSH CModelEditorSpecies::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    return (nCtlColor == CTLCOLOR_EDIT && pWnd->GetDlgCtrlID() == IDC_MyEditControl) ?
        redBoxBrush : CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
}

还要检查我在评论中建议的替代方案。这个将绘制到编辑控件的客户区。


编辑:

我在上面发布的代码确实有效,在它运行完之后就是HBRUSH句柄(编辑框的模式画笔)。我不明白你为什么坚持使用 MFC 包装器。它们是“更高级别”的瘦包装器,所以......“瘦”实际上,您仍然必须执行几乎完全相同的操作(创建、选择到 DC、执行某些绘图操作、从 DC 中选择) GDI 的。您不需要执行的唯一操作是删除资源(对象的析构函数会调用DeleteObject()您)。

无论如何,如果您更喜欢 MFC 而不是 GDI,让我们看看您的代码有什么问题。它有很多问题:

  • 首先,您需要一个内存 DC来在位图上绘图,通过调用获得的窗口 DCGetDC()在窗口表面上绘制。
  • 调用得到的 DCGetDC()必须返回给系统(ReleaseDC()),因为pDC它只是一个指针,编译器不会调用析构函数。
  • 您选择到 DC 中的对象必须在销毁之前将其选中,否则可能会发生内存泄漏。

所以你的代码应该如下所示进行更改:

void CModelEditorSpecies::xx()
{
    CRect r;
    GetDlgItem(IDC_MyEditControl)->GetClientRect(&r);
    
    // Create the bitmap and a memory-DC
    CBitmap redBoxBitmap;
    CDC mDC, *pDC = GetDC();
    redBoxBitmap.CreateCompatibleBitmap(pDC, r.Width(), r.Height());
    mDC.CreateCompatibleDC(pDC);
    ReleaseDC(pDC);

    // Create a red pen and get the default background brush
    CPen redPen;
    redPen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
    CBrush editBoxBrush;
    editBoxBrush.CreateSysColorBrush(COLOR_WINDOW);

    // Draw the bitmap - red pen & default background brush
    CBitmap *pOldBitmap = mDC.SelectObject(&redBoxBitmap);
    CPen *pOldPen = mDC.SelectObject(&redPen);
    CBrush *pOldBrush =mDC.SelectObject(&editBoxBrush);
    mDC.Rectangle(r);
    mDC.SelectObject(pOldBrush);
    mDC.SelectObject(pOldPen);
    mDC.SelectObject(pOldBitmap);

    // Create the edit-control custom brush
    redBoxBrush.CreatePatternBrush(&redBoxBitmap);
}

它与 GDI 版本基本相同。

于 2021-03-10T00:49:40.207 回答