9
votes

I have an MFC dialog in which there are two radio buttons. I have put them in a nice group, their IDCs are one after each other (RB_LEFT, RB_RIGHT).

I want to use DDX_Radio so I can access the buttons using an integer value so in the function DoDataExchange I call :

DDX_Radio(pDX, RB_LEFT, mRBLeftRight);

where mRBLeftRight is a member variable of integer type. I also need to edit the buttons properties so I wanted to use a DDX_Control to map them on member variables mRBLeft and mRBRight (CButton):

DDX_Control(pDX, RB_LEFT, mRBLeft);
DDX_Control(pDX, RB_RIGHT, mRBRight);

Now if I do the call to DDX_Control, whenever DoDataExchange is called, the application crashes because DDX_Control forces RB_LEFT to handle a message that DDX_Radio cannot handle. This part I understand.

I decided to not use DDX_Control (removed the calls in DoDataExchange) and just keep a pointer to my radio buttons (CButton*) in my classes. So in my OnInitDialog function, I do the following calls :

mRBLeft= ((CButton*)GetDlgItem(RB_LEFT));
mRBRight = ((CButton*)GetDlgItem(RB_RIGHT));

Now as long as I don't use mRBLeft it's going to be fine, but if I do, bam, crash on DoDataExchange. The thing that really puzzles me is if I change my left radio button using ((CButton*)GetDlgItem(RB_LEFT)->SetCheck(true) it's going to work. Sooo what's the difference ?

(I know it's a lot of hassle for little, but I just wanna understand the mechanics)

2
I read somewhere that I shouldn't store a pointer returned from GetDlgItem, which is probably right, perhaps this is the cause of my problem?levesque

2 Answers

9
votes

TBH Its even easier than JC's post leads you to believe.

DDX_Control( pDX, IDC_RADIO3, m_r3 );
DDX_Control( pDX, IDC_RADIO4, m_r4 );

m_Val   = 0;
DDX_Radio( pDX, IDC_RADIO3, m_Val );

You need to mark the FIRST radio button in the group with WS_GROUP (In this case IDC_RADIO3). You are now good to go and it will automatically select IDC_RADIO3).

Now to keep m_Val up to date it is probably worth putting a click handler on all the radio buttons in the group. Inside that function, simply, call UpdateData( TRUE ); m_Val will now point to the index of the radio button in the group.

3
votes

I found the answer here : http://www.flounder.com/getdlgitem.htm

There IS a problem with using DDX_Control and DDX_Radio at the same time :) This is a small hack to get around the problem.

Radio button variables

Another intrinsic problem, which represents some sort of strange philosophical viewpoint of Microsoft, is that you must not be allowed to create control variables for radio buttons. This makes no sense. They have some weird idea that the only way you will ever manipulate radio buttons is via an index. This is hopelessly inadequate. Therefore, you have to go through some serious contortions to get control variables for your radio buttons.

The first thing you have to do is go back and mark all radio buttons as having the WS_GROUP style. Only radio buttons with a WS_GROUP style can have a control variable. However, if you mark all of them with WS_GROUP, create the control variables, and then remove the WS_GROUP attribute, everything works just fine, thank you. Why we have to go through these extra steps makes no sense whatsoever, but like the derived classes problem, I've been complaining about this for years with no effect. My problem is that I keep forgetting to go back and undo all the WS_GROUP attributes, so the first time I run the program after this I find that all my radio buttons are one-button groups. Whoops. $#%! Fix, and recompile/relink.