近来在写MFC的应用程序时,使用到RadioButton,发现了一点问题,特写了个演示程序,共享出来,供大家参考。http://download.csdn.net/source/3171605此工程在VS2008环境编译通过,其他环境未测试。从中发现的问题点:
一 在为RadioButton按钮组合追加整型变量时,默认的组中第一个按钮的变量值为0,但MFC为这个变量提供了设置最小值和最大值的功能,(当按钮组合有一定意义时,也许不希望最小值从0开始)但实际操作中发现,最小值,最大值的设置存在缺陷。
1.由于构造函数优先执行,在构造函数中对此变量的初始化还是按0为最小值进行处理,如果手动改为其他值,可能导致默认没有按钮被选中的状态出现。
2.在触发OnOK事件时,总是弹出请输入最小值最大值范围内的数的提示(请参照代码和执行结果)
  默认的OnOK的触发函数中调用了CDialog的OnOK(),每次点OK按钮都会提示
  当我把OnOK()的调用注释掉,换成OnClose(),执行中,没有任何反应;
  当换成EndDialog(0)时,对话框才退出。二 在这里,我有点疑问,那个输入提示是怎么个执行原理,是在哪里调用了什么出现的?MFC为什么要做这个检查,如果使用默认的OnOK(),如何能避免这个问题?

解决方案 »

  1.   

    你Debug下F11进入CDialog::OnOK()中看看,它里面会调用UpdateData();来做校验
    void CDialog::OnOK()
    {
    if (!UpdateData(TRUE))
    {
    TRACE0("UpdateData failed during dialog termination.\n");
    // the UpdateData routine will set focus to correct item
    return;
    }
    EndDialog(IDOK);
    }
      

  2.   


    恩,最终是在DDV_MinMaxInt()这个函数中出的错,value的值并不在我设置的最大值和最小值之间,而是按照默认的以0为最小值处理的,就是说不管怎么设置最大值和最小值,它还是从0开始的
      

  3.   


    看了,里面的value值为1,却和我设置的最大值和最小值(7和5)去验证,导致了验证失败。
    我在单选按钮的单击事件中明明设置了5到7范围的值,不知这个value的1是哪来的
      

  4.   


    我想这就是MFC在处理最小值最大值时的问题了,那个value是通过参数传入的,value对应的就是单选按钮的变量,这说明当我在其单击事件中设置了正确范围的值之后,它又把那个值改变了,这我就不知道它是怎么变的了。
      

  5.   

    现在基本可以确定,MFC中的单选按钮组根本没有做最大值和最小值的处理,只要选中组中第一个按钮,它对应的整型变量值就是0,第二个就对应1,...以此类推...
    如果是这样的话,这应该就是其在实现时考虑不周之处了,最大值和最小值的设置完全没有实现
      

  6.   

    我这里想说的是MFC中单选按钮对应的一个缺陷,而不是说怎么想办法去得到正确的结果(实际上这我已经实现了,但不得不容忍它的缺陷),如果说它不支持对最大最小值的处理,就不该能让我设置最大最小值,实际设置了却没用,就成了鸡肋。也许真像7楼所说有方法可以实现这个最大最小值的功能,但目前还没有找到,我那样处理只是明白它的缺陷的基础上为了得到正确结果的无奈的对应,并不算是MFC本身的对应现在想知道的就是MFC有没有做这个对应希望有高手知道
      

  7.   

    找到症结所在了,问题就在下面这段代码里,而这个函数是在DDV_MinMaxInt()被调用之前执行的,所以无论我设置的按钮变量的值是多少,一执行UpdateData(TRUE),按钮变量的值就变成以0开始计算了。
    这就更能肯定,对这里的处理根本就没考虑最小值可能被设置成其他值的情况。所以可以肯定,单选按钮组是不支持设置最小值的,而对应的变量生成的界面中有最小值的设置框就成了Bug
    void AFXAPI DDX_Radio(CDataExchange* pDX, int nIDC, int& value)
    // must be first in a group of auto radio buttons
    {
    pDX->PrepareCtrl(nIDC);
       HWND hWndCtrl;
       pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl); ASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
    ASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON); if (pDX->m_bSaveAndValidate)   //这里当为TRUE时,value的值被清了
    value = -1;     // value if none found // walk all children in group
    int iButton = 0;   // 这里的初始值时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
    {
    TRACE(traceAppMsg, 0, "Warning: skipping non-radio button in group.\n");
    }
    hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT); } while (hWndCtrl != NULL &&
    !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
    }/////////////////////////////////////////////////////////////////////////////
    // Listboxes, comboboxesvoid AFXAPI DDX_LBString(CDataExchange* pDX, int nIDC, CString& value)
    {
    pDX->PrepareCtrl(nIDC);
       HWND hWndCtrl;
       pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
    if (pDX->m_bSaveAndValidate)
    {
    int nIndex = (int)::SendMessage(hWndCtrl, LB_GETCURSEL, 0, 0L);
    if (nIndex != -1)
    {
    int nLen = (int)::SendMessage(hWndCtrl, LB_GETTEXTLEN, nIndex, 0L);
    ::SendMessage(hWndCtrl, LB_GETTEXT, nIndex,
    (LPARAM)(LPVOID)value.GetBufferSetLength(nLen));
    }
    else
    {
    // no selection
    value.Empty();
    }
    value.ReleaseBuffer();
    }
    else
    {
    // set current selection based on data string
    if (::SendMessage(hWndCtrl, LB_SELECTSTRING, (WPARAM)-1,
      (LPARAM)(LPCTSTR)value) == LB_ERR)
    {
    // no selection match
    TRACE(traceAppMsg, 0, "Warning: no listbox item selected.\n");
    }
    }
    }
      

  8.   

    MFC在VC6之后有更新吗?如果有更新,用新版试试。
      

  9.   

    楼主学得不错啊,可以发现MFC的Bug
      

  10.   

    我在2005上试了
    确实应该是个bug
    不过表现出来的是, 刚点进去添加变量时, 最大最小那些地方都是disabled
    但是如果我选成bool或者别的,再选回来变成int的话, 最大最小就可以设置了
    所以显而易见是一个小bug