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;
Другие вопросы по тегам