¿Cómo pinvoke a GetWindowLongPtr y SetWindowLongPtr en plataformas de 32 bits?

Quiero P / Invocar a GetWindowLongPtr y SetWindowLongPtr , y veo información conflictiva sobre ellos.

Algunas fonts dicen que, en plataformas de 32 bits, GetWindowLongPtr es solo una macro de preprocesador que llama a GetWindowLong, y GetWindowLongPtr no existe como un punto de entrada en user32.dll. Por ejemplo:

  • La entrada de pinvoke.net para SetWindowLongPtr tiene un método estático que comprueba IntPtr.Size y luego llama a SetWindowLong o SetWindowLongPtr, con un comentario que dice que “los sistemas operativos heredados no son compatibles con SetWindowLongPtr”. No hay explicación de lo que significa “sistemas operativos heredados”.
  • Una respuesta en StackOverflow dice “En los sistemas de 32 bits GetWindowLongPtr es solo una macro C que apunta a GetWindowLong”.

Así que estas fonts parecen indicar que los puntos de entrada * Ptr simplemente no están en la versión de user32.dll que viene con, digamos, Windows 7 de 32 bits.

Pero no veo ninguna indicación de esto en la documentación de MSDN. Según MSDN, SetWindowLongPtr reemplaza SetWindowLong, simple y llanamente. Y de acuerdo con la sección de requisitos de la página SetWindowLongPtr , parece que SetWindowLongPtr ha estado en user32.dll desde Windows 2000 (ediciones cliente y servidor). Nuevamente, no se mencionan los puntos de entrada que faltan en los sistemas operativos de 32 bits.

Sospecho que la verdad está en algún punto intermedio: que cuando le dices al comstackdor C ++ que se dirija a sistemas operativos más antiguos (es decir, que compile algo que se ejecutará en Win9x y NT4), los archivos de cabecera declaran SetWindowLongPtr como una macro que llama a SetWindowLong, pero el punto de entrada probablemente existe en Windows 2000 y posterior y lo obtendrá directamente (en lugar de la macro) si le dice al comstackdor que se dirija a esas plataformas. Pero eso es solo una suposición; Realmente no tengo los recursos o los conocimientos para cavar y verificarlo.

También es posible que la plataforma objective desempeñe un papel: si comstack su aplicación para la plataforma x86, no debería llamar a SetWindowLongPtr en un sistema operativo de 64 bits. De nuevo, sé lo suficiente como para pensar en la pregunta, pero no sé cómo encontrar la respuesta. MSDN parece sugerir que SetWindowLongPtr siempre es correcto.

¿Alguien puede decirme si es seguro simplemente P / invocar a SetWindowLongPtr y terminar con esto? (Supongamos que Windows 2000 y posterior.) P / Invocar a SetWindowLongPtr me da el punto de entrada correcto:

  • si ejecuto una aplicación orientada a la plataforma x86 en un sistema operativo de 32 bits?
  • si ejecuto una aplicación orientada a la plataforma x86 en un sistema operativo de 64 bits?
  • si ejecuto una aplicación orientada a la plataforma x64 en un sistema operativo de 64 bits?

Te recomendaría que lidies con esto de la misma forma que Windows Forms lo hace internamente:

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); 
  1. Abra el archivo de encabezado (en la página de MSDN, esto se muestra como Winuser.h). Los encabezados de Win32 generalmente se encuentran en C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. Busque todas las instancias de SetWindowLongPtr / GetWindowLongPtr .
  3. Tenga en cuenta que cuando se define _WIN64 , son funciones; cuando no lo es, están #define a SetWindowLong / GetWindowLong .

Esto implica que los sistemas operativos de 32 bits pueden no tener SetWindowLongPtr / GetWindowLongPtr como una función real, por lo que parece que el comentario en pinvoke.net es correcto.

Actualización (más aclaraciones sobre _WIN64):

_WIN64 está definido por el comstackdor C / C ++ al comstackr código de 64 bits (que solo se ejecutará en un sistema operativo de 64 bits). Esto significa que cualquier código de 64 bits que use SetWindowLongPtr / GetWindowLongPtr usará las funciones reales, pero cualquier código de 32 bits que lo use usará SetWindowLong / GetWindowLong lugar. Esto incluye código de 32 bits que se ejecuta en un sistema operativo de 64 bits.

Para emular el mismo comportamiento en C #, recomiendo comprobar IntPtr.Size como hecho por pinvoke.net; eso le dice si está ejecutando código de 32 bits o de 64 bits. (Teniendo en cuenta que el código de 32 bits puede ejecutarse en un sistema operativo de 64 bits). El uso de IntPtr.Size en el código administrado emula el mismo comportamiento que _WIN64 para el código nativo.