【问题标题】:Disabling dialog OK button MFC禁用对话框确定按钮 MFC
【发布时间】:2013-06-18 11:46:07
【问题描述】:

如何禁用 MFC 对话框的“确定”按钮?
此代码:
CWnd* fieldOK = pDlg->GetDlgItem(IDOK);
fieldOK->EnableWindow(FALSE);

导致异常“访问冲突读取位置...” 在 winnocc.cpp 中的 CWnd::EnableWindow(BOOL bEnable) 函数 ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); 中来自 mfc90d.dll
在此期间,重点是另一个控件。
有什么问题?

感谢您的帮助。

[编辑]

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); 
  } 
}

【问题讨论】:

    标签: c++ mfc dialog


    【解决方案1】:

    试试这个:http://support.microsoft.com/kb/122489

    如何禁用 MFC 对话框的默认按钮处理

    虽然建议支持默认按钮(按钮),但您可以 想要在某些情况下禁用或修改标准实现 情况。您可以按照这些在 MFC 应用程序中执行此操作 步骤:

    将对话框加载到 App Studio 并更改 OK 按钮标识符 从 IDOK 到其他东西,例如 IDC_MYOK。另外,清除支票 来自默认按钮属性。

    使用 ClassWizard 创建消息 此按钮的处理函数名为 OnClickedMyOK。这个功能 将在收到来自此的 BN_CLICKED 消息时执行 按钮。

    在 OnClickedMyOK 的代码中,调用基类版本的 OnOK 功能。这是一个例子:

    void CMyDialog::OnClickedMyOK()
       {
          CDialog::OnOK();
       }
    

    为您的对话框覆盖 OnOK,并且在函数内部不执行任何操作。这是一个例子:

    void CMyDialog::OnOK()
       {
       }
    

    运行程序并弹出对话框。将焦点放在其他控件上 比确定按钮。按返回键。注意 CDialog::OnOK() 永远不会被执行。

    【讨论】:

    • 这会阻止按 OK 时的操作但不会禁用它,这是否正确?
    • 如果你相信文章的标题“如何禁用...”,不;)
    • 但我需要动态禁用/启用 OK 按钮。那是代码: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); } }
    • 在这种情况下,我将删除默认创建的标准 OK 按钮并创建我自己的按钮 (ID_MYBUTTON)。您可以像已经尝试过一样禁用此按钮...
    【解决方案2】:

    我不知道为什么不能这样做。如果我采用常规 CDialog 并执行如下初始化:

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

    它可以很好地禁用按钮。也许还有其他问题?

    【讨论】:

      【解决方案3】:

      我怀疑问题来自pDlg 指针。当你调用pDlg->GetDlgItem(IDOK)时,对话框已经创建了吗?

      在CWnd* fieldOK = pDlg->GetDlgItem(IDOK); 行处下断点并对其进行调试以查看 fieldOK 指针是否为空或有效指针。

      这就是为什么我认为mark's answer is very close. You can disable it onOnInitDialog` 或其他对话类成员出现后。

      【讨论】:

        【解决方案4】:

        您的问题是尚未在界面上创建按钮控件。我们无法全面了解您的问题。

        无论如何,您应该保护您的代码免于崩溃。你的代码最好什么都不做,而不是让应用程序崩溃。像这样重构它可以避免由于 NULL 指针导致的访问冲突问题:

        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); 
             }
        }
        

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 嗨,欢迎来到 SO。这实际上应该是评论,而不是答案。一旦您获得足够的声誉,您就可以发表评论。谢谢。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-06
          • 2011-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多