Reputation: 334
Using Visual Studio 2013, I created a dialog resource using the resource editor. It is a child control with no border and is just a collection of radio buttons, push buttons, and static text. I want to turn this into a custom control in order to place this in several different locations. Let's call this a "Panel".
I then created a regular dialog and using the Toolbox "Custom Control", defined an area for the Panel. The Panel registers itself and has a valid window handle.
I used the following example: https://www.codeproject.com/Articles/521/Creating-Custom-Controls
The parent's DDX gets hit and the _panel is properly instantiated:
MyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX)
DDX_Control(pDX, IDC_CUSTOM_PANEL, _panel)
}
I read that I need to override the OnPaint() and OnEraseBkgnd(CDC* pDC) methods so the Panel class has these but they are empty. I do not have any custom painting to do as the Panel contains nothing but regular buttons.
What do I have to include in OnPaint()?
I also noticed that none of the member buttons are instantiated in the Panel like would normally happen in a dialog's DoDataExchange method. Instead, I've had to resort to dynamically creating each of the control's inside the Panel's PreSubclassWindow() method:
void MyPanel:PreSubclassWindow()
{
_groupBox.Create(_T("Options"), WS_CHILD|WS_VISIBLE|BS_GROUPBOX, CRect(11, 11, 112, 231), this, IDC_STATIC_GROUPBOX);
//... do this for every dialog element??? seems like overkill...
CWnd::PreSubclassWindow()
}
Why do I need to do this when I've already defined/designed the Panel and each of its controls in the resource editor?
If I do not do this in the PreSubclassWindow method, nothing will appear on the dialog.
Any help is appreciated. Thanks.
Upvotes: 1
Views: 1740
Reputation: 31599
The article says override OnPaint
and OnEraseBkgnd
if you want to change the functionality. It doesn't say you have to override always.
Just remove ON_WM_PAINT
and ON_WM_ERASEBKGND
, remove OnPaint
and OnEraseBkgnd
if you don't need them. Or call the base class implementations if you are not making any changes:
void MyPanel::OnPaint() { CWnd::OnPaint(); }
BOOL MyPanel::OnEraseBkgnd(CDC* pDC) { return CWnd::OnEraseBkgnd(pDC); }
This will show a blank control with nothing in it, unless you add a child window to _panel
as you have done in MyPanel:PreSubclassWindow
You are adding _groupBox
to _panel
. And you are adding _panel
to the MyDialog
.
MyDialog::DoDataExchange(...){DDX_Control(pDX, IDC_CUSTOM_PANEL, _panel)}
is needed to invoke SubclassWindow
for _panel
. That in turn calls _groupBox.Create
.
If MyPanel::OnPaint
and MyPanel::PreSubclassWindow
are not doing anything MyPanel
appears as a blank control.
... do this for every dialog element??? seems like overkill...
You can directly add _groupBox
to the main dialog. But if you want to add specific controls within MyPanel
then you have to do it manually.
You can also create a child dialog within a main dialog. For example that's how a tab control works.
Upvotes: 1