Как я могу вызвать GetWindowLongPtr и SetWindowLongPtr на 32-битных платформах? - PullRequest
13 голосов
/ 27 июля 2010

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

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

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

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

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

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

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

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

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

Ответы [ 2 ]

17 голосов
/ 27 июля 2010

Я бы порекомендовал вам справиться с этим так, как 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);
4 голосов
/ 27 июля 2010
  1. Откройте файл заголовка (на странице MSDN он указан как Winuser.h).Заголовки Win32 обычно находятся в C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. Поиск всех экземпляров SetWindowLongPtr / GetWindowLongPtr.
  3. Обратите внимание, что когда определено _WIN64, они являются функциями;в противном случае они имеют значения #define 'до 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 для собственного кода.

...