C++ Q&A 专栏...
原著:Paul DiLascia
翻译:James Liu
原文出处:MSDN Magazine Aug 2004 (C++ Q&A)
原代码下载: CQA0408.exe (234KB) GetKeyState 使用示例 STL 字符串类与 UNICODE 如何向C#或.NET框架暴露 C++ 对象? 如何获取专用文件夹的路径名?
我想让用户双击程序图标时按住 Control 键,以一种特殊的方式来启动程序。 但::GetCommandLine和__argc 均没有任何反应,用 MFC 中的 CCommandLineInfo 似乎也是如此。有没有一种方法可以解决这个问题呢? Dean Jones 有,非常简单。你所要做的就是调用 GetKeyState。当你正在处理的当前消息被发送时, 该函数返回虚拟键的状态。这个状态可能是弹起,按下,或者套索钉。套索钉用于大写锁定( Caps)和转换锁(Shift Lock),它们可以转换状态。对于一般的 键,如控制键(VK_CONTROL),如果键被按下,则其状态的高位标识位为 1。
许多的应用程序使用 Control+F8 作为特殊键来启动恢复模式。比如,如果应用程序允许用户 定制工作间,那么Control+F8就可以将其恢复到初始的默认设置,只是在恢复之前一定要让用户进行确认。做的更好一点的话,你可以在单独的INI文件中保存用户的设置,这样用户 有机会恢复它们。不管怎样,要想在程序启动时检查 Control 键,你可以像下面这样写:
if (GetKeyState(VK_CONTROL)<0){ // enter special mode}Figure 1 给出了一个基于 MFC 的示例程序代码段,你可以通过本文顶端的链接进行下载,如果用户在启动程序的时候按下Ctrl+F8,它将显示一个消息框,并且 发出蜂鸣声。如果你只是想检查 Control键,可以忽略对 VK_F8 键的测试。
我经常在 C++ 程序中使用标准模板库(STL)的 std::string 类,但在 使用 Unicode 时碰到了问题。在使用常规 C 风格的字符串时,我可以使用 TCHAR 和 _T 宏,这样针对 Unicode 或 ASCII 均可以进行编译,但我 总是发现这种ASCII/Unicode的结合很难与 STL 的 string 类一起使用。你有什么好的建议吗? Naren J.
是的,一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单。基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于 _UNICODE 的值:
// abridged from tchar.h#ifdef _UNICODEtypedef wchar_t TCHAR;#define __T(x) L ## x#elsetypedef char TCHAR;#define __T(x) x#endif当你在工程设置中选择 Unicode 字符集时,编译器会用 _UNICODE 定义进行编译。如果你选择MBCS(多字节字符集),则编译器将不会带 _UNICODE 定义 。一切取决于_UNICODE 的值。同样,每一个使用字符指针的 Windows API 函数会有一个 A(ASCII) 和一个 W(Wide/Unicode) 版本,这些版本的 实际定义也是根据 _UNICODE 的值来决定:
#ifdef UNICODE#define CreateFile CreateFileW#else#define CreateFile CreateFileA#endif同样,_tprintf 和 _tscanf 对应于 printf 和 scanf。所有带"t"的版本使用 TCHARs 取代了chars。那么怎样把以上的这些应用到 std::string 上呢?很简单。STL已经有一个使用宽字符定义的wstring类 (在 xstring 头文件中定义)。string 和 wstring 均是使用 typedef 定义的模板类,基于 basic_string, 用它可以创建任何字符类型的字符串类。以下就是 STL 定义的 string 和 wstring:
// (from include/xstring)typedef basic_string< char, char_traits< char >, allocator< char > > string;typedef basic_string< wchar_t, char_traits< wchar_t >, allocator< wchar_t > > wstring;模板被潜在的字符类型(char 或 wchar_t)参数化,因此,对于 TCHAR 版本,所要做的就是使用 TCHAR 来模仿定义。
typedef basic_string< TCHAR, char_traits< TCHAR >, allocator< TCHAR > > tstring;现在便有了一个 tstring,它基于 TCHAR——也就是说,它要么是 char,要么是 wchar_t,这取决于 _UNICODE 的值。 以上示范并指出了 STL 是怎样使用 basic_string 来实现基于任何类型的字符串的。定义一个新的 typedef 并不是解决此问题最有