C++ MFC

Moderators: Lundin
Number of threads: 3354
Number of posts: 9032

This Forum Only
Post New Thread
Single Post View       Linear View       Threaded View      f

Report
Dynamic Button Creation Posted by cherrym on 13 Jan 2004 at 2:34 PM
I have a dialog box which I would like to create a variable number of buttons at run time. I use the CButton class, and the Create method in it, and it returns a True (for success), but I don't see the button within the dialog box. Also, any ideas how I would handle the message map event lines, since I don't know what buttons will be on the screen until run time? Thanks...

Report
Re: Dynamic Button Creation Posted by DB1 on 13 Jan 2004 at 6:11 PM
: I have a dialog box which I would like to create a variable number of buttons at run time. I use the CButton class, and the Create method in it, and it returns a True (for success), but I don't see the button within the dialog box. Also, any ideas how I would handle the message map event lines, since I don't know what buttons will be on the screen until run time? Thanks...
:
:

After you create the button you have to make it visible cButton->ShowWindow(true); The question about the message mapping I would like answered also.


To understand recursive, first you need to understand recursive

Report
Re: Dynamic Button Creation Posted by stober on 13 Jan 2004 at 7:21 PM
You have to manually set up the message map for these OnButtonClick events. The following code allocates 10 buttons and uses the same event handler for each (see RED below

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
	//{{AFX_MSG_MAP(CTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_CONTROL_RANGE(BN_CLICKED,100,110,OnButton1)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	CString str;
	int top = 10;
	int bottom = 30;
	for(int i = 0; i < 10; i++)
	{
		m_ButtonArray[i] = new CButton;
		str.Format("Button%d",i+1);
		DWORD dwStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
		m_ButtonArray[i]->Create(str, dwStyle, CRect(10,top,100,bottom), this,100+i);
		m_ButtonArray[i]->ShowWindow(TRUE);
		top += 30;
		bottom += 30;
	}

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// event handle for the buttons
void CTestDlg::OnButton1() 
{
	AfxMessageBox("OnButton1 Hit");	
}


class CTestDlg : public CDialog
{
// Construction
public:
	CTestDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	//{{AFX_DATA(CTestDlg)
	enum { IDD = IDD_TEST_DIALOG };
	CButton	m_Button1;
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CTestDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	HICON m_hIcon;
	CButton* m_ButtonArray[10];

	// Generated message map functions
	//{{AFX_MSG(CTestDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	virtual void OnOK();
	afx_msg void OnButton1();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};





Report
Re: Dynamic Button Creation Posted by DB1 on 14 Jan 2004 at 6:26 AM
: You have to manually set up the message map for these OnButtonClick events. The following code allocates 10 buttons and uses the same event handler for each (see RED below

Thats neat using the "ON_CONTROL_RANGE" message map Stober. How do you tell which button was clicked in the OnButton1() function?



To understand recursive, first you need to understand recursive

Report
Re: Dynamic Button Creation Posted by stober on 14 Jan 2004 at 6:54 AM
This message was edited by stober at 2004-1-14 6:54:50

: : You have to manually set up the message map for these OnButtonClick events. The following code allocates 10 buttons and uses the same event handler for each (see RED below
:
: Thats neat using the "ON_CONTROL_RANGE" message map Stober. How do you tell which button was clicked in the OnButton1() function?
:

call GetFocus() to get HWND, then GetDlgCtrlID() to get the ID.


Report
Re: Dynamic Button Creation Posted by cherrym on 14 Jan 2004 at 7:24 AM
: This message was edited by stober at 2004-1-14 6:54:50

: : : You have to manually set up the message map for these OnButtonClick events. The following code allocates 10 buttons and uses the same event handler for each (see RED below
: :
: : Thats neat using the "ON_CONTROL_RANGE" message map Stober. How do you tell which button was clicked in the OnButton1() function?
: :
:
: call GetFocus() to get HWND, then GetDlgCtrlID() to get the ID.
:
:
: Thanks guys, thats what I needed to know...

Report
Re: Dynamic Button Creation Posted by DB1 on 17 Jan 2004 at 7:38 PM
: This message was edited by stober at 2004-1-14 6:54:50

: : : You have to manually set up the message map for these OnButtonClick events. The following code allocates 10 buttons and uses the same event handler for each (see RED below
: :
: : Thats neat using the "ON_CONTROL_RANGE" message map Stober. How do you tell which button was clicked in the OnButton1() function?
: :
:
: call GetFocus() to get HWND, then GetDlgCtrlID() to get the ID.
:
:
:

Digging through MS docs, I found an easier way...
declare the handler like this: afx_msg void OnDoSomething( UINT nID ); then you have the ID already in the handler :)



To understand recursive, first you need to understand recursive

Report
Re: Dynamic Button Creation Posted by stober on 17 Jan 2004 at 8:52 PM
:
: Digging through MS docs, I found an easier way...
: declare the handler like this: afx_msg void OnDoSomething( UINT nID ); then you have the ID already in the handler :)


Well, not really. Two reasons(): (1) The OnButtonEvent() does not have a parameter, and (2) If you don't add that function to the message map it will never get called.

If you have a dialog with two buttons, and use the wizard to create the event handler for each, where each button uses the same event, the results are like below, which in the original posters problem, is not what he wants

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
	//{{AFX_MSG_MAP(CTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnButton1)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// in the .h file
	// Generated message map functions
	//{{AFX_MSG(CTestDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	virtual void OnOK();
	afx_msg void OnButton1();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

Report
Re: Dynamic Button Creation Posted by DB1 on 18 Jan 2004 at 6:40 AM
: :
: : Digging through MS docs, I found an easier way...
: : declare the handler like this: afx_msg void OnDoSomething( UINT nID ); then you have the ID already in the handler :)
:
:
: Well, not really. Two reasons(): (1) The OnButtonEvent() does not have a parameter, and (2) If you don't add that function to the message map it will never get called.
:
: If you have a dialog with two buttons, and use the wizard to create the event handler for each, where each button uses the same event, the results are like below, which in the original posters problem, is not what he wants

:
: BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
: 	//{{AFX_MSG_MAP(CTestDlg)
: 	ON_WM_SYSCOMMAND()
: 	ON_WM_PAINT()
: 	ON_WM_QUERYDRAGICON()
: 	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
: 	ON_BN_CLICKED(IDC_BUTTON2, OnButton1)
: 	//}}AFX_MSG_MAP
: END_MESSAGE_MAP()
: 
: 
: // in the .h file
: 	// Generated message map functions
: 	//{{AFX_MSG(CTestDlg)
: 	virtual BOOL OnInitDialog();
: 	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
: 	afx_msg void OnPaint();
: 	afx_msg HCURSOR OnQueryDragIcon();
: 	virtual void OnOK();
: 	afx_msg void OnButton1();
: 	//}}AFX_MSG
: 	DECLARE_MESSAGE_MAP()
: 

:


My reply was in response to getting the ID of the pressed button when you use the ON_CONTROL_RANGE message map.. I've tried it and it works good. Using your previous example:
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
	//{{AFX_MSG_MAP(CTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
         // this has to be outside the wizard created AFX_MSG_MAP (see msdn docs)
        ON_CONTROL_RANGE(BN_CLICKED,100,110,OnAnyButton)
END_MESSAGE_MAP()

BOOL CTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	CString str;
	int top = 10;
	int bottom = 30;
	for(int i = 0; i < 10; i++)
	{
		m_ButtonArray[i] = new CButton;
		str.Format("Button%d",i+1);
		DWORD dwStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
		m_ButtonArray[i]->Create(str, dwStyle, CRect(10,top,100,bottom), this,100+i);
		m_ButtonArray[i]->ShowWindow(TRUE);
		top += 30;
		bottom += 30;
	}

	return TRUE;  // return TRUE  unless you set the focus to a control
}


// event handle for the buttons
void CTestDlg::OnAnyButton( UINT nID ) 
{
        CString s;
        s.Format("button %d was pressed", nID - 100);
	AfxMessageBox(s);	
}




// in the header file
	// Generated message map functions
	//{{AFX_MSG(CTestDlg)
	afx_msg void OnAnyButton( UINT nID );
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()



To understand recursive, first you need to understand recursive

Report
Re: Dynamic Button Creation Posted by stober on 18 Jan 2004 at 8:22 AM
Oh I see. Yes, I agree that is a better and easier solution.
Report
Re: Dynamic Button Creation Posted by Scott14468 on 28 Jan 2011 at 10:01 AM
Hi all,

Thanks for this post, it has helped bunches.

I have just one more twist to add to the conversation. Suppose instead of creating a dialog on which to display these buttons, one wants to display them on the main form, a CFameWnd. How would this be accomplished. I've tried the outlined steps, and it works great for a dialog, but not for a main window.

Thanks,
Scott

Report
Re: Dynamic Button Creation Posted by heroestr on 31 Oct 2011 at 7:04 AM
That's really a good try. kapıda ödemeli alışveriş
Report
Re: Dynamic Button Creation Posted by heroestr on 31 Oct 2011 at 7:13 AM
That's really a good try.



 

Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.