Как делают меня pinvoke к GetWindowLongPtr и SetWindowLongPtr на 32-разрядных платформах?

Я хочу к P/Invoke к GetWindowLongPtr и SetWindowLongPtr, и я вижу конфликтующую информацию о них.

Некоторые источники говорят, что на 32-разрядных платформах GetWindowLongPtr является просто макросом препроцессора, который называет GetWindowLong, и GetWindowLongPtr не существует как точка входа в user32.dll. Например:

  • Запись pinvoke.net для SetWindowLongPtr имеет статический метод, который проверяет IntPtr. Размер и затем называет или SetWindowLong или SetWindowLongPtr с комментарием, говоря, что "Ose прежней версии не поддерживают SetWindowLongPtr". Нет никакого объяснения того, что предназначено "Ose прежней версии".
  • Ответ на состояниях StackOverflow "В системах на 32 бита, GetWindowLongPtr является просто макросом C, который указывает на GetWindowLong".

Таким образом, эти источники, кажется, указывают, что *точки входа Ptr просто не находятся там в версии user32.dll, который поставлется с, скажем, 32-разрядным Windows 7.

Но я не вижу признака этого в документации MSDN. Согласно MSDN, SetWindowLongPtr заменяет SetWindowLong, простой и простой. И согласно разделу требований страницы SetWindowLongPtr, кажется, что SetWindowLongPtr был в user32.dll начиная с Windows 2000 (оба выпуска клиента и сервера). Снова, никакое упоминание о точках входа, являющихся недостающим в 32-разрядных Ose.

Я подозреваю, что истина является где-нибудь промежуточной: это, когда Вы говорите компилятору C++ предназначаться для более старых Ose (т.е. скомпилировать что-то, что будет работать на Win9x и NT4), затем заголовочные файлы объявляют SetWindowLongPtr как макрос, который называет SetWindowLong, но точка входа, вероятно, существует в Windows 2000 и позже и Вы получите его непосредственно (вместо макроса), если Вы скажете компилятору предназначаться для тех платформ. Но это - просто предположение; у меня действительно нет ресурсов или ноу-хау, чтобы закопать и проверить его.

Также возможно, что целевая платформа играет роль - что при компиляции приложения для x86 платформы, затем Вы не должны называть SetWindowLongPtr на 64-разрядной ОС. Снова, я знаю достаточно для размышления о вопросе, но я не знаю, как найти ответ. MSDN, кажется, предполагает, что SetWindowLongPtr всегда корректен.

Кто-либо может сказать мне, безопасно ли это только к P/Invoke к SetWindowLongPtr и быть сделанным с ним? (Примите Windows 2000 и позже.) Был бы P/Invoking к SetWindowLongPtr давать мне корректную точку входа:

  • если я запускаю приложение, предназначающееся для x86 платформы на 32-разрядной ОС?
  • если я запускаю приложение, предназначающееся для x86 платформы на 64-разрядной ОС?
  • если я запускаю приложение, предназначающееся для x64 платформы на 64-разрядной ОС?

13
задан Community 23 May 2017 в 11:45
поделиться

2 ответа

Я бы порекомендовал вам разобраться с этим способом, которым Windows Forms делает это изнутри:

public static IntPtr GetWindowLong(HandleRef hWnd, int nIndex)
{
    if (IntPtr.Size == 4)
    {
        return GetWindowLong32(hWnd, nIndex);
    }
    return GetWindowLongPtr64(hWnd, nIndex);
}


[DllImport("user32.dll", EntryPoint="GetWindowLong", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowLong32(HandleRef hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint="GetWindowLongPtr", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);
17
ответ дан 1 December 2019 в 22:38
поделиться
  1. Откройте заголовочный файл (на странице MSDN он указан как Winuser.h). Заголовки Win32 обычно находятся по адресу C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. Найдите все экземпляры SetWindowLongPtr/GetWindowLongPtr.
  3. Обратите внимание, что когда _WIN64 определен, они являются функциями; когда его нет, они #define'd to SetWindowLong/GetWindowLong.

Это подразумевает, что 32-битные ОС могут не иметь SetWindowLongPtr/GetWindowLongPtr в качестве фактической функции, так что, похоже, комментарий на pinvoke.net верен.

Обновление (больше разъяснений по поводу _WIN64):

_WIN64 определяется компилятором C/C++ при компиляции 64-битного кода (который будет работать только на 64-битной ОС). Это означает, что любой 64-битный код, использующий SetWindowLongPtr/GetWindowLongPtr, будет использовать фактические функции, но любой 32-битный код, использующий их, будет использовать SetWindowLong/GetWindowLong вместо них. Это относится и к 32-битному коду, работающему на 64-битной ОС.

Чтобы эмулировать такое же поведение в C#, я рекомендую проверить IntPtr.Size, как это сделано в pinvoke.net; это подскажет вам, выполняете ли вы 32-битный или 64-битный код. (Помните, что 32-битный код может работать на 64-битной ОС). Использование IntPtr.Size в управляемом коде эмулирует такое же поведение, как _WIN64 для родного кода.

4
ответ дан 1 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: