Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > RadioButton


Автор: serg405 27.5.2009, 15:23
Здраствуйте!

я пишу разшыреный клас от СButton (class CRadioButtonEx: public CButton) для радио баттона... не могу перехватить сообщения изменения состояния (check/uncheck),  в функции DrawItem. Также не знаю как получить сообщения об (check/uncheck) через MESSAGE MAP. SetCheck я сделал через обработку ON_WM_LBUTTONDOWN, проблема в том что когда есть група радиобаттонс то я не могу определить в какой  момент кнопка стала uncheck в следствии установки в check другой кнопки.

Автор: Earnest 27.5.2009, 17:49
Проще всего, мне кажется, перехватить уведомление, посылаемое паренту в момент нажатия на кнопку. Т.е. воспользоваться reflecting. Вкратце: пишешь обработчик команды на кнопке, в карту обработчиков вставляешь ON_CONTROL_REFLECT, а лучше ON_CONTROL_REFLECT_EX с возвратом FALSE, чтобы твоя кнопка таки отсылала уведомление родителю. И работать это будет только в оболочке MFC.
Что касается второй части вопроса, то дело, видимо, в том, что ты делаешь кнопку OWNERDRAW, а этот стиль несовместим с прочими (т.е. OWNERDRAW-кнопка может быть только push-button, но никак не check\radio). Отсюда вывод: необходимую функциональность придется имитировать, т.е. самому следить за кнопками-соседями. 

Автор: SergMilk 11.8.2009, 10:30
Привет!
У кого-нибудь была проблема с ClassWizard в Visual Studio 6 при использовании MFC Radio Button Control ?
У меня такая ерунда, что через ClassWizard именно этому элементу управления я не могу автоматом назначить 
переменные члены  m_RadioValue и m_RadioCtrl
Пробовал добавлять вручную, взяв за аналогию CheckBox, (для которого всё добавляется через ClassWizard),
но методы DDX_Check и DDXRadio отличаются.
Какого типа должна быть переменная m_RadioValue? Пробовал делать ее 
Код
BOOL m_RadioValue; 
CButton m_RadioCtrl;

но тогда: 

Код

void CProgressDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
        DDX_Check(pDX, IDC_RADIO, m_RadioValue);   // этот метод срабатывает

        DDX_Radio(pDX, IDC_RADIO, m_RadioValue);    // а здесь появляется "Debug Assertion Failed!"
}


Кто пользовался RadioButton, подскажите, пожалуйста smile.


P.S.
Привожу реализацию DDX_Check и DDX_Radio


Код



/////////////////////////////////////////////////////////////////////////////
// Data exchange for special control

void AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value)
{
    HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
    if (pDX->m_bSaveAndValidate)
    {
        value = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L);
        ASSERT(value >= 0 && value <= 2);
    }
    else
    {
        if (value < 0 || value > 2)
        {
            TRACE1("Warning: dialog data checkbox value (%d) out of range.\n",
                 value);
            value = 0;  // default to off
        }
        ::SendMessage(hWndCtrl, BM_SETCHECK, (WPARAM)value, 0L);
    }
}

void AFXAPI DDX_Radio(CDataExchange* pDX, int nIDC, int& value)
    // must be first in a group of auto radio buttons
{
    HWND hWndCtrl = pDX->PrepareCtrl(nIDC);

    ASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
    ASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON);

    if (pDX->m_bSaveAndValidate)
        value = -1;     // value if none found

    // walk all children in group
    int iButton = 0;
    do
    {
        if (::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
        {
            // control in group is a radio button
            if (pDX->m_bSaveAndValidate)
            {
                if (::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0)
                {
                    ASSERT(value == -1);    // only set once
                    value = iButton;
                }
            }
            else
            {
                // select button
                ::SendMessage(hWndCtrl, BM_SETCHECK, (iButton == value), 0L);
            }
            iButton++;
        }
        else
        {
            TRACE0("Warning: skipping non-radio button in group.\n");
        }
        hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT);

    } while (hWndCtrl != NULL &&
        !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
}

///////////////////////////////////////////////////////////////////////////// 


Автор: Albor 11.8.2009, 12:28
SergMilk, начнём с того что радиокнопка не используется в одиночку. Поставь групповой стиль для первой кнопки в группе и переходи в визард. Теперь можно добавить переменную либо int, либо CButton

Автор: Earnest 11.8.2009, 15:07
Кроме того, на группу радиоконопок заводится ровно одна переменная, типа int. Она равно номеру выбранной в группе опции. Соответственно, DDX_Radio ровно это и делаеn: присваивает\ устанавливает переменную в зависимости от выбранной в группе опции. В диалоге все кнопки группы должны идти по-порядку (z-order); первая должна иметь стиль WS_GROUP, остальные - не иметь его; первый контрол за последней кнопкой - опять иметь - как бы замыкаем группу. На самом деле между радио-кнопками можно вставлять всякие зависимые поля, но тогда тоже без стиля WS_GROUP.
Если опций 2 и они имеют семантику "делать \ не делать", то можно использовать переменную BOOL.

Автор: SergMilk 11.8.2009, 18:55
Ооооо, круть! Спасибо!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)