SetCommState, SetCommState, Wherefore Art Thou?

Dear Dr. GUI:

I recently wrote a communication application with Visual C++ 4.1 and MFC 4.0. I call the SetCommState function in my application. I compiled the .CPP file that includes the call to the SetCommState function, but it failed. Then I added a line to the .CPP file:

#include <winbase.h>

and compiled the code again; it also failed.

I don't know what's wrong. How can I do this?

Qun Liu

Dr. GUI replies:

You are probably getting errors like:

error C2065: 'SetCommState' : undeclared identifier

error C2064: term does not evaluate to a function

For optimization purposes, AppWizard (versions 4.0 and later) adds a symbol called VC_EXTRALEAN to STDAFX.H. This symbol speeds up compilation by excluding less frequently used declarations. VC_EXTRALEAN is defined in AFXV_W32.H as:


#ifdef VC_EXTRALEAN
#define WIN32_EXTRA_LEAN
#define NOSERVICE
#define NOMCX
#define NOIME
#define NOSOUND
#define NOCOMM
#define NOKANJI
#define NORPC
#define NOPROXYSTUB
#define NOIMAGE
#define NOTAPE
 
#ifndef NO_ANSIUNI_ONLY
#ifdef _UNICODE
#define UNICODE_ONLY
#else
#define ANSI_ONLY
#endif
#endif //!NO_ANSIUNI_ONLY
 
#endif //VC_EXTRALEAN

Note that NOCOMM is defined along with VC_EXTRALEAN. In WINBASE.H, SetCommState is not declared if NOCOMM is defined.

One solution is to remove the #define VC_EXTRALEAN line from stdafx.h. This keeps the Communication, Registry, and other areas of the Win32 APIs that are not directly used by MFC in the project. But your builds will be substantially slower if you do this.

An alternative is to replace the "#define VC_EXTRALEAN" line with the set of #define lines listed above and then selectively remove any #define that should not be included. For instance, if the Communication APIs are called, you may have all the #define lines listed above except the "#define NOCOMM" line in the stdafx.h.

This is also documented in the Microsoft Knowledge Base article Q151666—PRB: C2065/C2064 "Errors when Using Win32 APIs in MFC Program."