Reputation: 121
I have a dialog box with over 500 radio buttons. I want to create a button for users to click to reset all the radio buttons in case he/she made too many mistakes.
I have tried doing them individually.
void DefectConfigurator::OnBnClickedButton2()
{
CButton* pBtn1 = (CButton*) GetDlgItem(IDC_AAAA);
pBtn1->SetCheck(0);
CButton* pBtn2 = (CButton*) GetDlgItem(IDC_BBBB);
pBtn2->SetCheck(0);
CButton* pBtn3 = (CButton*) GetDlgtem(IDC_CCCC);
pBtn3->SetCheck(0);
.
.
.
This way works, but I was wondering if there is a simpler way? Any help would be appreciated. Thank you!
Upvotes: 1
Views: 863
Reputation: 3401
I would rather use the CheckRadioButton()
Win32 function:
CheckRadioButton(m_hWnd, IDC_AAAA, IDC_AAAA + 500 - 1, -1);
Haven't tested it but pls check these two points:
nIDLastButton
argument seem to be inclusive, so I used IDC_AAAA + 500 - 1
.nIDCheckButton
to -1, this should cause no radio button to be checked.You could instead elect to use DDX/DDV, the DDX_Radio()
function does all the work for you (write AND read data). Set the variable to -1 before calling UpdateData(FALSE)
. Remember, this is an index into the radio-group, not a control identifier.
As a sidenote, isn't a UI with 500 radio-buttons really VERY cluttered? Consider using a drop-down list instead. Or you mean check-boxes instead of radio buttons? A "Defect-Configuration" using radio-buttons would allow only one "defect" to be selected.
Upvotes: 0
Reputation: 6103
The recommended way in MFC for exchanging data between the controls and variables is DDX. This uses DoDataExchange
function which is created by MFC Wizard by default (in most cases). The data is exchanged between the UI and the variables both ways by a call to UpdateData function.
The general idea is to have a variable in your dialog class that holds the current state of the radio group (nothing checked or index of the button that is checked). This is done by DDX_Radio function. You have a simple example in this article.
Back to your question:
If you have 500 radio buttons, they are probably splited into different groups. The first radio in the group has WS_GROUP
style and all following radio buttons in the same group must NOT have WS_GROUP
style.
More info about MFC radio button and DDX here.
Implementation:
Declare a CMap in your dialog header that will hold the state of the radio buttons. It maps between the dialog control ID and the state.
CMap <UINT, UINT, int, int> m_Radios;
Here is the DDX function:
void CMFC1Dlg::DDX_CustomRadios(CDataExchange* pDX)
{
// 1. enumerate all radio groups.
// 2. call to a DDX_Radio implementation
CWnd * wnd = pDX->m_pDlgWnd->GetWindow(GW_CHILD);
while (wnd)
{
// verify if this is radio button with WS_GROUP style.
if (wnd->GetStyle() & WS_GROUP &&
wnd->SendMessage(WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
{
#define CLEAR_STATE -1
int radioState = CLEAR_STATE;
int radioId = wnd->GetDlgCtrlID();
if(!pDX->m_bSaveAndValidate)
if (!m_Radios.Lookup(radioId, radioState))
m_Radios[radioId] = radioState;
DDX_Radio(pDX, radioId, radioState);
m_Radios[radioId] = radioState;
}
wnd = wnd->GetNextWindow();
}
Add a call to DoDataExchange:
void CMFC1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_CustomRadios(pDX);
}
Usage:
Clear all radio buttons:
void CMFC1Dlg::OnBnClearAll()
{
m_Radios.RemoveAll();
UpdateData(FALSE); // this updates the ui
}
Save all buttons state from UI to the variables:
void CMFC1Dlg::OnBnSaveAll()
{
UpdateData(TRUE);
POSITION pos = m_Radios.GetStartPosition();
while (pos != NULL)
{
UINT nId = 0;
BOOL state = 0;
m_Radios.GetNextAssoc(pos, nId, state);
TRACE("Control: %d State: %d\r\n", nId, state);
}
}
Upvotes: 0
Reputation: 10756
The IDC_
control id's are just numbers in the resource.h file. So ensure IDC_AAAA
, IDC_BBBB
... IDC_ZZZZ
, etc. are sequential with no interruptions. Then just iterate in a for
loop:
for (UINT nID = IDC_AAAA; nID <= IDC_ZZZZ; ++nID)
{
CButton* pBtn = static_cast<CButton *>(GetDlgItem(nID));
pBtn->SetCheck(BST_UNCHECKED);
}
If you want to be cautious then you could replace static_cast
with dynamic_cast
to have runtime type checking and then check for null pointer.
Upvotes: 1