Although message boxes are customarily used to convey messages and ask questions in finished programs, they are also helpful in debugging. For instance, you may be familiar with the assert macro included in the ASSERT.H header file with the Microsoft C Compiler. This macro is used for testing various conditions during a program's execution. If the condition does not hold, the macro displays the current source code filename and line number and terminates the program. You can create a similar macro for Windows:
#ifndef NDEBUG
#define WinAssert(exp)\
{\
if (!(exp))\
{\
char szBuffer [40] ;\
sprintf (szBuffer, "File %s, Line %d",\
__FILE__, __LINE__) ;\
MessageBox (NULL, szBuffer,\
"Assertion Error",\
MB_OK | MB_ICONSTOP) ;\
}\
}
#else
#define WinAssert(exp)
#endif
You can then make various assertions in your code. For instance, to be sure that the value of hwnd in a certain section of your program is never NULL, you can do this:
WinAssert (hwnd != NULL) ;
If hwnd is NULL when this statement is executed, the message box will be displayed to alert you to the problem. A macro is used rather than a function, because the predefined identifiers __FILE__ and __LINE__ must equal the source code filename and line number where the assertion failed. If you used a function, these identifiers would always be set to the filename and line number where the function was located.
Unlike assert, the WinAssert macro shown above doesn't terminate the program if the assertion fails. If you use a debugging terminal, you can use a different version of this macro shown below. When you select the Abort button, the FatalExit function is called to display a stack trace on the debugging terminal.
if (IDABORT == MessageBox (NULL, szBuffer,
"Assertion Error",
MB_ABORTRETRYIGNORE | MB_ICONSTOP))
FatalExit (-1) ;
Once you've finished debugging the program, you can compile with the identifier NDEBUG, defined by using the compiler switch -D NDEBUG. The WinAssert macro will then be defined as nothing.