简体   繁体   English

C ++ / Windows API - 无法找到CreateWindow

[英]C++/Windows API - Unable to find CreateWindow

Here's the start of my program in Visual C++ 2010 Express: 这是我在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). Visual C ++的IntelliSense告诉我它找不到CreateWindowW (即使我看到它在Winuser.h中查看#define而我可以在F12中找到函数定义)。 It doesn't compile, either. 它也没有编译。

dllmain.cpp(11): error C2065: 'CreateWindowW' : undeclared identifier

Any idea what's happening? 知道发生了什么事吗?

Thanks, 谢谢,

Mike 麦克风

Could it be because CreateWindowW() is really a macro that references CreateWindowExW() ? 可能是因为CreateWindowW()实际上是一个引用CreateWindowExW()的宏?

Try using CreateWindowExW() instead. 请尝试使用CreateWindowExW()

This is the code being preprocessed to end up with a symbol for CreateWindow (from WinUser.h): 这是预处理的代码,最终得到CreateWindow的符号(来自WinUser.h):

WINUSERAPI
HWND
WINAPI
CreateWindowExW(
    __in DWORD dwExStyle,
    ... params
    __in_opt LPVOID lpParam);

#define CreateWindowEx  CreateWindowExW

#define CreateWindowW(lpClassName, ... parameters )\
  CreateWindowExW(0L, lpClassName, ... parameters )

#define CreateWindow  CreateWindowW

The preprocessor will replace the symbol "CreateWindow" by the identifier "CreateWindowW" where it bumps into it. 预处理器将用标识符“CreateWindowW”替换符号“CreateWindow”,它会碰到它。

Next, although "CreateWindowW" is a macro, it can not expanded because there are no arguments to it. 接下来,虽然“CreateWindowW”是一个宏,但它无法扩展,因为它没有参数。

That is why CreateWindowW is not found. 这就是找不到CreateWindowW原因。 You may want to use CreateWindowExW directly, or wrap it in a similar bunch of macro definitions. 您可能希望直接使用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. 由于历史原因(以及我认为方便),采用字符串参数的函数(如CreateWindow)通常有两个实现,它们采用ASCII编码的字符串或Unicode编码的字符串。 By convention they are named with an A or W to distinguish them (eg, CreateWindowA and CreateWindowW). 按照惯例,它们以A或W命名以区分它们(例如,CreateWindowA和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). 通常,基于宏UNICODE的#defined是#defined为一个或另一个(通过查看WinUser.h中CreateWindow的定义可以看到)。 That's why your use of CreateWindow is turning into a reference to CreateWindowW. 这就是你使用CreateWindow变成对CreateWindowW的引用的原因。

Sometimes, functions like CreateWindow have to be extended by adding another parameter. 有时,必须通过添加另一个参数来扩展CreateWindow之类的函数。 Again by convention these functions are often named by adding an Ex suffix to the original function name. 按照惯例,这些函数通常通过在原始函数名称中添加Ex后缀来命名。 That has happened with CreateWindow. 这就发生在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. 如果比较CreateWindowCreateWindowEx的定义,您会发现CreateWindowEx有一个附加参数 - 列表中的第一个参数: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. 如果你看一下WinUser.h中CreateWindowW的定义,你会看到CreateWindowW扩展为CreateWindowExW上的一个调用,使用0L作为第一个参数的值,并使用11个CreateWindowW参数作为第二个到第十二个CreateWindowExW参数。

As @Jonathan Wood already suggested, you can get the code to compile by using CreateWindowEx instead of CreateWindow. 正如@Jonathan Wood已经建议的那样,您可以使用CreateWindowEx而不是CreateWindow来编译代码。 To do that you'll also have to add the dwExStyle parameter to your declaration. 为此,您还必须将dwExStyle参数添加到声明中。 For example 例如

HWND (WINAPI *pCreateWindow)(DWORD dwExStyle, LPCWSTR lpClassName,
    LPCWSTR lpWindowName, DWORD dwStyle,
    int x, int y, int nWidth, int nHeight,
    HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
    LPVOID lpParam) = CreateWindowEx;

One potential "gotcha" is that you've declared parameters like lpClassName using LPCWSTR rather than LPCTSTR. 一个潜在的“问题”是你使用LPCWSTR而不是LPCTSTR声明了像lpClassName这样的参数。 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. 这意味着在非Unicode版本中,CreateWindowEx将扩展为ASCII版本CreateWindowExA,但您的字符串参数类型仍将扩展为W版本,因此您将不匹配。

To be consistent you should really either change the LPCWSTR parameters to be LPCTSTR or else explicitly use CreateWindowExW in your declaration. 为了保持一致,您应该将LPCWSTR参数更改为LPCTSTR,或者在声明中明确使用CreateWindowExW。 To avoid future confusion it would also be good to rename the pointer to match the parameter list and implementation 为了避免将来混淆,重命名指针以匹配参数列表和实现也是一件好事

HWND (WINAPI *pCreateWindowExW)(DWORD dwExStyle, LPCWSTR lpClassName,
    LPCWSTR lpWindowName, DWORD dwStyle,
    int x, int y, int nWidth, int nHeight,
    HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
    LPVOID lpParam) = CreateWindowExW;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM