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

Posted

技术标签:

【中文标题】C++/Windows API - 无法找到 CreateWindow【英文标题】:C++/Windows API - Unable to find CreateWindow 【发布时间】:2011-03-23 21:20:24 【问题描述】:

这是我在 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

知道发生了什么吗?

谢谢,

迈克

【问题讨论】:

【参考方案1】:

会不会是因为CreateWindowW()真的是一个引用CreateWindowExW()的宏?

尝试改用CreateWindowExW()

【讨论】:

做到了。非常感谢。所以基本上,在一个 API“函数”实际上是另一个函数的简化宏的情况下,我必须小心。【参考方案2】:

这是经过预处理的代码,以 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

预处理器会将符号“CreateWindow”替换为它遇到的标识符“CreateWindowW”。

接下来,虽然“CreateWindowW”是一个宏,但它不能扩展,因为它没有参数。

这就是找不到CreateWindowW 的原因。您可能想直接使用CreateWindowExW,或者将其包装在类似的一组宏定义中。

【讨论】:

哇!随着时间的推移,用一些宏“修复”Windows 的 A 和 W 接口的想法变得更糟了。:-((( @Bo Persson:我非常同意这一点。也许一堆小的函数包装器会更好......【参考方案3】:

如果我重复你已经知道的事情,请提前道歉。

由于历史原因(我想也是为了方便),采用字符串参数的函数(如 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;

【讨论】:

以上是关于C++/Windows API - 无法找到 CreateWindow的主要内容,如果未能解决你的问题,请参考以下文章

无法在目标 c 中调用方法

Qt实用技巧:Qt中添加对windows api的支持,显示/隐藏任务栏和桌面(解决无法找到windows api)

Qt实用技巧:Qt中添加对windows api的支持,显示/隐藏任务栏和桌面(解决无法找到windows api)

C# Windows 服务无法将关闭事件记录到远程 API

无法找到脚本文件 C:/Windows/explorer.exe:574323188.vbs

小白学Pytorch系列--Torch.nn API Vision Layers(15)