Using C++/MFC and GDI (not GDI+), the overall goal is to create an patterned HBRUSH
, which will be used in OnCtlColor
to outline an edit control in red, with the ability to turn the outline on and off. To do this, you attach a bitmap to an HBRUSH
using CreatePatternBrush
. Here is the code for doing that, using a stored bitmap resource:
CDialog::OnInitDialog();
BOOL ok = redBoxBitmap.LoadBitmap(MAKEINTRESOURCE(IDB_mespe_EditBox_Red));
ok = redBoxBrush.CreatePatternBrush(&redBoxBitmap);
and in 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;
}
The above code all works as desired. However, it depends on the bitmap being sized to the edit control. What I need now is the ability to create the bitmap within the C++ program, sized to the client area of the control, which depends on both the design size of the control (in the dialog editor), and the user's setting of text size in Windows 10 settings.
I cannot find a straightforward way of either constructing a bitmap, or, better, creating an empty one of the proper size (can do), selecting it into a CDC
(can do), drawing the red box into it (can do), then extracting the update bitmap from the CDC
(how to do?).
Can anyone suggest either how to create the bitmap programmatically, or suggest a better method of getting an edit control boxed in red when the program calls for that?
Added in response to @Constantine Georgiou's answer of 3/9:
New code:
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;
}
This code produces an all-black edit control, as if the bitmap being used were monochrome. That would be expected if drawing in the dc does not affect the bitmap, or, if drawing in a dc-compatible bitmap does not use the colors in redPen
and editBoxBrush
, as suggested by @IInspectable.
Here's how to create the brush - used the Win32 functions instead of their MFC wrappers, but you can figure it out.
Also check the alternatives I suggested in the comments. This one will be drawing into the edit-control's client area.
EDIT:
The code I posted above does work, and after it runs all left is the
HBRUSH
handle (pattern-brush for your edit box). I can't see why you insist using the MFC wrappers instead. They are "higher-level" thin wrappers, so... "thin" actually, that you still have to perform almost exactly the same operations (create, select into a DC, perfrom some drawing operation, select out of the DC) as the GDI ones. The only operation you don't need to perform is delete the resource (the object's destructor will callDeleteObject()
for you).Anyways, if you prefer MFC over GDI, let's see what's wrong with your code. It has quite a few issues:
GetDC()
draws on a window's surface.GetDC()
must be returned to the system (ReleaseDC()
), becausepDC
is just a pointer, and the compiler won't call the destructor.So your code should be changed as shown below:
It's basically the same as the GDI version.