需要一个强大的错误系统来win32 gui应用程序

时间:2013-03-12 11:24:34

标签: c++ windows mfc error-handling

我有一些代码如下:

void MyClass::OnButtonClick()
{
    int retVal = SomeDialog.DoModal();
    if(retVal == MYCLASS_ERROR)
    {
        MessageBox("Error"...blah ...blah);
    }
    else if(retVal == IDOK)   // IDOK is returned on clicking the 'OK' button
    {
        MessageBox("All is well"...blah ...blah);
    }
}
  • SomeDialog只显示进度条。如有任何错误,请致电EndDialog(MYCLASS_ERROR)自动关闭进度条。只有在成功完成后,才允许用户点击“确定”。
  • MYCLASS_ERRORenum中包含各种类型的值 返回类型和状态。

我发现在SomeDialog中单击“确定”后,仍会显示错误消息!我挖了一点,发现MYCLASS_ERROR = IDOK = 1。

所以我的问题是,我应该如何定义所有这些返回状态,以便它不会与任何其他实现的状态发生冲突?意思是,我的函数应返回任何其他函数(或尽可能少的其他函数)不返回的值。

我想到修改我的设计,使所有函数只返回TRUE或FALSE。但是,这在所有情况下都不可行。我也搜索了很多答案,到目前为止还没找到。

感谢您的期待!

3 个答案:

答案 0 :(得分:3)

有办法解决这个问题,但它们有点难看。

最干净的设计通常是避免与标准Win32惯用语冲突的设计,在Win32的世界中,模态对话框返回ID值中的一个,以指示用户在解除它们时单击的按钮(仅喜欢消息框)。严格来说,它是nResult参数传递给用于关闭模态对话框的EndDialog函数。

我建议不要尝试使用其他含义重载此返回值。试图这样做只会让你遇到麻烦(例如,你可能还没有注意到返回值为-1意味着对话框的创建失败了。)


而是在对话框类中定义一个额外的成员变量,并使用它来报告您的其他信息。成功后,您将从对话框中返回IDOK。如果失败(任何类型的失败),请返回IDCANCEL之类的内容。然后,您在OnButtonClick内的代码会检查返回值是IDOK还是IDCANCEL。如果它是IDCANCEL,那么 还需要查询您添加到对话框中的成员变量的值以获取更多信息。

希望这是有道理的。如果没有,也许这个代码示例将(假设m_errStatus是您添加到CDialog的子类中的成员变量):

void MyClass::OnButtonClick()
{
    if (SomeDialog.DoModal() == IDOK)
    {
        // Success!
        // The OK button was clicked, so IDOK was returned.
        MessageBox("All is well"...blah ...blah);
    }
    else
    {
        // Failure!
        // Some error occurred, so IDCANCEL (or any other value) was returned.
        // Determine what to do now, based on additional information that the
        // dialog set upon failure.
        switch (SomeDialog.m_errStatus)
        {
            case MYCLASS_ERROR_1:
                MessageBox("Error 1 occurred.");
                break;
            case MYCLASS_ERROR_2:
                MessageBox("Error 2 occurred.");
                break;
            // etc.
        }
    }
}

答案 1 :(得分:1)

您可以简单地定义自定义错误代码,使其不与Windows返回值“冲突”。当然,你不知道微软什么时候会添加新的返回值,所以这总是有点不稳定。

您可以尝试这样的事情:

enum MYERR
{
    MYERR_FIRST_ERROR   = 0x0F000000, /* large and unlikely to be used */
    MYERR_SECOND_ERROR,
    MYERR_THIRD_ERROR,
    /* and so on */
};

但是,正如Cody Gray上面所说,我认为你最好从DoModal返回一个标准错误代码,例如IDABORT,而不是像这样重载返回代码。然后只需要一个用户必须显式检索的二级错误代码,这是您自己的“内部”错误代码。

答案 2 :(得分:0)

您可以使用枚举而不是宏定义的返回码,使用命名空间以避免名称冲突。看看Boost Error Handling Policy

namespace boost { namespace math { namespace policies {

enum error_policy_type
{
   throw_on_error = 0, // throw an exception.
   errno_on_error = 1, // set ::errno & return 0, NaN, infinity or best guess.
   ignore_error = 2, // return 0, NaN, infinity or best guess.
   user_error = 3  // call a user-defined error handler.
};

}}} // namespaces