简体   繁体   中英

Dynamically Created Button Events in MFC Doesn't Fire After Clicking the Button

So i was asked to make a bunch of buttons in MFC to update the app with new functions.

What have i done is

a. Reserving the ID in resource.h

#define IDC_MAINFRM_BTN_1               40501
#define IDC_MAINFRM_BTN_2               40502
#define IDC_MAINFRM_BTN_3               40503
#define IDC_MAINFRM_BTN_4               40504
#define IDC_MAINFRM_BTN_5               40505

I also have made sure that there's no duplicate ID in the resource.h

b.To create the button i have inserted these codes in the CMainFrame::OnCreate() function

//Custom function start
cButtonA = new CButton();
cButtonB = new CButton();
cButtonC = new CButton();
cButtonD = new CButton();
cButtonE = new CButton();
cButtonA->Create(_T("My button 1"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(btnLeft1, btnTop1, btnRight1, btnBottom1), this, IDC_MAINFRM_BTN_1);
cButtonB->Create(_T("My button 2"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(btnLeft1, btnTop2, btnRight1, btnBottom2), this, IDC_MAINFRM_BTN_2);
cButtonC->Create(_T("My button 3"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(btnLeft1, btnTop3, btnRight1, btnBottom3), this, IDC_MAINFRM_BTN_3);
cButtonD->Create(_T("My button 4"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(btnLeft2, btnTop1, btnRight2, btnBottom1), this, IDC_MAINFRM_BTN_4);
cButtonE->Create(_T("My button 5"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(btnLeft2, btnTop2, btnRight2, btnBottom2), this, IDC_MAINFRM_BTN_5);

Header File:

CButton*                cButtonA; //First Button
CButton*                cButtonB; //Second Button
CButton*                cButtonC; //Third Button
CButton*                cButtonD; //Fourth Button
CButton*                cButtonE; //Fifth Button

c. For the message map i have tried both of these and neither of them works or catch the functions as for the ShowTestMessage function it only just contain a placeholder AfxMessageBox code. Tried putting breakpoints on those too and it still doesn't work.

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
//Method 1
ON_COMMAND_RANGE(IDC_MAINFRM_BTN_1, IDC_MAINFRM_BTN_13, &CMainFrame::ShowTestMessage)

//Method 2
ON_BN_CLICKED(IDC_MAINFRM_BTN_1, &CMainFrame::ShowTestMessage)

d. I also have made sure that the functions in MainFrm.h who handle the events has afx_msg prefix.

    protected:
    //{{AFX_MSG(CMainFrame
    afx_msg void ShowTestMessage();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP(

Other things that i have tried intercepting the message by adding some line of codes in PreTranslateMessage

if (pMsg->message == BN_CLICKED){ //This doesn't work
    AfxMessageBox("Ohlala", MB_OK);
}

if (pMsg->message == WM_LBUTTONDOWN){ //This one work
    AfxMessageBox("Ohlala", MB_OK);
}

Then i tried changing the event handle to

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)

Yet this one also doesn't fire (Since the breakpoint isn't triggered)

So did i miss something? I have to admit i'm not really good at MFC. I tried searching for all the probable mistake that i probably made yet i still can't find out why the event doesn't fire. @__@

EDIT1: If it helps i'm developing this in Visual Studio 2013 and this project (maybe) use MDI judging by the class declaration that i found in the header.

class CMainFrame : public CMDIFrameWnd

That's an odd way to place buttons, because the frame usually has children windows (like a child frame and the MDI frames and so on), but here it is, working with a SDI frame (I did not test it for a MDI frame, though):

In CMainFrame :

CButton*                testButton;

afx_msg void ShowTestMessage();

In CMainFrame::OnCreate at the end:

testButton = new CButton();
testButton->Create(_T("My button 1"), 
    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(10, 10, 100, 30), this, ID_TEST_BUTTON);

The 'click' method:

afx_msg void CMainFrame::ShowTestMessage()
{
    AfxMessageBox(L"Bingo!");
}

In message map:

ON_COMMAND(ID_TEST_BUTTON, &CMainFrame::ShowTestMessage)

Later Edit: If you really want the buttons in the client area, then you'll have some work to do. First, derive a 'child frame', something like that:

class CChildFrame : public CMDIChildWndEx

Second, replace the child frame from the document template with yours, something like that:

m_pWhateverDocTemplate = new CMultiDocTemplate( IDR_SOME_ID, RUNTIME_CLASS(CWhateverDoc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CWhateverView)); AddDocTemplate(m_pWhateverDocTemplate);

What's being changed here is the CChildFrame instead of the default CMDIChildWndEx . Now you can create your buttons in the client window. Maybe you can override the OnCreateClient and create them in there. You should be able to handle the buttons clicks in the client class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM