C++/Windows API - Невозможно найти CreateWindow
Вот начало моей программы в 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
Есть идеи, что происходит?
Спасибо,
Майк
3 ответа
Может ли это быть потому, что CreateWindowW()
действительно макрос, который ссылается CreateWindowExW()
?
Попробуйте использовать CreateWindowExW()
вместо.
Этот код предварительно обрабатывается, чтобы получить символ 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
непосредственно, или оберните это в подобную связку макроопределений.
Заранее извиняюсь, если я повторяю то, что вы уже знаете.
По историческим причинам (и, я полагаю, для удобства) функции (например, CreateWindow), которые принимают строковые параметры, часто имеют две реализации, которые принимают строки, закодированные в ASCII, или строки, закодированные в Unicode. По соглашению они обозначаются буквой A или W, чтобы различать их (например, CreateWindowA и CreateWindowW).
Обычно пустое имя функции #defined определяется как одно или другое на основе макроса 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;