C ++ / Windows API - Невозможно найти CreateWindow

3

Здесь начало моей программы в 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

Теги:
winapi
detours

3 ответа

7
Лучший ответ

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

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

  • 0
    Это сделал это. Большое спасибо. В общем, я должен быть осторожен в случаях, когда одна «функция» API действительно является макросом упрощения для другой функции.
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 напрямую или обернуть его в подобный набор макроопределений.

  • 0
    Вау! Идея «исправить» интерфейсы A и W в Windows с помощью нескольких макросов со временем просто ужасна.: - (((
  • 0
    @ Бо Перссон: Я вполне согласен с этим. Может быть, куча маленьких упаковщиков функций будет лучше ...
0

Извините заранее, если я повторяю то, что вы уже знаете.

По историческим причинам (и, я полагаю, удобнее) функции (такие как 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;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню