Здесь начало моей программы в Visual С++ 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 С++ IntelliSense говорит мне, что он не может найти CreateWindowW
(хотя я вижу, что он смотрит на #define в Winuser.h, и я могу F12 перейти к определению функции). Он также не компилируется.
dllmain.cpp(11): error C2065: 'CreateWindowW' : undeclared identifier
Любая идея, что происходит?
Спасибо,
Mike
Может быть, потому что 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 или строки, закодированные в Юникоде. По соглашению они называются 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;