MFC Custom Control Not Appearing On Dialog










1















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


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.










share|improve this question


























    1















    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


    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.










    share|improve this question
























      1












      1








      1








      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


      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.










      share|improve this question














      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


      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.







      c++ mfc custom-controls






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 15 '18 at 0:57









      jslmscajslmsca

      5010




      5010






















          1 Answer
          1






          active

          oldest

          votes


















          1














          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.






          share|improve this answer

























          • Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

            – jslmsca
            Nov 15 '18 at 16:57











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310979%2fmfc-custom-control-not-appearing-on-dialog%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          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.






          share|improve this answer

























          • Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

            – jslmsca
            Nov 15 '18 at 16:57
















          1














          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.






          share|improve this answer

























          • Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

            – jslmsca
            Nov 15 '18 at 16:57














          1












          1








          1







          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.






          share|improve this answer















          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 15 '18 at 9:52









          IInspectable

          26.2k54396




          26.2k54396










          answered Nov 15 '18 at 3:05









          Barmak ShemiraniBarmak Shemirani

          21.6k42246




          21.6k42246












          • Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

            – jslmsca
            Nov 15 '18 at 16:57


















          • Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

            – jslmsca
            Nov 15 '18 at 16:57

















          Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

          – jslmsca
          Nov 15 '18 at 16:57






          Thank you. I can get every element to be drawn through the PreSubclassWindow but your last comment "You can also create a child dialog within a main dialog" led me to an easier solution. I don't know why I thought I was limited to one dialog within a dialog but since I'm not, I can just make the Panel a dialog that can be used in various controls so long I create it dynamically in its parent OnInitDialog rather than rely on its parent DDX to instantiate it.

          – jslmsca
          Nov 15 '18 at 16:57




















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53310979%2fmfc-custom-control-not-appearing-on-dialog%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Barbados

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3