1

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
Ega Rinaldo
  • 99
  • 3
  • 12
  • Do you see the buttons which you created? Explain what settings you used to create the project, for example MDI with Doc/View support + standard or office style... – Barmak Shemirani Oct 03 '16 at 04:56
  • @BarmakShemirani Yes i can see the buttons that i created, i'm not really sure as i am not the one who create the project file but AFAIK this doesn't use Ribbon Style. – Ega Rinaldo Oct 03 '16 at 05:18
  • I don't know what is going on. I think that should work. Maybe you are doing something odd in `PreTranslateMessage` or elsewhere. Or try different values for `IDC_MAINFRM_BTN_1` in case there is collision. – Barmak Shemirani Oct 03 '16 at 07:49
  • @BarmakShemirani btw i've tried looking at it and i think its a MDI since the MainFrm class contains `class CMainFrame : public CMDIFrameWnd` what kind of code that you expect ruining the event handling? Ok, i'll change the IDC_MAINFRM_BTN_1 tomorrow and see if the problem caused by the value collision. Thanks btw – Ega Rinaldo Oct 03 '16 at 08:02

1 Answers1

2

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.

Adrian Roman
  • 534
  • 4
  • 8
  • OP says the buttons are showing, so that shouldn't be an issue. But you are right that it is an odd place for putting buttons. – Barmak Shemirani Oct 03 '16 at 07:56
  • @AdrianRoman Where is the correct place to put the buttons? Btw i just have learned that the project probably has MDI Frame judging by his snippet that i found in the MainFrm header `class CMainFrame : public CMDIFrameWnd`. I just literally learned MFC over the weekends and i'm still confused with it since its really different from developing java program @__@ And oh, it still doesn't work. I tried replacing the message map with the one that you wrote. :/ Maybe there's something messing with the message like @Barmak said :/ – Ega Rinaldo Oct 03 '16 at 08:04
  • 2
    You have replicated the exact code the OP already had. That's not helpful. @EiZenHoweLL: You are trying to learn MFC, C++, and Windows programming all at the same time. Not going to work, ever. [Prerequisites for learning MFC programming](http://stackoverflow.com/q/18165076/1889329) tells you, what's required. If you are impatient, have a look at [TN021: Command and Message Routing](https://msdn.microsoft.com/en-us/library/xt2c310k.aspx). – IInspectable Oct 03 '16 at 08:22
  • 1
    "You have replicated the exact code the OP already had" The difference is that it's actually working. I can see the message box when clicking the button. I don't know if it's 'exact replication' since for example I don't see a `new CButton()` in the OP code. – Adrian Roman Oct 03 '16 at 10:55
  • I don't know what is your purpose of placing the buttons in there, I would probably put them in a toolbar, but you know better what the goals are. If your really want to put them in the client area, well, I'll edit the answer and add a suggestion. You'll have some work to do... – Adrian Roman Oct 03 '16 at 11:02
  • Alright thanks! Your solution is working, i don't know that i have to put them inside another container. I'm assuming the MainFrame itself is already a container. I just have to solve how to call them correctly inside my MainFrame::OnCreate() i still have assertion error that probably caused by my barbaric codes. – Ega Rinaldo Oct 05 '16 at 02:16