Sunday, April 13, 2008

Why does ShowWindow cause a flicker?

When you call
ShowWindow(hwnd, SW_SHOW);
the WM_ERASEBKGND message is sent to the window procedure. If you are using your own custom paint routine, you probably don't need this. It will fill in your window with gray and then your paint routine will paint over it, but the gray fill appears briefly as a flicker. To prevent this, just override the WM_ERASEBKGND message handler.
case WM_ERASEBKGND:
return FALSE;

Friday, April 4, 2008

Why does my application fail when run on computers that don't have Visual Studio installed?

If you get an error message like "The application failed to initialize properly (0xc0150002)" when you try to run your application on a computer that doesn't have Visual Studio installed, it is probably because the proper C runtime DLLs are missing on that computer. This is one of the trickier aspects of using Microsoft's development tools because you need to have access to the same version of the DLLs that you linked with. So if you link dynamically to the C runtime library, you will have to either include the C runtime DLLs with your installer or provide a way for users to obtain the propert DLLs. To me this seems like a bad idea for most programs because it is rare that a program will use all that many functions in the runtime library. So for many cases it is probably more efficient to statically link the C runtime library using /MT on the command line instead of /MTD. This will usually yield binaries that are smaller than the combined size of the dynamically linked binary and the DLL file. Static linking will ensure that your program will run even without access to any DLLs.

Thursday, April 3, 2008

How do I send trace messages to the debug console in Visual Studio?

If you are not using MFC or ATL then there are some basic macros in crtdbg.h that allow you to write to the debug console in Visual Studio. The only problem is that they are not very user friendly - you have to use a different macro depending on how many parameters you have in your formatted string. I suspect that the reason behind this is that prior to the C99 specification there was no support for variadic macros. However, now that almost all compilers are C99 compliant, it is probably worth using a more convenient trace command for debugging purposes. The following macro works just like printf except that it sends its output to the debug console.
#include <stdio.h>
#include <crtdbg.h>
#define TRACE(...) \
do{ \
char *__trace = NULL; \
int len = 1+_scprintf(__VA_ARGS__); \
__trace = (char*)malloc(len*sizeof(char)); \
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); \
sprintf_s(__trace, len, __VA_ARGS__); \
_RPT0(_CRT_WARN, __trace); \
if(__trace != NULL) \
free(__trace); \
} while(0)
This uses the do-while trick so that the calling syntax includes a trailing semicolon. This will only work when you compile with the debug version of the C runtime libraries (/MTd for example).

Wednesday, April 2, 2008

How do I disable font anti-aliasing (font smoothing) for a window?

This can be accomplished by creating a font with the NONANTIALIASED_QUALITY flag in the fdwQuality parameter. Then set the font by sending the WM_SETFONT message.
void DisableFontSmoothing(HWND hwnd)
{
HFONT font;

font = CreateFont(10, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
NONANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
"MS Sans Serif");
SendMessage(hwnd, WM_SETFONT, (LPARAM)font, 0);
}
Be sure that you do not delete the font or else it will revert back. If you do not know what the font parameters will be at compile time, then you could modify this function to use WM_CHOOSEFONT_GETLOGFONT and WM_CHOOSEFONT_SETLOGFONT messages with a command to set the NONANTIALIASED_QUALITY flag in between.