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.
Limitaciones
-
No soportan nombres de ficheros largos, sólo el conocido formato 8.3 de DOS.
-
No tiene API de comunicaciones.
-
No soportan las capacidades Plug & Play.
Invocación a las funciones del API de Windows
se debe conocer bien el entorno de programación (Windows Appilcation Interface) Windows API.
Una de la caracteristica primaria de API de Windows son funciones y mensajes internos/externos de Windows.
Al utilizar esta serie de librerias podemos manipular todas las características de Windows, Mensajes, funciones propias del sistema.
Es imposible conocer todas las APIs de Windows ya que muchas de ellas son de uso exclusivo del sistema y no estan disponibles para los programadores
La mayoría de funciones de la API se agrupan en librerías que adoptan forma de ficheros; generalmente con terminación .DLL (Dynamic Linked Library)
HWND (IDENTIFICADOR DE VENTANAS).
El hwnd es un numero, ahora ¿que función cumple ese numero?, imaginemos que tenemos 3 aplicaciones abiertas Word, Excel, y PowerPoint, y la tenemos abierta al mismo tiempo, cuando damos clic a una de ellas en la pantalla, Windows sabe a que programa se da clic gracias al HWND, cada ventana (ojo ventana no programa, ya explicare esto con mas detalle), posee un numero único al momento de ejecutarse, este numero único entra en un registro de ventanas abiertas en el momento de ejecutarlo, cuando se le da clic a una ventana o cualquier otro mensaje él (Windows) sabe para quien va el mensaje ya que el tiene un registro de las ventanas abiertas, y mediante un algoritmo ejecuta la función encargada de controlar el mensaje.
HDC (DISPOSITIVO DE CONTEXTO).
Imaginen un pintor, el pintor para pintar ¿que necesita?, bueno de manera básica seria un pincel, un cabestrillo, colores y un lienzo; el cabestrillo es mi aplicación y ella se identifica con el HWND, y el lienzo es mi HDC, es decir, el hdc es el lugar donde se pinta tan simple como eso, toda ventana (me refiero a TODO!). posee un hdc, el hdc es donde nosotros ponemos nuestra creatividad, este hdc también es un numero único, que no se duplica, y solo lo usamos cuando dibujamos. Cuando veamos las API’S graficas entenderán un poco mas esto.
MENSAJERIA WINDOWS
Es fácil ver, que Windows es un lenguaje orientado a objetos, ahora una de las cosas mas difíciles para los programadores cuando están aprendiendo todo esto de programación orientada a objetos es como hacerlos funcionales, es decir, como enviar un mensaje de un objeto a otro; ya dije que todo era una ventana, y desde un punto de vista todo es un objeto, ahora esos objetos hablan entre si, inclusive para no complicarnos, el movimiento del ratón genera un mensaje que el usuario le transmite a Windows, si ustedes se movieran desde el píxel 0 hasta el píxel 800 (ancho), increíblemente Windows esta recibiendo 800 mensajes del usuario ya que para cada movimiento en píxel se genera dicho mensaje, ahora que hace Windows, bueno el recibe el mensaje verifica en su lista de ventanas activas “hwnd”, y verifica cual hwnd se encuentra en la posición del mouse, y el hwnd seleccionado será el ganador de dicho mensaje, si el objeto o ventana tiene un código para procesar dicho mensaje este se ejecuta en caso contrario este se omite, es decir, el papel de Windows es como el de una compañía de correo, agarra el mensaje del EMISOR y se lo envía al RECEPTOR. Es increíble pero cuando veamos mas profundo esto se van a impresionar de cómo lo creadores de Windows a mi manera de ver hicieron un excelente y practico trabajo con este tema de mensajes, TODO absolutamente TODO gira en los mensajes.
¿Como nos comunicamos?
Un mensaje de Windows tiene básicamente esta estructura.
Mensaje “Componente que recibe el mensaje”, “Tipo de mensaje”, mensaje1, mensaje_opcional
Esta es una estructura básica o simple de un mensaje de Windows, mas adelante veremos la función API encargada de ello. Pero se preguntaran que significan esos 4 componentes imaginen que Windows hablara, y cuando entran a Windows el los saluda, haría lo siguiente:
Mensaje “TU”, “SALUDOS”, “Buenos Días”, NULL.
Que significa esto: que el receptor eres “tu”, Windows te va saludar “SALUDOS”, y te dirá “Buenos Días”, el mensaje opcional es NULL (Nada). Ahora esto no es un mensaje real de Windows es un ejemplo, pero veamos los componentes:
Mensaje = Windows usa la función API SendMessage y PostMessage para ese trabajo.
Componente que recibe el mensaje = seria el hwnd del receptor, es decir, quien va recibir el mensaje.
Tipo de mensaje = muy importante este parámetro, aquí se le pasa un numero, que quiero decir, Windows tiene una lista de mensajes que los identifica por un numero. Ejemplo.
1 = Movimiento del mouse
2 = Clic del mouse
3 = Tecla presionada
etc.
Mi primer código
En el source code pegamos esto, de lo contrario dejamos que el asistente nos cree toda la interfaz.
#include
LONG proc;
HWND hWnd;
LRESULT CALLBACK GestorMensajes(HANDLE hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam)
{
switch (mensaje) {
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,mensaje,wParam,lParam);
}
}
BOOL IniciaAplicacion(HANDLE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = GestorMensajes;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, "boope.ico");//
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "APP";
return(RegisterClass(&wc));
}
BOOL IniciaInstancia(HANDLE hInstance, int nCmdShow)
{
hWnd = CreateWindow(
"APP",
"Aplicación sencilla",
WS_OVERLAPPEDWINDOW,
10,
10,
300,
80,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG Mensaje;
if (!hPrevInstance){
if (!IniciaAplicacion(hInstance))
return (FALSE);
}
if (!IniciaInstancia(hInstance,nCmdShow))
return (FALSE);
while (GetMessage(&Mensaje,NULL,NULL,NULL)){
TranslateMessage(&Mensaje);
DispatchMessage(&Mensaje);
}
return (Mensaje.wParam);
}
Empezamos con:
#include "windows.h"
Esta instrucción abre el archivo el cual contiene todas las referencias a las funciones API o bueno no todas pero las mayoría, aquí se encuentran las funciones API básicas y la mayoría de los mensajes.
Después toca explicar esto:
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
mSG Mensaje;
if (!IniciaAplicacion(hInstance))
return (FALSE);
if (!IniciaInstancia(hInstance,nCmdShow))
return (FALSE);
while (GetMessage(&Mensaje,NULL,NULL,NULL)){
TranslateMessage(&Mensaje);
DispatchMessage(&Mensaje);
}
return (Mensaje.wParam);
}
Para los conocedores de C, C++ o Java, saben que existe una función de arranque que se llama main, la cual es la primera función que arranca cuando se inicia el programa, bueno en Windows su equivalente es WinMain. Esta función le pasa a la aplicación 4 cosas, la primera hInstance es un numero que Windows le da a tu aplicación, ese numero lo usamos mas adelante, la segunda hPrevInstance, nos dice si hay otra instancia abierta de nuestra aplicación, esto es por si ejecutamos la misma aplicación 2 veces, o 3, etc. LpCmdLine son los parámetros que le pasamos a nuestra aplicación cuando arranca, se recuerdan de DOS cuando hacíamos esto:
Programa .exe /c /d /e, bueno este parámetro contienes las letras c,d,e.
Y por ultimo tenemos nCmdShow que es el como se va abrir nuestra aplicación si maximizada, minimizada o normal. Parecido al parámetro “Windows State” de VB.
Lo primero que hacemos es iniciar la aplicación.
if (!IniciaAplicacion(hInstance))
return (FALSE);
Funcion:
BOOL IniciaAplicacion(HANDLE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = GestorMensajes;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "APP";
return(RegisterClass(&wc));
}
aquí creamos un objeto WNDCLASS este objeto se utiliza para configurar la apariencia de nuestra ventana futura que todavía no ha sido creada.
wc.style = CS_HREDRAW | CS_VREDRAW ; aquí lo que estamos configurando es que cuando la ventana se redimensione tanto vertical como horizontal, se repinte de nuevo.
wc.lpfnWndProc = GestorMensajes; aquí estamos configurando nuestro “oido”, es decir, colocamos el nombre de la función encargada de recibir todos los mensajes que se le envíen a nuestra ventana.
wc.cbClsExtra = 0;
wc.cbWndExtra = 0; Parámetros no importantes.
wc.hInstance = hInstance; Aquí colocamos el numero que nos dio Windows. Cuando se inicia la aplicación. OJO! Este no es todavía el HWND.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); Aquí colocamos el icono que queremos, por defecto elegimos uno del sistema.
wc.hCursor = LoadCursor(NULL, IDC_ARROW); Aquí colocamos el tipo de puntero que queremos para nuestra aplicación.
wc.hbrBackground = GetStockObject(WHITE_BRUSH); Asignamos el color de fondo.
wc.lpszMenuName = NULL; Indicamos si tiene menú o no, en caso de haber menú se le coloca el nombre del recurso.
wc.lpszClassName = "APP"; Indicamos el nombre de la clase, esto de la clase lo veremos mejor cuando veamos una API relacionada con ella.
return(RegisterClass(&wc)); Ya con los parámetros configurados le pedimos a Windows con esta función API RegisterClass, que registre nuestra configuración y si es valida retorna un TRUE y si es FALSE pues implica que nos equivocamos en los parámetros o cometimos algún error.
Después sigue la siguiente línea.
if (!IniciaInstancia(hInstance,nCmdShow))
return (FALSE);
Con nuestra instancia ya registrada, procedemos a crear físicamente nuestra ventana.
BOOL IniciaInstancia(HANDLE hInstance, int nCmdShow)
{
hWnd = CreateWindow(
"APP",
"Aplicación sencilla",
WS_OVERLAPPEDWINDOW,
10,
10,
300,
80,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
Aquí es donde realmente creamos ya nuestra ventana físicamente, para ello usamos la API CreateWindow. Bueno creo que el nombre de la función API representa de manera obvia lo que hace.
hWnd = CreateWindow(
"APP", Nombre de la clase que usamos en el objeto WC de arriba
"Aplicación sencilla", Nombre del Caption o de la ventana
WS_OVERLAPPEDWINDOW, Estilo de la ventana
10, Posición X de la ventana
10, Posición Y de la ventana
300, Ancho
80, Alto
NULL,
NULL,
hInstance, Instancia a la cual corresponde.
NULL);
Y esta función es la que nos regresa nuestro HWND correspondiente. Luego si el HWND es valido. Procedemos a Mostrar la ventana
ShowWindow(hWnd, nCmdShow);
Noten que ya a partir de este momento usamos nuestro HWND, y le indicamos como se mostrara nuestra ventana.
Y luego le decimos que se pinte con:
UpdateWindow(hWnd);
Y listo ya tenemos nuestra primera ventana hecha a “mano”.
Quienes hayan visto sistema operativo en la universidad aquí esta el bucle de mensajes , el cual se encarga de escuchar los mensajes que recibe la ventana, toda ventana internamente tiene esto o algo parecido, lo que sucede es que en los otros lenguajes no se ve.
while (GetMessage(&Mensaje,NULL,NULL,NULL)){
TranslateMessage(&Mensaje);
DispatchMessage(&Mensaje);
}
LRESULT CALLBACK GestorMensajes(HANDLE hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam)
{
switch (mensaje) {
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,mensaje,wParam,lParam);
}
}
Esta ultima función es la encargada de escuchar, ella es nuestro oido, ella recibirá TODOS LOS MENSAJES que se generen en la ventana y luego quedara en nosotros la misión de codificar cada mensaje si fuera necesario. Se recuerdan de la estructura:
Componente que recibe el mensaje, Tipo de mensaje, mensaje1, mensaje_opcional
Esta estructura se convierte en esto:
HANDLE hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam
Ahora algunos de ustedes después de esto, pueden que no hayan entendido, y yo les digo ¡No importa!, ya que esto no lo vamos a usar, solo se los mostré como cultura general para que vean lo que hay detrás de esos formularios ya creados por diferentes lenguajes, y vean que todo el formulario se crea con funciones API. Lo que quiero que vean es que TODO gira alrededor de las API de Windows, no puedes hacer una aplicación para Windows sin usarlas. En este momento ustedes dicen: ¡ESO ES MENTIRA!, yo hice una aplicación en VB y no use API, OK! Tienes razón pero internamente ese botón que usaste, ese listbox y el propio formulario internamente están usando las API de Windows para su funcionamiento. Lo que sucede es que programar a este nivel es demasiado complicado!, inclusive si tu me preguntaras que porcentaje del 1 al 100% consideras tus conocimientos en API, yo te diría en un 5 al 7%, ya que esto es extremadamente grande!!!.
Lo que hacen los programadores y las empresas es crear controles y librerías que esconden la parte fea del asunto, poniéndolo todo bonito para que sea fácil para el programador manipularlas y así diseñar los software de manera rápida y efectiva.
¿CÓMO USAR API’S WIN32 EN VB?.
Para usar las API Win32 en VB hay que hacer ciertas cositas, si vas a declarar las API’S en un modulo tiene que ser de esta manera:
Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Primero se coloca Declare Function, luego el nombre de la función API, después lib y entre comillas se coloca el archivo .dll que contiene la función, y luego dependiendo del tipo de función se le coloca sus respectivos parámetros. Cada función API se encuentra en la ayuda de Microsoft en
www.msdn.microsoft.com o en la ayuda MSDN del visual studio.
En caso de usar la API en un formulario se le coloca la palabra PRIVATE antes de DECLARE.
NUESTRA PRIMERA FUNCIÓN API SENDMESSAGE
En esta sección vamos a ver nuestra primera API, que es el SendMessage, como todos sabemos la acción que usa un OBJETO para comunicarse con otro OBJETO es el MENSAJE, ese mensaje lleva una información que se procesará en el OBJETO receptor.
El API se compone de esta manera:
SendMessage (hwnd,wMsg,wParam, lParam)
Estudiemos su estructura:
hwnd = es ese número que le asigna WINDOW a ese objeto o ventana receptora.
wMsg = es el Mensaje.
wParam = es la información que se le envía al hwnd.
lParam = es otra información que también se le envía al hwnd.
En Windows los tipos de mensajes vienen definidos por CONSTANTES. Existen miles de constantes y tipos de mensaje que se pueden enviar a un objeto o hwnd. Ahora hay ciertos mensaje que están definidos para cierto tipo de ventana. Por ejemplo hay mensajes solo para TEXTBOX, otras solo para LISTBOX, etc.
Veamos nuestro primer programa en Visual Basic. Para este ejemplo es necesario tener un botón en un formulario. A continuación copien el siguiente código:
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const WM_SETTEXT = &HC
Private Sub Command1_Click()
Dim Resultado As Long
Resultado = SendMessage(Command1.hwnd, WM_SETTEXT, 0, ByVal "GRACIAS")
End Sub
Private Sub Form_Load()
Command1.Caption = "PRESIONAME"
End Sub
ANALISIS
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Van a notar en los parámetros que se le pasan a la función, que tienen la palabra ByVal, esto significa que los parámetros se pasan por valor y no por referencia. He de suponer que ustedes a este nivel tienen claro esos términos.
El “lParam as Any” el Any es que acepta cualquier objeto en este caso una cadena “GRACIAS”.
Con este código verán que cuando le dan click al botón, cambia y dice “GRACIAS”, ahora que sucedió:
Resultado = SendMessage(Command1.hwnd, WM_SETTEXT, 0, ByVal "GRACIAS")
RESULTADO = Todos los mensaje o en su mayoría retornan VALORES, siempre todas las funciones API regresan un número de tipo LONG. En este caso no interesa el valor a retornar pero más adelante veremos que sí.
HWND = COMMAND1.hwnd
Este es nuestro objeto receptor, es decir el objeto a quién le estamos enviando el mensaje.
MENSAJE = WM_SETTEXT
Mensaje que declaramos como constante en el área de “DECLARACIONES”, normalmente estos son valores hexadecimales.
Wparam = 0
En esta caso aquí no va el mensaje.
LParam = “ ByVal “GRACIAS”
El ByVal es muy importante ya que obliga a que se pase el valor por copia y no por referencia. Y este es el mensaje que le pasamos.
MAS SOBRE MENSAJES. Si ustedes cambian el Command1.hwnd y colocan Me.hwnd y lo corren cuando aprieten el botón van a ver el GRACIAS, no en el botón sino en el CAPTION del formulario, esto es por que el mensaje WM_SETTEXT sirve para cualquier hwnd. Ahora como saber que mensaje sirve para tal objeto.
Bueno aquí te muestro una lista de algunos de ellos:
BM_ Button mensaje
CB_ Combo Box Mensaje
CDM_ Common Dialog Mensaje
DRV_ Driver Mensaje
EM_ Edit control o TextBox Mensaje
LB_ List Box Mensaje
WM_ General Window Mensaje
Etc.
Cuando ustedes vean un mensaje o constante que empiece por BM_ significa que es un mensaje para un botón si lo usan en un Combo Box no funcionará. Es por esa razón que WM_SETTTEXT funcionó tanto para el botón como para el formulario.
Tanto para los mensajes como para la funciones tienen que tomar en cuenta un detalle, vean que el mensaje es WM_SETTEXT el SET se usa cuando asignamos y el GET para tomar un valor, es decir, cuando vean una función:
SETXNOMBRE = significa que vamos asignar algo.
GETXNOMBRE = significa que vamos a obtener algo.
En este caso el WM_ = mensaje que identifica que es un hwnd o ventana, SET = asignamos, TEXT = texto.
En este caso el TEXTO de la VENTANA botón es lo que llamamos en VB la propiedad CAPTION, al igual con el formulario.
Ahora vamos a probar algo interesante pero con GET
Declara este mensaje
Const WM_GETTEXT = &HD
Luego en el evento click del botón cambiamos el código que esta por el siguiente:
Private Sub Command1_Click()
Dim Resultado As Long
Resultado = SendMessage(Command1.hwnd, WM_GETTEXT, 0, 0)
End Sub
Arranca y presiona el botón verás que no cambia nada, ni se ve nada, tu dirás bueno el Texto del hwnd debe de estar en la variable “Resultado”, bueno vamos a probar pon debajo de:
Resultado = SendMessage(Command1.hwnd, WM_GETTEXT, 0, 0)
Msgbox Resultado
Cuando lo corras verás que te muestra 0, las funciones API de WINDOW retornan nada mas resultados de tipo LONG, no retornan ni STRING, ni FLOAT, etc. Ustedes dirán ¿bueno y como hacemos?. Cuando un API retorna una información ya sea de texto o una estructura (ya veremos eso mas adelante) se usan de esta manera:
Cambia el código en el evento Click del botón por este:
Private Sub Command1_Click()
Dim Resultado As Long
Dim Texto As String
Texto = Space$(20)
Resultado = SendMessage(Command1.hwnd, WM_GETTEXT, 15, ByVal Texto)
MsgBox Texto
End Sub
Dim Texto as String
Verás que declaramos una variable de tipo String
Texto = Space$(20)
Le asignamos 20 espacios en blancos a la variable, cuando quieres llenar una variable de tipo STRING sea cual sea la función API, tienes que asignarle el espacio en memoria, eso lo hacemos asignándole 20 espacios en blanco, pero el número puede variar.
SendMessage(Command1.hwnd, WM_GETTEXT, 15, ByVal Texto)
En esta función lo que cambia es el mensaje y los parámetros, el mensaje cambia a GETTTEXT es decir, “tomar el texto”, wParam = 15 esto significa que le dices a WINDOW que te regrese 15 caracteres nada más, si la cadena a regresar es mayor a 15 te le regresa incompleta. lParam = ByVal Texto; “Texto” es la variable donde se almacenará el Texto que Windows regrese. Si tu declaras por ejemplo:
Texto = Space$(2)
Cuando Windows intente llenar la variable no lo va llenar con el texto completo y te puede aparecer caracteres extraños. Esto es por que cuando quiere grabar el Texto del hwnd en la memoria se encuentra con una variable que fue inicializada con dos caracteres.
Normalmente se declaran las variables con 255, ejemplo, Texto = Space$(255), luego si quieres eliminar los espacios en blancos usamos la función TRIM de VB para ello.
El SendMessage es una de las API mas usadas en la programación bajo WINDOW, bueno es obvio que nosotros nunca vamos hacer lo que hicimos arriba para asignarles un Texto a una hwnd (Verán que uso la palabra hwnd y no ventana esto es por que no quiero que se confundan de que ventana es el Formulario, necesito que se acostumbre a que un hwnd sea cual fuera, es una ventana). Esto es por que los controles de VB resumen ese paso en sus propiedades, es decir, cuando cambias el texto a un hwnd (botón) lo que haces es usar su propiedad CAPTION. Obviamente ya ustedes se imaginarán lo que hace CAPTION en su interior.
La finalidad de explicar todo lo que dije arriba, fue para que vean como se maneja un API, ya que las API’S en su manejo son similares dependiendo de su tipo. A partir de ahora vamos a empezar a ver API’S un poco más complejas, ya que entenderlas implica entender a WINDOW y eso es un poco complicado. VB es un lenguaje muy sencillo y tal vez necesiten de las API’S para problemas extremos, pero les aseguro que si quieren aprender lenguajes como VC++ necesitarán del mas mínimo conocimiento de API’S para entenderlo.
SENDMESSAGE Y POSTMESSAGE PostMessage es exactamente igual a SendMessage, la diferencia radica en que cuando mandan mensaje con SendMessage el código que esta inferior a él no se ejecuta hasta que termine, por ejemplo:
Private Sub Command1_Click()
Dim Resultado As Long
Dim Texto As String
Texto = Space$(20)
Resultado = SendMessage(Command1.hwnd, WM_GETTEXT, 15, ByVal Texto)
MsgBox Texto ‘ Esta línea no se ejecuta hasta que el SendMessage se ejecute por completo
End Sub
Si usamos PostMessage:
Private Sub Command1_Click()
Dim Resultado As Long
Dim Texto As String
Texto = Space$(20)
Resultado = PostMessage(Command1.hwnd, WM_GETTEXT, 15, ByVal Texto)
MsgBox Texto ‘ Esta línea se ejecuta sin necesidad de que PostMessage haya finalizado.
End Sub
El uso de PostMessage no es muy usual, inclusive todavía no he visto un ejemplo práctico con esta función. Pero ya saben que existe.
NOTA: Ustedes se preguntaran, ¿COMO SABER CUANDO USAR WPARAM Y LPARAM? o ¿COMO SE QUE VALOR LES PASO?, para ello no existe ninguna regla, cuando ustedes quieran usar un mensaje con SendMessage ustedes tienen que buscar en la ayuda de MSDN que parámetros se le envían a ese mensaje.
WINDOWS MESSAGE En esta sección vamos a ver algunos mensajes útiles para las ventanas o hwnd usando el SendMessage, es importante mencionar, que no voy a explicar todos los mensajes para cada control, sino los que yo considero más importantes, recuerden que esta manual no esta orientado, para ser un diccionario de API sino explicar como funcionan mediante ejemplos.
EDIT CONTROL O TEXTBOX
- Mensaje : EM_GETLINE
Valor : Const EM_GETLINE = &HC4
Mensaje que funciona en un Textbox Multiline, este permite tomar el Texto que se encuentra en una línea específica.
Dim Respuesta As Long
Dim Texto As String
Texto = Space$(10)
Respuesta = SendMessage(Text1.hwnd, EM_GETLINE, 1, ByVal Texto)
MsgBox Texto
Lo único que hay que explicar es el valor que toma wParam que es 1, este es el número de línea de la cual queremos ver el texto. Si ponemos 0 seria la primera línea, 1 la segunda línea, así sucesivamente.
- Mensaje: EM_GETLINECOUNT
Valor: Const EM_GETLINECOUNT = &HBA
Mensaje que sirve para retornar la cantidad de líneas que posee un Textbox configurado de manera multiline.
Dim Respuesta As Long
Respuesta = SendMessage(Text1.hwnd, EM_GETLINECOUNT, 0, 0)
MsgBox Respuesta
Si vemos aquí, si nos interesa el valor de retorno del Mensaje, verán que no se le pasa ningún parámetro o información, con el tipo de Mensaje basta para que él sepa a que nos referimos. El número de líneas se almacena en la variable Respuesta.
- Mensaje: EM_GETMODIFY
Valor: Const EM_GETMODIFY = &HB8
Esta mensaje sirve para saber si un TEXTBOX, multiline o simple, se ha modificado.
Dim Respuesta As Long
Respuesta = SendMessage(Text1.hwnd, EM_GETMODIFY, 0, 0)
MsgBox Respuesta
Los valores que retornan es 0 si no se ha modificado y 1 si fue modificado.
- Mensaje : EM_LINELENGTH
Valor: Const EM_LINELENGTH = &HC1
Este mensaje sirve para tomar la longitud de una línea de un TEXTBOX sea multiline o no.
Dim Respuesta As Long
Respuesta = SendMessage(Text1.hwnd, EM_LINELENGTH, 1, 0)
MsgBox Respuesta
Aquí el mensaje retorna la longitud sería como el LEN de VB. wParam es el número de la línea de la cual queremos tomar su longitud. Esto si el Textbox es Multiline, en caso de no serlo no importa el número que pongas en wParam, siempre te retornará la longitud de la única línea que tiene.
- Mensaje : EM_SETSEL
Valor: Const EM_SETSEL = &HB1
Esta mensaje sirve para seleccionar una porción de la cadena que esta contenida en el TEXTBOX.
SendMessage Text1.hwnd, EM_SETSEL, 5, 1
MsgBox Text1.SelText
Aquí wParam recibe la posición donde se inicia la selección, el texto seleccionado se encontrara en la Propiedad .SelText del Textbox.
Noten que esta función la invocamos diferente. Cuando el valor que retorna una función no interesa, podemos usar la función como que si llamáramos a un método, Por ejemplo:
Respuesta = SendMessage(Text1.hwnd, EM_LINELENGTH, 1, 0)
En este caso nos interesa el resultado de la función por que la variable “Respuesta” toma el valor de la longitud de la cadena.
Respuesta = SendMessage(Text1.hwnd, EM_SETSEL, 5, 1)
Aquí “respuesta” no nos sirve para nada, por consiguiente, cuando el valor de la función sea cual sea el API no nos interese, podemos usarla de esta manera:
SendMessage Text1.hwnd, EM_SETSEL, 5, 1
Siendo completamente válido esta instrucción. Pero tienen que tomar en cuenta que algunas veces lo que retorna una función no lo usamos con un propósito, pero algunas veces el resultado que devuelve una función puede estar diciendo si la operación se ejecuto o no se ejecuto con éxito. Les repito eso dependerá del mensaje que ustedes utilicen.
COMBO BOX CONTROL
- Mensaje: CB_DIR
Valor : Const CB_DIR = &H145
Este mensaje, el cual lo veo muy importante permite llenar un COMBO BOX con información del sistema. En este caso a wParam le pasaremos unos parámetros ya predefinidos por WINDOW.
Parámetros que se pasan por Wparam:
Const DDL_ARCHIVE = &H20
Const DDL_DIRECTORY = &H10
Const DDL_DRIVES = &H4000
Const DDL_EXCLUSIVE = &H8000
Const DDL_HIDDEN = &H2
Const DDL_READONLY = &H1
Const DDL_READWRITE = &H0
Const DDL_SYSTEM = &H4
Ejemplo:
Dim path As String
path = App.path
SendMessage Combo1.hwnd, CB_DIR, DDL_DRIVES, ByVal path
Se darán cuenta que al ejecutarlo, todas las letras y unidades de la computadora se almacenan en el combo, verán que en wParam toma el parámetro que declaramos como constante DDL_DRIVES, los parámetros también pueden ser constantes ya establecidas o que poseen un valor. En lParam verán que es la ruta de nuestro programa, que es lo que exige el mensaje como segundo parámetro. Para saber que se les pasa a los otros parámetros que van en wParam, les recomiendo que busquen la ayuda en Línea de MSDN, ya que la ayuda normal, no muestra que parámetros son.
- Mensaje : CB_FINDSTRING
Valor: Const CB_FINDSTRING = &H14C
Este mensaje muy importante en el momento de hacer búsqueda en un COMBO ya que permite localizar cierto registro en el COMBO. En este mensaje wParam es el índice en donde empezamos a buscar y lParam es la cadena que buscamos.
Dim Texto As String
Dim Respuesta As Long
Texto = "Prueba"
Respuesta = SendMessage(Combo1.hwnd, CB_FINDSTRING, -1, ByVal Texto)
MsgBox Respuesta
Podremos ver que wParam le coloque el valor de –1, eso es para que busque en toda la lista del combo, si pongo por ejemplo 2 en wParam, empezará a buscar desde el registro 3, recuerden que el combo empieza en el índice 0.
Si la función encuentra la cadena regresa el índice en donde se encuentra en el combo, en caso de que no exista regresa –1. En esta función la búsqueda no es exacta, es decir:
“PRUEBA” Imagínense que tienen esta cadena en el Combo, si ustedes asignan la variable “Texto” de esta manera:
Texto = “Pru”
Cuando realice la búsqueda para el tipo de mensaje “PRUEBA” es igual a “PRU”, esto es por que la cadena en el combo empieza por “PRU”. Para hacer una búsqueda exacta vean el mensaje a continuación.
- Mensaje : CB_FINDSTRINGEXACT
Valor : Const CB_FINDSTRINGEXACT = &H158
Esta mensaje es igual al anterior con la diferencia que busca la cadena exacta en la lista del combo.
Dim Texto As String
Dim Respuesta As Long
Texto = "Prueba"
Respuesta = SendMessage(Combo1.hwnd, CB_FINDSTRINGEXACT, -1, ByVal Texto)
MsgBox Respuesta
Si seguimos el ejemplo de “PRU”, para este mensaje “PRU” no es igual a “PRUEBA”, ya que esta función busca la cadena que sea EXACTAMENTE igual.
Estas dos funciones son muy importantes en el momento de realizar búsquedas en COMBO que contengan mucha información, es común de los programadores en VB hacer:
For i = 0 to Combo1.listcount –1
Código para buscar
Next
Usando el SendMessage les aseguro que van a tener resultados increíblemente rápidos.
- Mensaje : CB_SHOWDROPDOWN
Valor : Const CB_SHOWDROPDOWN = &H14F
Esta función se utiliza para mostrar la lista desplegable del combo box.
SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, True, 0
En este caso el valor de wParam toma el valor TRUE para mostrar la lista y FALSE para esconderla.