如果我重复你已经知道的事情,请提前道歉。
出于历史原因(我想也是为了方便),采用字符串参数的函数(如 CreateWindow)通常有两个实现,它们采用以 ASCII 编码的字符串或以 Unicode 编码的字符串。按照惯例,它们用 A 或 W 命名以区分它们(例如,CreateWindowA 和 CreateWindowW)。
通常,裸函数名称是 #defined 是基于宏 UNICODE 的一个或另一个(您可以通过查看 WinUser.h 中 CreateWindow 的定义来了解这一点)。这就是您对 CreateWindow 的使用变成对 CreateWindowW 的引用的原因。
有时,像 CreateWindow 这样的函数必须通过添加另一个参数来扩展。同样按照惯例,这些函数通常通过在原始函数名称中添加 Ex 后缀来命名。CreateWindow 发生了这种情况。
如果您比较CreateWindow和CreateWindowEx的定义,您会发现 CreateWindowEx 有一个附加参数 - 列表中的第一个参数:DWORD dwExStyle。
如果查看 WinUser.h 中 CreateWindowW 的定义,您会看到 CreateWindowW 扩展为对 CreateWindowExW 的调用,使用 0L 作为第一个参数的值,并使用十一个 CreateWindowW 参数作为第二个到第十二个 CreateWindowExW 参数。
正如@Jonathan Wood 已经建议的那样,您可以使用 CreateWindowEx 而不是 CreateWindow 来编译代码。为此,您还必须将 dwExStyle 参数添加到您的声明中。例如
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;
一个潜在的“陷阱”是您使用 LPCWSTR 而不是 LPCTSTR 声明了像 lpClassName 这样的参数。这意味着在非 Unicode 版本中 CreateWindowEx 将扩展为 ASCII 版本 CreateWindowExA 但您的字符串参数类型仍将扩展为 W 版本,因此您将出现不匹配。
为了保持一致,您实际上应该将 LPCWSTR 参数更改为 LPCTSTR,或者在声明中明确使用 CreateWindowExW。为避免将来出现混淆,最好重命名指针以匹配参数列表和实现
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;