MFC radio button group message handler - c++

I've got two little questions at Visual Studio MFC-GUI programming technique regarding the handling of a group of radio buttons in VS2015 CE.
I have a little dialog based application. This application draws some lines on my dialog with a specified pen.
Now I made a group of radio buttons to be able do use different colors for the pen. So I created a group box, placed the radio buttons into this group box, enabled the group property of the first radio button and checked the tab sequence so that all of the radio buttons are properly in sequence.
That's ok - testing the GUI I'm able to select just one of the radio button as planned, because I wouldn't be able to draw a line in to different colors at the same time. Now I added an handler for the BN_CLICKED Message of the first radio button object in the ClassWizard to add the selection of different colored pens.
Now comes the interesting part. This handler is executed only when i click the first radio button. The one with group property enabled. I thought it should be executed whenever I click any of the radio buttons in this group. The next thing I tried was to add an BN_CLICKED-Messagehandler to all of those radio buttons, but the ClassWizard does not shows the BN_CLICKED Message for the other radio buttons - only for the one with group proerty enabled.
After googling around I read a post that one would be able to add an BN_CLICKED-Messagehandler for an button by simply double clicking it in the Dialog. So I double clicked all of my radio buttons and added an invocation of the BN_CLICKED-Messagehandler of the first radio button. That's working as a workaround so that now my line is drawn in the different colors whenever I click on any of those radio buttons (black, blue, red , and so on).
I have two questions - is this behaviour intended? I suppose the reason why I'm only able to add a BN_CLICKED-Messagehandler in the ClassWizard for the first radio button is, that it would be invoked by any of the radio buttons in my group, wouldn't it?
Another question is, I would have preferred to write the handler once and be able to tell the class wizard to use this particular handler instead of creating a unique handler for each of the buttons. That's independent of this radio buttons. I tested this with a simple application which consists of an assembly of several buttons - which can have their own BN_CLICKED-Messagehandlers attached by the class wizard. When I didn't accept the automatically generated functionname from the wizard and enter the name of my own handlerfunction it simply states that it wouldn't be able to overwrite it. How can I select an existing handler for an object message in the class wizard or is that not possible and I have to do this manually in code for myself?
Hope there's an VS2015 MFC Guy out there be able to tell me ..

This is indeed by design. You could have wanted different behaviour for each button click - if you don;t simply associate all of the BN_CLICKED to the same message handler and delete the ones that were automatically generated.
You can also use ON_CONTROL_RANGE(BN_CLICKED, id1, id2, memberFxn ) - make sure your buttons are in the same range in your resource.h
Hope that helps!

Related

MFC DDX_Radio causes debug assertion failure when DoDataExchange is called (dlgdata.cpp Line 286)

I have a dialog with radio button with groups of 4 buttons.
DDX_Radio(pDX, D_RADIO_GROUPLEAD, intToStore) in DoDataExchange is there for saving and loading.
It works perfectly fine.
Selection changed, DoDataExchange called, stores and loads data no problem.
Problem occurs when I hide one of the radio button (hide it via ShowWindow(SW_HIDE). Let's just call it 3rd button for reference. And previously, the selection was this 3rd button.
I have logic that will automatically select the default one (one with Group flagged as true in the editor). I call the button's SetCheck(1).
Visually everything seems to be working.
However, when I click on 2nd button, then try to call DoDataExchange (hence DDX_Radio), it will causes debug assertion failure. (dlgdata.cpp Line 286)
AND
the data is not properly populated back in intToStore.
Why could this be and how can I avoid this issue?
Thank you.
The problem is, that the auto radio button stuff in Windows skips buttons that are disabled. In detail. You click on button 2 while button 3 is selected and disabled. Button 2 gets selected but button 3 is not unchecked.
The next problem occurs when DoDataExchange runs. It doesn't check if a button is enabled or disabled. DDX_Radio just loops over all radio buttons, and it find 2 buttons in the group are enabled. This causes the ASSERT. DDX_Radio don't care if a button is enabled or disabled.
My advice: Use a custom OnClick handle by yourself, and disable all other buttons manually.

MFC - Deactivating all buttons except one

I have a legacy C++ MFC application with a complex GUI with Ribbons. I have a use case as follows : User clicks button A on a ribbon panel and does some work. After his work is done, before he can exercise the rest of the GUI controls, he absolutely must click button B on the same ribbon panel, and failing to click button B in this manner results in a crash if the user exercises some other controls.
Hence, in order to deal with this use case, I figured it would solve my problem if I could disable all of program's GUI controls in Button A's event handler except button B. Button B's event handler then enables the rest of the GUI controls. This way, I ensure that button B always gets pressed after button A.
Hence, my question to you is as follows : Is there a way to disable all GUI controls in one fell swoop, and then enable and disable controls individually?
I know how to enable or disable controls individually, but I have not yet come across an API that allows one to disable all controls.
This way, you get all IDs of the ribbon buttons:
CList<UINT, UINT>& lstItems;
CMFCRibbonBar *pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
pRibbon->GetItemIDsList(lstItems);
Put the three lines in your view's OnInitialUpdate() handler.
Then use the list to compare the IDs coming through your OnCmdMsg() handler to disable all the buttons (except button B).

Unable to Create Exit Button

I tried a tutorial about C and ATL about a basic dialog. It has a window, and 2 buttons inside. In the beginning of the tutorial, there are 2 buttons and they all exit the application. But, these 2 buttons are created by default. So, I tried creating another button that can exit the application, and I failed.
My aim is to use radio buttons with this project. I want to create some radio buttons and when I press a button, I want to execute some commands.
Here are the links - In my opinion, the tutorial link is unrelated, but I guess it won't hurt: Tutorial, Working Project, Problematic Project.
Thanks in advance.
You add a button onto dialog resource template
You associate an identifier with the button in properties pane right there in resource editor, e.g. IDC_MYBUTT
You will find #define for the chosen constant IDC_MYBUTT in resource.h file on the project
You add handlers to button events on your dialog class. Those are COMMAND_ID_HANDLER macros on Sample ATL Dialog Window code, which connect the event (underlying WM_COMMAND message sent to the window) with specific method (both IDOK and IDCANCEL buttons execute OnCommand in the sample code).
There on the handler you decide how to handle, and in particular to end the dialog or not.
COMMAND_HANDLER, COMMAND_ID_HANDLER and friends are described on MSDN: Message Map Macros (ATL).

How do I add a Checkbox to a tool bar in MFC with a custom bitmap?

I have a C++ MFC MDI application. I have a tool bar with some buttons on it. I need to add some check boxes to this toolbar and i need them to have custom bitmaps just as my buttons do. Thanks
EDIT:
By bitmpas i refer to the pixel images that can be created using the tool bar editor in visual stuidos 2008. I would like a picture (of my creation) instead of the usual tick box.
You don't use checkboxes on toolbars.
You should rather use regular buttons in Check mode. That means that the button stays pressed when user releases it. Clicking it a second time releases the button. This is the same behaviour as a checkbox.
You can either set a toolbar button as checkable by code:
m_ToolBar.SetButtonStyle(nButtonId, TBBS_CHECKBOX);
Or by enabling the corresponding property in the resource editor.
If you want to modify the image displayed when the button is pressed, in your ON_UPDATE_COMMAND_UI handler, use m_ToolBar.GetButtonInfo() to check if the image matches the state. If not, change it using m_ToolBar.SetButtonInfo() and specify the index of an extra image added to the image list of the toolbar.
The following is a link which might help you
http://www.ucancode.net/Visual_C_Control/Place-Combo-Edit-Box-Progress-Control-On-ToolBar-CToolBar-VC-Example.htm

How do I set focus to CEdit in child dialog that is inside TabCtrl?

I have a dialog box (CDialog) with owner-drawn CTabCtrl in it. Tabs content are child dialogs (one for each tab). There is an CEdit in each tab. When the user clicks a tab, I'm hiding all child dialogs using ShowWindow(SW_HIDE) and showing a selected one.
The problem is that when I have, for example, two tabs, click inside an edit box in the first tab and then switch to second, input focus stays on that (invisible) edit box in the first tab no matter what I do in my code (tried calling all methods that potentially can set focus, nothing changed).
Try this:
GetDlgItem(IDC_YOURCONTROL)->SetFocus();
Or the related variable linked with the control:
m_YOURCONTROLControl.SetFocus();