Locked MFC Controls Disappearing

  • Tuesday, July 31, 2012 3:29 PM
     
     

    EDIT: 

    Mods should look at the last two responses I have made to this thread; that is where they will be informed of my problem. It has to do with how I make my background color. 

    The question is : How do I set a background color for my main window in a way that doesn't color over controls I make? 

    Original Post : 

    I have a problem. If I try to Create a MFC control outside the OnCreate method for my application, all the other controls disappear. Can this be explained? How can I Create a control without all other ones disappearing? 

    The line of code which make all other controls disappear is : 

    m_TriggerType->Create(WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST|WS_VSCROLL, CRect(120, 270, 220, 370), this, IDCB_TRIGGER_TYPE);

    I have noticed that it is specifically the WS_VISIBLE trait that causes all the controls to disappear. (Also, m_TriggerType is of type *CComboBox).


    Ashton Grimball



    • Edited by agrimball Tuesday, July 31, 2012 6:08 PM
    • Edited by agrimball Tuesday, July 31, 2012 6:10 PM to aid understanding my question
    •  

All Replies

  • Tuesday, July 31, 2012 3:52 PM
     
     

    I have a problem. If I try to Create a MFC control outside the OnCreate method for my application, all the other controls disappear. Can this be explained? How can I Create a control without all other ones disappearing? 

    The line of code which make all other controls disappear is : 

    m_TriggerType->Create(WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST|WS_VSCROLL, CRect(120, 270, 220, 370), this, IDCB_TRIGGER_TYPE);

    I have noticed that it is specifically the WS_VISIBLE trait that causes all the controls to disappear. (Also, m_TriggerType is of type *CComboBox).

    Presumably they're being obscured - have you tried using Spy++ to find
    the control windows/positions to clarify what's going on?

    Dave

  • Tuesday, July 31, 2012 3:58 PM
     
     

    Hello Agrimball,

    You could also try to make the window a little smaller.

    Try CRect(120, 270, 220, 50)?


    Cameron Conacher

  • Tuesday, July 31, 2012 4:12 PM
     
     

    I have used Spy++, and I do not know how to interpret the messages. You should also know that once minimized and then re-shown, it looks as it should. 

    What do you mean when you say that they've been obscured? How & why does this occur? 


    Ashton Grimball

  • Tuesday, July 31, 2012 4:14 PM
     
     
    It does not overlap with any other controls. You should also note that this does not only occur for this control. Any time I declare a control and either enforce the WS_VISIBLE or use a ShowWindow command (with any parameter that shows it), all other controls are hidden. Another item of interest is how the controls show again if I minimize and then show the window. 

    Ashton Grimball

  • Tuesday, July 31, 2012 4:21 PM
     
     

    I have used Spy++, and I do not know how to interpret the messages.

    Try again - it pays dividends to be familiar with that tool.

    You should also know that once minimized and then re-shown, it looks as it should. 

    Then something odd is wrong.

    When are you creating the control?

    Does the same code produce the correct expected result when done from
    OnCreate (you seem to imply this in your original post)?

    Dave

  • Tuesday, July 31, 2012 4:42 PM
     
     

    If I create the control in the OnCreate method, it works perfectly. 

    It is being created in another method, using the *exact* same code that works perfectly in the OnCreate method; it does not work. 


    Ashton Grimball

  • Tuesday, July 31, 2012 5:11 PM
     
     
    The "other" method must have the same 'this' pointer and the same this->m_hWnd. If the m_hWnd is not valid or not the same then you can't create a child control of the original window.  For example, you cannot create a child control from the parent's constructor because the parent's m_hWnd has not been created yet at construction time.
  • Tuesday, July 31, 2012 5:15 PM
     
     
    In whichat method are you creating the control?

    Cameron Conacher

  • Tuesday, July 31, 2012 5:36 PM
     
     

    Here's the current program flow: 

    Main window is created. During OnCreate(), it makes some controls. One of these controls is a CComboBox. 

    In the message map for the main window, it calls SomeMethod() whenever the selection changes on the CComboBox. 

    During SomeMethod(), it attempts to create another control (a CButton). After this creation, all other controls disappear. 

    This is my current understanding. 


    Ashton Grimball

  • Tuesday, July 31, 2012 5:40 PM
     
     
    Can you invalidate the window to force repainting?

    Cameron Conacher

  • Tuesday, July 31, 2012 5:42 PM
     
     
    How would I do this? 

    Ashton Grimball

  • Tuesday, July 31, 2012 5:53 PM
     
     
  • Tuesday, July 31, 2012 5:56 PM
     
      Has Code

    I have decided that some code would be helpful. Here it is : 

    It has occurred to me that no painting errors occurred until I modified the OnPaint function. Help me out? 

    #include<afxwin.h>
    
    class CMainWin : public CFrameWnd
    {
    	CButton *b2;
    	CComboBox cb;
    	DECLARE_MESSAGE_MAP()
    
    public:
    	afx_msg void OnPaint(void);
    	afx_msg void OnClose(void);
    	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    
    	CMainWin(void);
    
    	afx_msg void MakeButton(void);
    };
    
    class CApp : public CWinApp
    {
    public:
    	BOOL InitInstance();
    };
    
    BOOL CApp::InitInstance(void)
    {
    	m_pMainWnd = new CMainWin;
    	m_pMainWnd->ShowWindow(m_nCmdShow);
    	m_pMainWnd->UpdateWindow();
    	return TRUE;
    }
    
    CApp app;
    
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd)
    	ON_WM_PAINT()
    	ON_WM_CLOSE()
    	ON_WM_CREATE()
    	ON_CBN_SELCHANGE(101, MakeButton)
    END_MESSAGE_MAP()
    
    CMainWin::CMainWin(void)
    {
    	Create(NULL, "Test1");
    }
    
    void CMainWin::OnPaint(void)
    {
    	CClientDC dc(this);
    	RECT r;
    	GetClientRect(&r);
    
    	CBrush pBr;
    	pBr.CreateSolidBrush(RGB(200,200,200));
    	dc.FillRect(&r, &pBr);
    	pBr.DeleteObject();
    
    	CFrameWnd::OnPaint();
    }
    
    void CMainWin::OnClose(void)
    {
    	if(NULL != b2) delete b2;
    	CFrameWnd::OnClose();
    }
    
    int CMainWin::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	int res = CFrameWnd::OnCreate(lpCreateStruct);
    	cb.Create(WS_VISIBLE|WS_CHILD|WS_VSCROLL|CBS_DROPDOWNLIST, CRect(10, 10, 110, 110), this, 101);
    	cb.AddString("s1");
    	cb.AddString("s2");
    	b2 = NULL;
    	return res;
    }
    
    void CMainWin::MakeButton(void)
    {
    	if(NULL == b2)
    	{
    		b2 = new CButton;
    		b2->Create("Where'd everyone go?", WS_CHILD|WS_VISIBLE|WS_TABSTOP, CRect(10, 50, 110, 80), this, 102);
    	}
    }

    Ashton Grimball

  • Tuesday, July 31, 2012 5:56 PM
     
     
    I have discovered that the problem lies within my OnPaint method. I just want to have a background color. Can you help me out? The code is posted as a reply to the original question. 

    Ashton Grimball

  • Tuesday, July 31, 2012 6:06 PM
     
      Has Code

    I have noticed that if I modify OnPaint to be the following, it works perfectly : 

    void CMainWin::OnPaint(void)
    {
    	CClientDC dc(this);
    	/*RECT r;
    	GetClientRect(&r);
    
    	CBrush pBr;
    	pBr.CreateSolidBrush(RGB(200,200,200));
    	dc.FillRect(&r, &pBr);
    	pBr.DeleteObject();*/
    
    	CFrameWnd::OnPaint();
    }

    How do I set a background without (apparently) coloring over all the controls I make? 


    Ashton Grimball

  • Tuesday, July 31, 2012 6:12 PM
     
     

    Hello Ashton,

    Can you try this?

    void CMainWin::MakeButton(void)
    {
    if(NULL == b2)
    {
    b2
    = new CButton;
    b2
    ->Create("Where'd everyone go?", WS_CHILD|WS_VISIBLE|WS_TABSTOP, CRect(10, 50, 110, 80), this, 102);

    Invalidate();

    }

    Personally, I would be inclined to create the button in the resource editor, and leave it hidden until a ComboBox selection is made.

    Hope this helps.


    Cameron Conacher

  • Tuesday, July 31, 2012 6:36 PM
     
     

    When I do this, all controls are shown again (yes!), but the background color is returned to white. 

    I asked this question so that I could keep my background color as the grey color that I chose. If I use OnPaint() immediately after Invalidate(), it does not help. 

    I believe that the code changes are supposed to be inside my OnPaint() function. 


    Ashton Grimball

  • Tuesday, July 31, 2012 6:40 PM
     
     Answered

    In order to change the background colour, remove the OnPaint handler and define OnEraseBkgnd, i.e. handle the WM_ERASEBKGND message. Use the supplied DC object and return TRUE.

    It is also possible to change the brush which is defined inside the window class (WNDCLASSEX).

    If you still want to draw inside OnPaint, then you should use CPaintDC instead of CClientDC. Also do not call base OnPaint.

    • Marked As Answer by agrimball Tuesday, July 31, 2012 6:47 PM
    •  
  • Tuesday, July 31, 2012 6:46 PM
     
     Answered
    I have figured it out. Instead of using OnPaint to set my background color, I should be modifying it in OnEraseBkgnd(). I have modified my code and it works properly now. Thank you for your help!

    Ashton Grimball

    • Marked As Answer by agrimball Tuesday, July 31, 2012 6:46 PM
    •  
  • Tuesday, July 31, 2012 10:22 PM
     
     

    Hello Ashton,

    Sorry I sent you down the incorrect path earlier.

    Just trying to be helpful.


    Cameron Conacher