C++/Windows API - 无法找到 CreateWindow
下面是我在 Visual C++ 2010 Express 中的程序的开头:
#pragma comment(lib, "detoured.lib")
#pragma comment(lib, "detours.lib")
#include <Windows.h>
#include <detours.h>
HWND (WINAPI *pCreateWindow)(LPCWSTR lpClassName,
LPCWSTR lpWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
LPVOID lpParam) = CreateWindow;
Visual C++ 的 IntelliSense 告诉我它找不到 CreateWindowW
(即使我看到它正在查看 Winuser.h 中的 #define,我可以F12 转到函数定义)。它也无法编译。
dllmain.cpp(11): error C2065: 'CreateWindowW' : undeclared identifier
知道发生了什么吗?
谢谢,
迈克
Here's the start of my program in Visual C++ 2010 Express:
#pragma comment(lib, "detoured.lib")
#pragma comment(lib, "detours.lib")
#include <Windows.h>
#include <detours.h>
HWND (WINAPI *pCreateWindow)(LPCWSTR lpClassName,
LPCWSTR lpWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
LPVOID lpParam) = CreateWindow;
Visual C++'s IntelliSense is telling me that it can't find CreateWindowW
(even though I see it looking at the #define in Winuser.h and I can F12 to go to the function definition). It doesn't compile, either.
dllmain.cpp(11): error C2065: 'CreateWindowW' : undeclared identifier
Any idea what's happening?
Thanks,
Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
难道是因为
CreateWindowW()
确实是一个引用CreateWindowExW()
的宏吗?尝试使用 CreateWindowExW() 代替。
Could it be because
CreateWindowW()
is really a macro that referencesCreateWindowExW()
?Try using
CreateWindowExW()
instead.这是经过预处理的代码,最终得到
CreateWindow
的符号(来自 WinUser.h):预处理器将在遇到符号“CreateWindow”时用标识符“CreateWindowW”替换符号“CreateWindow”。
接下来,虽然“CreateWindowW”是一个宏,但它不能扩展,因为它没有参数。
这就是找不到
CreateWindowW
的原因。您可能想直接使用CreateWindowExW
,或者将其包装在类似的一组宏定义中。This is the code being preprocessed to end up with a symbol for
CreateWindow
(from WinUser.h):The preprocessor will replace the symbol "CreateWindow" by the identifier "CreateWindowW" where it bumps into it.
Next, although "CreateWindowW" is a macro, it can not expanded because there are no arguments to it.
That is why
CreateWindowW
is not found. You may want to useCreateWindowExW
directly, or wrap it in a similar bunch of macro definitions.如果我重复你已经知道的事情,请提前道歉。
出于历史原因(我想也是为了方便),采用字符串参数的函数(如 CreateWindow)通常有两种实现,采用 ASCII 编码的字符串或采用 Unicode 编码的字符串。按照惯例,它们用 A 或 W 命名以区分它们(例如,CreateWindowA 和 CreateWindowW)。
通常,裸函数名称是 #define 为基于宏 UNICODE 的其中之一(您可以通过查看 WinUser.h 中 CreateWindow 的定义看到这一点)。这就是为什么您对 CreateWindow 的使用变成了对 CreateWindowW 的引用。
有时,像 CreateWindow 这样的函数必须通过添加另一个参数来扩展。同样按照惯例,这些函数通常通过在原始函数名称中添加 Ex 后缀来命名。 CreateWindow 就发生过这种情况。
如果您比较 CreateWindow 和 < a href="http://msdn.microsoft.com/en-us/library/ms632680%28v=VS.85%29.aspx" rel="nofollow">CreateWindowEx 你会发现 CreateWindowEx 有附加参数 - 列表中的第一个参数:DWORD dwExStyle。
如果查看 WinUser.h 中 CreateWindowW 的定义,您将看到 CreateWindowW 扩展为对 CreateWindowExW 的调用,使用 0L 作为第一个参数的值,并使用 11 个 CreateWindowW 参数作为第二个到第十二个 CreateWindowExW 参数。
正如@Jonathan Wood 已经建议的那样,您可以使用 CreateWindowEx 而不是 CreateWindow 来编译代码。为此,您还必须将 dwExStyle 参数添加到您的声明中。例如,
一个潜在的“陷阱”是您使用 LPCWSTR 而不是 LPCTSTR 声明了 lpClassName 等参数。这意味着在非 Unicode 版本中 CreateWindowEx 将扩展为 ASCII 版本 CreateWindowExA 但您的字符串参数类型仍将扩展为 W 版本,因此您会遇到不匹配的情况。
为了保持一致,您实际上应该将 LPCWSTR 参数更改为 LPCTSTR,或者在声明中显式使用 CreateWindowExW。为了避免将来混淆,最好重命名指针以匹配参数列表和实现
Apologies in advance if I'm repeating things you already know.
For historical reasons (and convenience I suppose) functions (like CreateWindow) that take string parameters often have two implementations that take strings encoded in ASCII or strings encoded in Unicode. By convention they are named with an A or W to distinguish them (e.g., CreateWindowA and CreateWindowW).
Usually the bare function name is #defined to be one or the other based on the macro UNICODE (you can see that by looking at the definition of CreateWindow in WinUser.h). That's why your use of CreateWindow is turning into a reference to CreateWindowW.
Sometimes, functions like CreateWindow have to be extended by adding another parameter. Again by convention these functions are often named by adding an Ex suffix to the original function name. That has happened with CreateWindow.
If you compare the definitions of CreateWindow and CreateWindowEx you'll find that CreateWindowEx has an additional parameter - the first parameter in the list: DWORD dwExStyle.
If you look at the definition for CreateWindowW in WinUser.h, you'll see that CreateWindowW expands into a call on CreateWindowExW using 0L as the value for the first parameter and using the eleven CreateWindowW parameters as the second through twelfth CreateWindowExW parameters.
As @Jonathan Wood already suggested, you can get the code to compile by using CreateWindowEx instead of CreateWindow. To do that you'll also have to add the dwExStyle parameter to your declaration. For example
One potential "gotcha" is that you've declared parameters like lpClassName using LPCWSTR rather than LPCTSTR. That means in non-Unicode builds CreateWindowEx will expand to the ASCII version CreateWindowExA but your string parameters types will still expand to the W version so you'll have a mismatch.
To be consistent you should really either change the LPCWSTR parameters to be LPCTSTR or else explicitly use CreateWindowExW in your declaration. To avoid future confusion it would also be good to rename the pointer to match the parameter list and implementation