Indice
¿Que es el API
de Win32?
Llamadas a las Funciones
API
Librerias
Dinamicas
Declarando
una Funcion DLL
Algunas
Funciones API
Ejemplo:GetDeviceCaps
Ejemplo:
GetWindowsDirectory
Ejemplo: Rotar un
Texto
Algunas
APIs Interesantes...
Win32 es un conjunto de funciones,
tipos y mensajes pre-definidos para poder programar sobre los sistemas
operativos de 32 bits de Microsoft. El API Win32, surge para cubrir la necesidad
de crear un sistema operativo
de 32 bits como es Windows 95, frente al API
de 16 bits existente de Windows 3.1. Surge el problema de que Win32, no es
compatible con el API de 16 bits, lo que implica que si queremos portar un
código de Windows 3.1
a Windows 95, deberemos reescribir el código. Aunque
hemos dicho que el API Win32 no es compatible con el
API de 16 bits, hay una
versión que es Win32s que sirve para la versión 3.1 de Windows. Algunas de las
limita- ciones entre ambos API son:
Llamadas a las Funciones del API de Windows
Un programador de aplicaciones
Windows además de conocer el entorno de trabajo de Windows debe
conocer
también su entorno de programación, conocido generalmente como interfaz de
programación de aplicaciones de Windows ( Windows Application Programming
Interface, abreviadamente Windows API ).
La característica primaria de la
API de Windows son las funciones y los mensajes internos/externos de
Windows.
Las funciones Windows son el
corazón de las aplicaciones Windows. Hay más de 600 funciones de
Windows
dispuestas para ser llamadas por cualquier lenguaje, como C o Visual Basic.
A través de estos mecanismos,
podemos realizar gran cantidad de funciones que hasta el momento no
teníamos
ni idea que se podían realizar. La utilización de ésta serie de librerías que
contienen las funciones
de la API pueden solucionar gran cantidad de
problemas en la programación, aunque también no debemos desestimar el gran poder
destructivo de las mismas. La depuración de un programa es muy diferente si éste
tiene incorporadas llamadas a APIs, ya que el resultado de las mismas en
algunos casos puede llegar a ser incomprensible. Cuando se trabaja con éstas
funciones siempre es recomendable tener a mano una buena
guía o bien tener a
mano alguien que sepa, para no encontrarnos con posibles problemas.
Las dos principales ventajas
que obtenemos con la utilización de APIs es la gran funcionalidad que
podemos darle a nuestra aplicación, y en segundo lugar la gran velocidad de
proceso, ya que a menudo es
mucho más rápido realizar una función a través
de la API adecuada que por medio del lenguaje en si mismo.
Los mensajes son utilizados
por Windows para permitir que dos o más aplicaciones se comuniquen entre
sí
y con el propio sistema Windows. Se dice que las aplicaciones Windows son
conducidas por mensajes o
sucesos.
Conocer todas las APIs de Windows es imposible, ya que tiene gran similitud con aprenderse la guía de teléfonos.
Lo que debemos hacer es
realizar un razonamiento contrario, nosotros tenemos una necesidad a la
hora
de programar, y debemos pensar que eso tiene una solución con una API.. En la
mayoría de los casos
es así.
Casi todas las APIs de Windows se unen formando librerías de enlace dinámico.
Una librería dinámica ( Dynamic Link Libraries, abreviadamente DLLs ) permite
que las aplicaciones
Windows compartan código y recursos. Una DLL es
actualmente un fichero ejecutable que contiene funciones
de Windows que
pueden ser utilizadas por todas las aplicaciones.
Si bien en DOS estamos
acostumbrados a utilizar librerías de enlace estático, es decir, a la hora de
compilar incluyen junto con nuestro código, y de esta manera cuando se
ejecuta nuestra aplicación, todas las librerías se cargan en memoria esperando a
ser invocadas. Sin embargo, cuando trabajamos con DDLs, el
enlace con la
aplicación es dinámico en tiempo de ejecución.
Una DDL no se incluye dentro
de nuestro código, sino que en el momento que realizamos la llamada a
la
función, la DLL se carga en memoria, se utiliza la API, y a continuación se
descarga.
La gran ventaja que posee este
método es que no es necesario tener gran cantidad de código cargado
en
memoria a la hora de ejecutar nuestra aplicación. En contra, es necesario que
cuando llevemos nuestro ejecutable a otra instalación, tengamos que llevar las
DLLs necesarias.
También tenemos que pensar que
si utilizamos las DLLS que nos proporciona Windows, en cualquier
máquina con
este sistema operativo vamos a encontrar esas mismas DLLs, con lo cual no es
necesario que
nos las llevemos.
La utilización de librerías
dinámicas tiene ventajas. Una ventaja es que como están separadas del
programa se pueden actualizar sin tener que modificar los programas que las
utilizan. Otra ventaja es el
ahorro de memoria principal y de disco ya que
como es Windows quien administra la utilización de las DLLs,
no existe
duplicidad de código cuando varias aplicaciones las utilizan.
También, como todo (jeje)
tiene inconvenientes. Uno de ellos es el tiempo que Windows tiene que emplear
en leer las funciones que el programa necesita utilizar de una DLL.
Otra desventaja es que cada
programa ejecutable necesita que estén presentes las DLLs que utiliza.
Cuando se utilizan librerías
estáticas, las funciones que el programa necesita se incluyen en el mismo,
por lo que ni se pierde tiempo en leerlas ni la librería tiene que estar
presente.
La mayoría de éstas librerías suelen estar localizadas en el directorio SYSTEM de Windows.
Dentro de Windows tenemos gran
cantidad de DLLs, agrupando las APIs en funciones respecto a un
mismo tema.
Además en cada nueva versión de Windows, posiblemente tengamos más DLLs para
utilizar.
Para acceder a las funciones
de las librerías dinámicas, lo primero que debemos hacer es declararlas.
Declaración de una Función DLL.
Para declarar una función de una librería dinámica, tiene que escribir una sentencia declare en el módulo global de la aplicación, o en la sección de declaraciones de la forma o del módulo correspondiente. Por ejemplo:
Declare Function lopen Lib "kernel" Alias "_lopen" (Byval lpPathname as string, Byval iReadWrite As Integer) as Integer
La cláusula Lib indica al
lenguaje de programación la librería donde puede encontrar la función de la API
de Windows declarada. Las DLLs del entorno operativo están en "Kernel",
"GDI", "User", o en una de las
DLLs correspondientes a un driver de
dispositivo tal como "Sound". Para otras DLLs, el nombre incluye el
camino
completo. Por ejemplo: "c:windowssystemlzexpand.dll"
La cláusula alias indica que
la función tiene otro nombre en la librería dinámica ( DLL ). Esto es útil
cuando el nombre de la función coincide con alguna palabra clave, con alguna
variable o constante global, o
el nombre de la función DLL, tiene caracteres
no reconocidos por el lenguaje de programación.
La sentencia declare debe
contener asimismo una lista de los parámetros que se pasarán a la función.
La mayor parte del trabajo consiste en determinar cuáles serán esos
parámetros. Algo muy utilizado dentro
de los parámetros son lo que podemos
traducir como manejadores ( handles ). Esto es un valor entero único definido
por el entorno operativo y utilizado para referirse a objetos tales como
formularios, controles, etc. Un handle es un número de identificación. HWnd es
un handle para referirse a una ventana, hDC es un handle para referirse al
contexto de dispositivo de un objeto ( Device Context ). Cuando una función de
una DLL espera
recibir como argumento un handle, se debe declarar como ByVal
Integer.
Declare Function IsIconic Lib "User" (ByVal hWnd As Integer) As Integer
If IsIconic (Form1.hWnd) Then ....
El entorno operativo asigna un
handle a cada formulario de una aplicación para posteriormente identificarles.
La propiedad hWnd de un
formulario o de un control no gráfico permite acceder a este handle.
Por contexto de dispositivo se
entiende un conjunto de atributos (color de fondo, tipo de letra, espaciado
entre caracteres, posición actual de la pluma, paleta de colores, etc.) que
determinan la localización y la
apariencia de un objeto. Una aplicación
puede modificar estas propiedades a través del hDC del objeto.
Afortunadamente, Microsoft ha
pensado en el programador y proporciona una herramienta dentro de
algunos
lenguajes de programación de entorno visual como es el API viewer, en Visual
Basic versión 4.0.
Con ésta herramienta podemos
cargar unos archivos TXT que nos proporcionan las sentencias declare de
gran
cantidad de funciones API. Si no poseemos ningún tipo de ayuda respecto a una
API específica, es muy posible
que todos nuestros intentos en utilizarla
sean inútiles.
Para declarar una función de
una librería dinámica, se tiene que escribir en la sección de declaraciones de
un formulario o de un módulo de la aplicación en construcción.
Una función declarada en un
formulario es privada para este formulario, y declarada en un módulo es
pública, y por lo tanto puede ser llamada desde cualquier parte de la
aplicación.
Si la función no retorna un
valor, se declarará como un procedimiento o sub, aunque esta opción no se
utiliza casi nunca, pues la mayoría de las APIs retornan un valor, aunque
sea una verificación de su realización.
Los argumentos que se pasan a
una función pueden ser pasados por valor o por referencia. UN parámetro
por
valor quiere decir que lo que estamos metiendo dentro de la función es el
contenido de la variable, mientras
que por referencia se introduce la
dirección de memoria donde reside la variable que contiene el valor que queremos
pasar.
Habitualmente, dentro de
nuestro programa trabajamos con variables que se pasan por valor, es decir, no
nos interesa la posición de memoria de la variable, sino su contenido. Al
trabajar con APIs la cosa cambia. La mayoría
de estas funciones están
desarrolladas en C, y en este lenguaje se utiliza asiduamente los punteros
(direcciones de memoria )
Por defecto, los lenguajes
actuales de entorno visual pasa los argumentos por referencia ( utilizando
direcciones de
32 bits ).
Para pasar un argumento por valor, se debe de escribir la palabra clave ByVal delante de la declaración del argumento.
Algunas funciones aceptan más
de un tipo de datos para un mismo argumento, y esto se indica declarando
el
argumento como Any.
Declare Function Catch Lib "Kernel" (lpCatchBuf As Any) As Integer
Esta función puede ser llamada con un
argumento tipo cadena, de tipo largo, etc.
Algunas de las funciones del API, se pueden agrupar en:
- Funciones
de direccionamiento de memoria a 32 bits.
Recupera el API para aplicaciones que utilizan 32 bits.
-
Funciones de ejecución de aplicaciones.
Tiene la función de cargar y ejecutar aplicaciones.
ej: Winhelp
Loadmodule
- Funciones
bitmap.
Crea y maneja los bitmaps.
Createbitmap, crea un bitmap.
Getpixel, recupera el color RGB del pixel especificado.
-
Funciones callback o rellamada.
Recupera información sobre algo que se está ejecutando, con la posibilidad de
hacer algún cambio.
Abortproc, procesa los trabajos de impresora cancelados.
EnumFontFamProc, recupera información sobre las fuentes (tipo de letra)
disponibles.
- Funciones de cuadro de diálogo
común.
Funciones que actúan sobre una caja de diálogo común, cambiando su color, texto,
etc.
Choosecolor, crea una caja de diálogo seleccionando el color.
- Funciones de
comunicación.
Funciones que gestionan los dispositivos de comunicaciones.
Opencomm, abre un dispositivo de comunicaciones.
- Funciones de cursor.
Gestionan todo lo relacionado con el cursor.
Createcursor, crea un cursor con dimensiones especificadas.
- Funciones DDE (Data
Dinamic Exchange ).
Gestiona el intercambio de datos dinámico.
DdeAccessData, proporciona un acceso a un objeto con memoria global.
DdeGetdata, copia los datos de un objeto de memoria global a un buffer.
- Funciones de error.
Funciones que gestionan los errores de los dispositivos.
Debugoutput, envía mensajes al terminal erróneo.
- Funciones de movimiento y
visualización.
Isiconic, determina si una ventana está minimizada.
- Funciones para las
propiedades.
Informa y modifica el estado de las propiedades.
Getprop, devuelve una lista de propiedades de una ventana.
- Funciones pen.
Son las funciones correspondientes al lápiz.
- Funciones de paleta de colores.
- Funciones de dibujo y pintura.
- Grupo de funciones
OLE.
Funciones que se basan en el manejo de objetos.
Olenumobjects, enumera los objetos en un documento.
- Funciones
Toolhelp.
Normalmente devuelven información sobre los objetos que hay en memoria.
-
Funciones Drag & Drop
Funciones de arratrar y soltar.
Tiene información sobre la posición de arrastre de algún elemento, si se puede
arrastrar, etc.
- Funciones de
controladores instalables.
Hacen una gestión de los controladores instalables.
- Funciones
de decodificación LEMPEL-ZIV.
Hacen una gestión de los ficheros comprimidos.
- Funciones para
la impresión.
Devuelve tamaños de letra, página, etc. y activa o desactiva algunas funciones,
configura colores, etc.
a la hora de imprimir.
- Funciones SHELL (entorno).
Son las funciones que controlan el entorno.
FindExecutable: recupera el nombre del ejecutable asociado a un fichero
especificado.
- Funciones "Stress"
Controla espacio libre y manejadores de ficheros (handles).
AllocDiskSpace: crea un fichero del espacio consumido en una partición del disco
(instalar software).
- Funciones TrueType
Funciones que controlan los fuentes o tipos de letra a utilizar.
GetRasterizarCaps: recupera el estado del tipo de letra en un sistema. Cuando se
hace un cambio de
tipo de letra , reestablece el que hay por defecto.
- Funciones de versión.
Función que controla la versión de los ficheros.
GetfileVersionInfo: devuelve información sobre un fichero especificado.
- Funciones GDI.
Controla todo lo que se refiere a los gráficos, ya sea tipos de letra, manejo de
trabajo a la hora de una
impresión, prepara la impresora para aceptar datos, etc.
StartPage: Prepara un controlador de impresora para aceptar datos.
StarDoc: Inicializará un trabajo de impresión.
GetRasterizerCaps: recupera el estado del tipo de letra de un sistema.
- Funciones
KERNEL.
Lleva a cabo una E/S a ficheros, control de errores,etc.
hread: Lee datos de un fichero.
hwrite: escribe datos en un fichero.
Debugoutput: envía mensajes a un terminal erróneo.
- Funciones de usuario.
Son funciones en las que el usuario realiza alguna acción, como activar o
desactivar flechas de scroll-
bar (texto horizontal-vetical), recupera información de mensajes de hardware,
etc.
GetDriverInfo: recupera datos de un dispositivo instalable.
CopyIcon: copia un icono.
OpenDriver: abre un dispositivo instalable.
Una de las primeras funciones que vamos a comentar es bastante utilizada.
En muchas ocasiones hemos
querido saber qué resolución tiene la pantalla de la pc en el momento que se
ejecuta nuestro software. Con ésta información podemos dar un aspecto bastante
más profesional a nuestra aplicación si ajustamos el tamaño de nuestros
formularios a la resolución de la pantalla. También a través de
la misma API
sabemos la cantidad de puntos que nos da la impresora, con lo que podemos
ajustar nuestros informes independientemente de la impresora seleccionada. Esta
función la tenemos dentro de la librería GDI,
y se denomina GetDeviceCaps.
Dependiendo del valor del índice introducido, así nos da la información sobre la
cantidad de puntos horizontales de la pantalla, cantidad de puntos verticales de
la pantalla, puntos por pulgada horizontalmente en la impresora y puntos por
pulgada verticalmente en la impresora.
Declare Function GetDeviceCaps Lib
"GDI" ( ByVal HDC As Integer, Byval nIndex As Integer) As Integer
Global
Const HorRes = 8 ' resolución horizontal en pixels
Global Const VerRes = 10
' resolución vertical en pixels
Global Const PPPX = 88 ' pixels por pulgada
en X
Global Const PPPY = 90 ' pixels por pulgada en Y
Private Sub Command1_click()
p1 = GetDeviceCaps ( HDC, HorRes )
p2 = GetDeviceCaps ( HDC, VerRes )
i1 = GetDeviceCaps (
Printer, HDC, PPPX )
i2 = GetDeviceCaps ( Printer, HDC,
PPPY )
Label1.Caption = "Pantalla: " & p1 & " x"
& p2
Label2.Caption = "Impresora: " & i1 & "
x " & i2
End Sub
En muchas ocasiones necesitamos conocer
dónde esta el directorio de Windows y dónde reside el
directorio System del
mismo. Es muy lógico suponer que todas las instalaciones están en el directorio
C:Windows.
Puede ser que se ejecute desde una red, o que el usuario haya cambiado el directorio por omisión. En cualquiera de estos casos no podemos referirnos directamente a estos directorios, sino que debemos conocerlos dinámicamente cuando ejecutamos la aplicación.
Para ello utilizamos dos APIs
de la librería Kernel, la primera nos devuelve el directorio de Windows
(GetWindowsDirectory ), mientras que la segunda el directorio de System (
GetSystemDirectory ).
Para hacer funcionar esta API debemos inicializar la variable que nos devuelve la información, con 255 caracteres rellenos con el valor ASCII 0. Si la cadena estuviese vacía, no funcionaría, y su comportamiento sería impredecible.
Declare Function GetWindowsDirectory
Lib "Kernel " (ByVal lpBuffer As String, ByVal nSize As Integer
Declare
Function GetSystemDirectory Lib "Kernel" (ByVal lpBuffer As String, ByVal nSize
As Integer
Private Sub Command2_Click ()
Dim Camino As String
Camino =
String( 255, 0 )
w = GetWindowsDirectory ( Camino,
Len(camino))
Label3.Caption = Camino
w = GetSystemDirectory ( Camino, Len(Camino))
Label4.Caption = Camino
End Sub
Por último queria comentar una
utilidad realizada con llamadas a APIs. Consiste en el efecto de poder rotar
un texto, algo que dentro de algunos lenguajes no se puede hacer, como es en
el entorno Visual Basic, a no ser
que sea por medio de una imagen. Esto no
se realiza con una simple llamada, sino que es necesaria una estructura de
programación más compleja.
En primer lugar debemos definir dos estructuras. La primera nos va a permitir introducir una posición del texto, y la segunda es una definición completa de una fuente por el usuario.
Type RECT
LEFT
As Integer
TOP As Integer
RIGHT As
Integer
BOTTOM As Integer
End Type
Global Const F_TAMNOMBRE = 32
Type FUENTE
FANCHO As Integer
FLARGO As Integer
FESCAPE As Integer
FORIENTACION As
Integer
FWEIGHT As Integer
FITALICA As String * 1
FUNDERLINE As String * 1
FSTRIKEOUT As String * 1
FCHARSET
As String * 1
FOUTPRECISION As String * 1
FCLIPRECISION As String * 1
FQUALITY As String * 1
FPITCHANDFAMILY As String * 1
FNOMBRE As String * F_TAMNOMBRE
End Type
Global Const TRANSPARENTE = 1
Global Const OPACO = 2
Como se ha comentado antes, se
utilizan varias APIs para realizar este efecto. Todo ellas son de la
librería GDI, excepto una de USER.
Declare Sub GETCLIENTRECT Lib "USER"
(ByVal HWND As INTEGER, LPRECT As RECT)
Declare Function SETBKMODE Lib "GDI"
(ByVal HDC As Integer, ByVal NBKMODE As Integer) As Integer
Declare Function
CREATEFONTINDIRECT Lib "GDI" (LPLOGFONT As FUENTE) As Integer
Declare
Function SELECTOBJECT Lib "GDI" (ByVal HDC As Integer, ByVal HOBJECT As Integer
Declare Function TEXTOUT Lib "GDI" (ByVal X As Integer, ByVal Y As Integer,
ByVal LPSTRING As String ByVal NCOUNT As Integer) As Integer
Declare Function DELETEOBJECT Lib "GDI"
El mecanismo utilizado para
visualizar un texto inclinado consiste en crear una fuente ya inclinada y
visualizar el texto con esa fuente y el fondo transparente para no ocultar
otros elementos de la pantalla. En el ejemplo que sigue se puede ver que se va
realizando el giro a través de una barra de desplazamiento.
Private Sub HScroll_Change ( )
Dim POS As RECT
Dim LF As FUENTE
Dim I As Integer, ANGULO As Integer
Dim HFONT As Integer, HOLDFONT As
Integer
Dim TEXTO As String
' INICIALIZA EL TEXTO A VISUALIZAR
TEXTO = " TEXTO A ROTAR "
' ESPECIFICA LA FUENTE A
USAR
LF.NOMBRE = "Arial"
LF.FWEIGHT = 1000
' USA FONDO TRANSPARENTE
I =
SETBKMODE (HDC, TRANSPARENTE )
' CENTRA EL TEXTO EN LA VENTANA
Call GETCLIENTRECT ( HWND, POS )
Cls
ANGULO = HScroll.Value
LF.FESCAPE = ANGULO
HFONT = CREATEFONTINDIRECT ( LF )
HOLDFONT = SELECTOBJECT ( HDC, HFONT )
I = TEXTOUT ( HDC, POS.RIGHT / 2, POS.BOTTOM / 2, TEXTO.
Len ( TEXTO ))
I = SELECTOBJECT ( HDC, HOLDFONT )
I =DELETEOBJECT ( HFONT )
' RESTAURA EL FONDO POR
DEFECTO
I = SETBKMODE ( HDC, OPACO )
End Sub
Como podemos comprobar, no
siempre se puede realizar las operaciones que deseamos con una sola API.
En
la mayoría de los casos es necesario utilizar varias, que se complementan para
obtener los resultados deseados.
Algunas Funciones Interesantes y una breve descripcion dde cada una:
GetUserName (Devuelve
en nombre del usuario)
GetComputerName (Devuelve en nombre del
computador)
GetDiskFreeSpace (Devuelve información sobre el
disco duro)
GetDiskFreeSpaceEx (Devuelve la capacidad de un
disco mayor de 2Mb.)
GetVolumeInformation (Nombre del Disco,
tipo de formato y numero de disco)
GetLogicalDriveStrings
(Devuelve las unidades disponibles en un ordenador)
GetLocalTime (Devuelve la fecha y hora del ordenador)
GetCursorPos (Devuelve la posición del cursor en la pantalla)
GetDriveType (Devuelve el tipo de Unidad)
SetWindowPos (Formulario Siempre Visible)
GlobalMemoryStatus (Información sobre la memoria fisica
disponible)
ShellExecute (Ejecutar)
GetVersionEx (Devuelve la versión del Windows)
SystemParametersInfo (Cambia el fondo de pantalla del Windows)
SHFileOperation (Enviar un archivo a la papelera de reciclaje)
GetWindowsDirectory (Mustra la ruta del Windows)
GetSystemDirectory (Mustra la ruta del directorio System de
Windows)
sndPlaySound (Ejecutar sonidos .WAV)
FindExecutable (Busca el archivo ejecutable asociado a un
archivo, y muestra el icono)
GetKeyboardStateByString -
SetKeyboardStateByString (Seleccionar y Deseleccionar el Bloque Numerico
del teclado)
FindWindow (Indica si una aplicación determinada
esta en ejecución)
SystemParametersInfo (Activa/Desactiva las
teclas de Escape - CTRL+ALT+SUB - ALT+TAB - CRTL+ESC)
GetSysColor (Devuelve los colores del Windows)
GetACP (Determina la página de código ANSI vigente)
SetWindowPos (Esconder y mostrar la barra de tareas del
Windows)
ExitWindowsEx (Apaga o Reinicia el Windows 95/98)
GetSystemInfo (Información sobre el Hardware)
SystemParametersInfo (Devuelve y establece parámetros del
sistema de Windows)