3

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

何が起こっているのか分かりますか?

ありがとう、

マイク

4

3 に答える 3

8

CreateWindowW()が実際に参照するマクロだからCreateWindowExW()でしょうか?

CreateWindowExW()代わりに使用してみてください。

于 2011-03-23T21:26:41.273 に答える
3

これは、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するか、同様の一連のマクロ定義でラップすることができます。

于 2011-03-23T21:41:06.373 に答える
0

すでに知っていることを繰り返している場合は、事前にお詫び申し上げます。

歴史的な理由から (そして便宜上)、文字列パラメーターを受け取る関数 (CreateWindow など) には、ASCII でエンコードされた文字列または Unicode でエンコードされた文字列を受け取る 2 つの実装があることがよくあります。慣例により、それらを区別するために A または W で名前が付けられます (例: CreateWindowA と CreateWindowW)。

通常、生の関数名はマクロ UNICODE に基づいて #define されます (WinUser.h の CreateWindow の定義を見ればわかります)。これが、CreateWindow の使用が CreateWindowW への参照に変わる理由です。

場合によっては、別のパラメーターを追加して CreateWindow などの関数を拡張する必要があります。ここでも慣例により、これらの関数は元の関数名に Ex サフィックスを追加して名前が付けられることがよくあります。それはCreateWindowで起こりました。

CreateWindowCreateWindowExの定義を比較すると、CreateWindowEx には追加のパラメーター (リストの最初のパラメーター: DWORD dwExStyle) があることがわかります。

WinUser.h の CreateWindowW の定義を見ると、最初のパラメーターの値として 0L を使用し、2 番目から 12 番目の CreateWindowExW パラメーターとして 11 個の CreateWindowW パラメーターを使用して、CreateWindowW が CreateWindowExW の呼び出しに展開されることがわかります。

@Jonathan Wood が既に提案したように、CreateWindow の代わりに CreateWindowEx を使用してコンパイルするコードを取得できます。これを行うには、宣言に 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;

潜在的な「落とし穴」の 1 つは、LPCTSTR ではなく LPCWSTR を使用して 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;
于 2011-03-23T22:02:10.157 に答える