I have some code that looks as follows:
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
just shows a progress bar. On any error, the progress bar is automatically closed by calling EndDialog(MYCLASS_ERROR)
. Only on successful completion will the user be allowed to click on 'OK' there.MYCLASS_ERROR
is a value in an enum
which contains all sorts of
return types and statuses.I found that on clicking OK in SomeDialog
, the error message still displayed! I dug a little deeper and found that MYCLASS_ERROR
= IDOK
= 1.
So my question is, how should I define all these return statuses such that it doesn't collide with any other implementation's statuses? Meaning, my functions should return values that is not returned by any other function (or as few other functions as possible).
I thought of modifying my design such that all functions only returned TRUE or FALSE. But, this would not be feasible in all cases. I have also searched quite a bit for answers and haven't found any thus far.
Thanks for looking!
There are ways to work around this, but they're kind of ugly.
The cleanest design is usually the one that avoids clashing with standard Win32 idioms, and in the world of Win32, modal dialogs return one of the ID
values to indicate the button that the user clicked when dismissing them (just like message boxes). Strictly speaking, it's the nResult
parameter that was passed to the EndDialog
function used to close the modal dialog box.
I recommend not trying to overload this return value with additional meaning. Trying to do so will just run you into trouble (for example, you probably also haven't noticed yet that a return value of -1 means that the creation of the dialog box failed).
Instead, define an additional member variable in your dialog class and use this to report your additional information. On success, you will return IDOK
from the dialog. On failure (any kind of failure), return something like IDCANCEL
. Your code inside of OnButtonClick
would then check to see if the return value is IDOK
or IDCANCEL
. If it's IDCANCEL
, then you also need to query the value of the member variable you added to the dialog for additional information.
Hopefully that made sense. If not, maybe this code example will (assume that m_errStatus
is the member variable you added to your subclass of 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.
}
}
}
You could simply define your custom error codes to not "clash" with the Windows return values. Of course, you don't know when Microsoft will add new return values, so this will always be a little flakey.
You could try something like this:
enum MYERR
{
MYERR_FIRST_ERROR = 0x0F000000, /* large and unlikely to be used */
MYERR_SECOND_ERROR,
MYERR_THIRD_ERROR,
/* and so on */
};
But, as Cody Gray notes above, I think you're better off returning a standard error code from DoModal
, such as IDABORT
instead of overloading the return codes like that. Then simply have a secondary error code that users must explicitly retrieve, which is your own "internal" error code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With