Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Detecting which button was clicked 1

Status
Not open for further replies.

katenka5

ISP
Nov 30, 2001
15
US
I have a number of buttons which are stored in a two dimensional array. How do I make the program to know what button I clicked on? Something like mouseClicked event in Java.
 

If you've created the button in the resources, it will have an ID (something like IDC_BUTTON1). This should then be added to a message map which will call a function when the parent class (e.g. your dialog) gets the BN_CLICKED message. This can be done in class wizard - Ctrl+W, Message Maps, highlight the object ID, find the BN_CLICKED message and "Add Function". This should add a function (for each button) to the dialog called something like OnButton() which will be called when BN_CLICKED is recieved for the buttons resource ID - i.e. the user clicks the button.

If all your buttons point to one resource object, you can add the message map in the normal way and to differentiate between buttons, you can create a class that inherits from CButton (Ctrl+W, Add Class, New, enter a class name and select CButton as the base class) and add an ID member variable which you can assign when you create the button object. When your OnButton() function is called, you can check the buttons ID to find out which one has been clicked.

Hope this helps

CMR
 

Ok, when I came to do this, it was a bit more tricky than I'd anticipated. This solution isn't exactly as I said before, and it's a little messy but it does work (which is the main thing!).

anyway, here goes:

first, you create your CMyButton class and inherit from CButton. Your class declaration should look someting like this:

class CMyButton : public CButton
{
// Construction
public:
CMyButton();

// Attributes
public:
int m_nButtonID;
bool m_bIsClicked;

// Operations
public:
bool IsClicked()
{
bool bClicked = m_bIsClicked;
m_bIsClicked = false;
return bClicked;
}

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyButton)
protected:
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CMyButton();

// Generated message map functions
protected:
//{{AFX_MSG(CMyButton)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

You'll notice that I've overridden OnLButtonDown(), which should look like this:

void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bIsClicked = true;
CButton::OnLButtonDown(nFlags, point);
}

Now, in my dialog class, I've declared an array of CMyButtons:
CMyButton buttons[1][2];

And I initialise the buttons in my dialogs OnInitDialog() function:

CRect rect;
rect.SetRect(10, 10, 50, 50);
buttons[0][0].Create("button1", BS_PUSHBUTTON,rect, this, IDC_BUTTON1);
buttons[0][0].m_nButtonID = 1;

rect.SetRect(50, 50, 100, 100);
buttons[0][1].Create("button2", BS_PUSHBUTTON,rect, this, IDC_BUTTON1);
buttons[0][1].m_nButtonID = 2;

buttons[0][0].ShowWindow(SW_SHOW);
buttons[0][1].ShowWindow(SW_SHOW);

In the Dialog itself, you need to add a button (in resource view) and give it an ID, say, IDC_BUTTTON1. Then add it to the message map and create a funtion (as described in my previous post).
Add the following code to the message map function OnButton1():

void CTestDlg::OnButton1()
{
for(int x = 0; x <= 1; x++)
{
for(int y = 0; y <= 1; y++)
{
if(buttons[x][y].IsClicked())
{
//it's this one [x][y]
int id = buttons[x][y].m_nButtonID;
}
}
}
}


CMyButton::m_bIsClicked is set to true in CMyButton::OnLButtonDown(). When you call CMyButton::IsClicked(), it's set to false again so there should be no confusion about which button is the one you want.

Originally, I thought you'd be able to ascertain which button was being clicked by calling GetDlgItem(IDC_BUTTON1) in the dialogs message map function, but it seems that MFC binds the IDC_BUTTON1 id to a control and it can't be shared, hence the change of plan.

a little convoluted I know, but I hope it helps

CMR
 
Hi

Well, IMHO, there is a much easier way. This is to use the macro ON_COMMAND_RANGE.

Here is how:

* Put your controls in your dialog with successive IDs

* declare the handler OUTSIDE the area reservedf for the wizard in the Message_Map ( here is is the one of a dialog class)

BEGIN_MESSAGE_MAP(CTestinitDlg, CDialog)
//{{AFX_MSG_MAP(CTestinitDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
//}}AFX_MSG_MAP
ON_COMMAND_RANGE( IDC_CMD1, IDC_CMD5, OnCmd)
END_MESSAGE_MAP()

* Add the declaration of the handler OUTSIDE the aread reserved for the wizard ( in the .h file)

// Generated message map functions
//{{AFX_MSG(CTestinitDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
//}}AFX_MSG
afx_msg void OnCmd( UINT nID);
DECLARE_MESSAGE_MAP()

* Add the function in your dialog class as show here:

void CTestinitDlg::OnCmd( UINT nID)
{
CString str;

str.Format( &quot;Id %d &quot;, nID);
AfxMessageBox( str);

}

Here it is, your got your ID, it's passed as the parameter of the handler.

HTH

Thierry

EMail: Thierry.Marneffe@skynet.be
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top