Acceder al API de Windows



Actualizado 23/10/2018.

Una de las características más interesantes que presenta CPython es que corre bajo gran cantidad de sistemas operativos. Es por esto que la mayoría de nuestros programas podrán ejecutarse con normalidad en diversas plataformas sin modificar el código original. Python nos permite acceder al API de Windows, por lo que, al utilizarse, el código en cuestión sólo podrá ejecutarse en dicho sistema operativo. El simple hecho de hacerlo le quitaría al lenguaje una de sus cualidades, a mi parecer, más útiles. Sin embargo, en muchas ocasiones resulta conveniente tener acceso a la gran cantidad de funciones que nos presenta el sistema de las ventanas. Es por eso que he decidido dar a conocer los siguientes métodos para lograrlo.

Pywin32

El paquete se instala sencillamente vía pip:

pip install pywin32

Actualmente soporta Python 2.7 y 3.x, tanto sistemas de 32 bits como 64 bits. De todas maneras, es importante aclarar que si cuentas con un sistema de 64 bits pero te manejas con un intérprete de 32, deberás instalar la versión de 32 bits del paquete. Para determinar la versión de Python que actualmente corres, basta con abrir la línea de comandos del intérprete y observar la primera línea en la que encontrarás los detalles.

Sin nada más que aclarar, un ejemplo en el que ejecuto un sonido por el altavoz, muevo la posición del cursor y muestro un mensaje en pantalla:

from win32api import Beep, GetCursorPos, SetCursorPos, MessageBox
from win32con import MB_OK

if __name__ == "__main__":
    Beep(200, 200)
    pos = GetCursorPos()
    SetCursorPos((pos[0] + 100, pos[1] + 100))
    MessageBox(0, "Listo.", "Ejemplo Windows API", MB_OK)

El módulo win32api cuenta con gran cantidad de las funciones generales del API y win32con presenta numerosas constantes. Con la instalación de Pywin32 también obtenemos otros como win32gui para funciones en relación con interfaces gráficas, win32net, entre otras.

ctypes

Con el módulo ctypes también es posible acceder al API de Windows, y lo mejor, es parte de la librería estándar. Incluso, permite el acceso a gran cantidad de funciones del API las cuales no podremos encontrar, al menos por ahora, en Pywin32. Este módulo nos permite cargar cualquier librería mediante la función LoadLibrary. Sin embargo, no es necesario hacerlo con user32 y kernel32 (en donde se encuentran las funciones del API), ya que ctypes lo realiza automáticamente al iniciarse.

A continuación, el mismo ejemplo anterior con ctypes. A diferencia de Pywin32, ctypes no cuenta con las constantes como MB_OK, ni funciones adaptadas a los tipos propios del lenguaje (tuplas, listas), y en el caso de MessageBox, deberemos especificar si se trata de ANSI o UNICODE (MessageBoxA y MessageBoxW, respectivamente).

from ctypes import c_int, pointer, Structure, windll

MB_OK = 0x00000000

class POINT(Structure):
    _fields_ = [("x", c_int), ("y", c_int)]

if __name__ == "__main__":
    pos = POINT()
    windll.kernel32.Beep(200, 200)
    windll.user32.GetCursorPos(pointer(pos))
    windll.user32.SetCursorPos(pos.x + 100, pos.y + 100)
    windll.user32.MessageBoxA(0, "Listo.", "Ejemplo Windows API", MB_OK)

La función GetCursorPos toma como argumento un puntero que se dirige a una variable del tipo POINT para almacenar las coordenadas. Como en Python no es posible especificar si se trata de una variable por valor o referencia, hacemos uso de la función ctypes.pointer. Nótese también la creación de la clase POINT simulando una estructura.

Como habrás visto, el método de ctypes es ligeramente más complicado. Ambas alternativas para acceder al API cuentan con ventajas y desventajas; se trata de elegir la más adecuada para la tarea que deseas realizar.

Ante cualquier inquietud o duda, no olvides dejar tu comentario.



7 comentarios.

  1. Saludos amigos.. tengo una api EZClient.dll que contiene una función llamada ClientLogon con los siguientes parámetros

    […]

    Al ejecutarlo me da error de argumento y no logro resolverlo. Si alguien podría ayudarme les estaré muy agradecido desde ya gracias

  2. Hola, acabo de asomarme al mundo del api de windows y me gustaria saber si usando phyton, se puede acceder a todos los metodos que hay relativos a las ventanas, ejemplo :
    – se puede acceder a la función GetWindowRect -> según el api de windows se define asi:
    BOOL WINAPI GetWindowRect (
    _In_ HWND hWnd,
    _Out_ LPRECT lpRect
    );
    Gracias,
    Muy buen aporte, empezaré a trastear un poco haber como se me da.

    • Recursos Python says:

      Hola Carlos. Sí, es posible acceder a las funciones relacionadas con ventanas, tanto con pywin32 (vía import win32gui) como con ctypes. Si tenés algun problema podés crear un tema en el foro para verlo en detalle.

      Un saludo.

  3. Andres Niño says:

    Excelente post, por casualidad conoces de alguna forma para que el MessageBox se cierre automáticamente después de cierto tiempo.

    • Recursos Python says:

      Hola. Se me ocurre que puedes usar SendMessage para enviar WM_CLOSE al mensaje una vez transcurrido un determinado tiempo. Si tienes problemas te invito a que crees un nuevo tema en el foro y lo vemos.

      Un saludo.

Deja un comentario