C ++ / Windows API - Невозможно найти CreateWindow - PullRequest
3 голосов
/ 24 марта 2011

Вот начало моей программы в 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;

IntelliSense в Visual C ++ говорит мне, что он не может найти CreateWindowW (хотя я вижу его, глядя на #define в Winuser.h и могу F12 перейти к определению функции). Он также не компилируется.

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

Есть идеи, что происходит?

Спасибо

Mike

Ответы [ 3 ]

8 голосов
/ 24 марта 2011

Может быть потому, что CreateWindowW() - это действительно макрос, который ссылается на CreateWindowExW()?

Попробуйте вместо этого использовать CreateWindowExW().

3 голосов
/ 24 марта 2011

Это код, предварительно обработанный для получения символа 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 напрямую или обернуть его в похожую группу макроопределений.

0 голосов
/ 24 марта 2011

Заранее извиняюсь, если я повторяю вещи, которые вы уже знаете.

По историческим причинам (и, я полагаю, для удобства) функции (например, CreateWindow), которые принимают строковые параметры, часто имеют две реализации, которые принимают строки, закодированные в ASCII.или строки, закодированные в Unicode.По соглашению им присваиваются имена A или W, чтобы различать их (например, CreateWindowA и CreateWindowW).

Обычно пустое имя функции # определяется как одно или другое на основе макроса UNICODE (вы можете увидеть это, посмотрев на определение CreateWindow в WinUser.h).Вот почему ваше использование CreateWindow превращается в ссылку на CreateWindowW.

Иногда такие функции, как CreateWindow, должны быть расширены путем добавления другого параметра.Опять же, по соглашению, эти функции часто называются путем добавления суффикса Ex к исходному имени функции.Это произошло с CreateWindow.

Если вы сравните определения CreateWindow и CreateWindowEx , вы обнаружите, что CreateWindowEx имеет дополнительный параметр - первый параметр в списке: DWORD dwExStyle.

Если вы посмотрите на определение CreateWindowW в WinUser.h, вы увидите, что 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;

Одна потенциальная «ошибка» заключается в том, что вы объявили такие параметры, как lpClassName, используя LPCWSTR, а не LPCTSTR.Это означает, что в сборках, отличных от 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;
...