Я хочу к P/Invoke к GetWindowLongPtr и SetWindowLongPtr, и я вижу конфликтующую информацию о них.
Некоторые источники говорят, что на 32-разрядных платформах GetWindowLongPtr является просто макросом препроцессора, который называет GetWindowLong, и GetWindowLongPtr не существует как точка входа в user32.dll. Например:
Таким образом, эти источники, кажется, указывают, что *точки входа 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 давать мне корректную точку входа:
Я бы порекомендовал вам разобраться с этим способом, которым 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);
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
SetWindowLongPtr
/GetWindowLongPtr
. _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
для родного кода.