禁用MFC对话框的确定按钮

7
我该如何禁用MFC对话框的“确定”按钮?这段代码:
``` CWnd* fieldOK = pDlg->GetDlgItem(IDOK); fieldOK->EnableWindow(FALSE); ```
会导致异常“访问地址出错...”,位于函数`CWnd::EnableWindow(BOOL bEnable)`的文件`winnocc.cpp`中的行`ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL))`。此时焦点在另一个控件上。可能出了什么问题?
感谢您的帮助。
[编辑]
bool CSCalcNormCell::OnSelectionChanged( CWnd* pDlg, int type, int page, UINT ctrl_id ) 
{ 
  DDX_DataBox(pDX.get(), IDC_WORKSHOP_COMBO, ws_code); 
  if (!CInfactoryPriceAdapter::CanEditPricesForWorkshop( ws_code )) 
  { 
    CWnd* fieldOK = pDlg->GetDlgItem(IDOK); 
    fieldOK->EnableWindow(FALSE); 
  } 
  else 
  { 
    CWnd* fieldOK = pDlg->GetDlgItem(IDOK); 
    fieldOK->EnableWindow(TRUE); 
  } 
}
6个回答

6

我不确定为什么你不能这样做。如果我使用普通的CDialog,并像这样进行初始化:

BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    CWnd *okbtn = GetDlgItem( IDOK );
    if ( okbtn ) {
        okbtn->EnableWindow( FALSE );
    }
    return TRUE;
}

它可以很好地禁用按钮。也许其他方面出了问题?

2
尝试这个:http://support.microsoft.com/kb/122489 如何禁用MFC对话框的默认按钮处理
虽然推荐使用默认按钮(pushbutton)支持,但在某些情况下,您可能希望禁用或修改标准实现。您可以通过以下步骤在MFC应用程序中实现此操作:
1.将对话框加载到App Studio中,并将OK按钮标识符从IDOK更改为其他内容,例如IDC_MYOK。同时,清除默认按钮属性中的选中状态。
2.使用ClassWizard为此按钮创建一个名为OnClickedMyOK的消息处理函数。当从该按钮接收到BN_CLICKED消息时,将执行此函数。
3.在OnClickedMyOK的代码中,调用基类版本的OnOK函数。以下是一个示例:
void CMyDialog::OnClickedMyOK()
   {
      CDialog::OnOK();
   }

重写对话框的OnOK函数,并在函数内部不执行任何操作。以下是一个示例:

void CMyDialog::OnOK()
   {
   }

运行程序并打开对话框。将焦点放在除“确定”按钮以外的控件上。按下回车键。注意,CDialog::OnOK() 永远不会被执行。

这是正确的吗?它可以阻止按下“确定”按钮时的操作,但不会禁用它吗? - Pixelchemist
如果您相信文章标题是 "如何禁用...",那么不应该;) - Leo Chapiro
但我需要动态地禁用/启用“确定”按钮。这是代码:bool CSCalcNormCell::OnSelectionChanged(CWnd* pDlg, int type, int page, UINT ctrl_id) { DDX_DataBox(pDX.get(), IDC_WORKSHOP_COMBO, ws_code); if (!CInfactoryPriceAdapter::CanEditPricesForWorkshop(ws_code)) { CWnd* fieldOK = pDlg->GetDlgItem(IDOK); fieldOK->EnableWindow(FALSE); } else { CWnd* fieldOK = pDlg->GetDlgItem(IDOK); fieldOK->EnableWindow(TRUE); } } - GrinderZ
1
在这种情况下,我会删除默认创建的标准“确定”按钮并创建自己的“按钮”(ID_MYBUTTON)。就像您已经尝试过的那样,您可以禁用此按钮。 - Leo Chapiro

1
我怀疑问题来自于`pDlg`指针。当您调用`pDlg->GetDlgItem(IDOK)`时,对话框是否已经创建?请在行`CWnd* fieldOK = pDlg->GetDlgItem(IDOK);`处设置断点并进行调试,以查看`fieldOK`指针是空指针还是有效指针。
这就是为什么我认为`mark的答案非常接近。在`OnInitDialog`或其他对话框类成员显示后,您可以将其禁用。

0

在LoadBitmaps()函数中,您需要加载一个位图来作为OK按钮的禁用模式。


你好,欢迎来到SO。这实际上应该是一条评论,而不是一个答案。当你获得足够的声望时,你可以发表评论。谢谢。 - Cthulhu

0

我不知道是什么原因导致了这个异常,我也遇到了同样的问题,但是我找到了一种使用命令更新处理程序来禁用按钮的替代方法,参考darwen's answer

这对我来说很有效:

afx_msg void OnUpdateButton(CCmdUI *pCmdUI); 
void CYourClass::OnUpdateButton(CCmdUI *pCmdUI) {
    pCmdUI->Enable(enableButton);
}
ON_UPDATE_COMMAND_UI(ID_BUTTON, OnUpdateButton) // On message map

0
你遇到的问题是按钮控件尚未在界面上创建。我们无法完全了解你的问题。
无论如何,你应该保护你的代码免于崩溃。最好让你的代码什么也不做,而不是使应用程序崩溃。像这样重新构造代码可以避免由于空指针引起的访问冲突问题:
bool CSCalcNormCell::OnSelectionChanged( CWnd* pDlg, int type, int page, UINT ctrl_id ) 
{ 
    DDX_DataBox(pDX.get(), IDC_WORKSHOP_COMBO, ws_code);

    CWnd* fieldOK = pDlg->GetDlgItem(IDOK); 
    if (fieldOK)
    {
        if (!CInfactoryPriceAdapter::CanEditPricesForWorkshop( ws_code )) 
            fieldOK->EnableWindow(FALSE); 
        else
            fieldOK->EnableWindow(TRUE); 
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接