Enviar mensajes y acceder a una ventana de otra aplicación.

 

 

Por: Demian Panello.

 

Enviar mensajes:

 

Escribir una aplicación en VC++, (en principio usando MFC), radica básicamente en crear los manejadores de mensajes, (o eventos), que necesitemos, como por ejemplo: WM_LBUTTONDOWN para un botón, WM_DRAW para dibujar un diálogo, y cualquier otro mensaje que reciba la aplicación.

Pero además de esto también puede uno enviar algún mensaje, lo que significa que se fuerza la ejecución del código escrito en ese mensaje a pesar de que el mismo no ha sido recibido por alguna acción del usuario. Por ejemplo, se puede enviar el mensaje WM_LBUTTONDOWN de un diálogo desde un botón.

Esto se hace a través de la función SendMessage(), que es una función miembro de CWnd.

Supongamos que tenemos un diálogo cuya clase es CEnviarmensajesDlg, y que en el mensaje WM_LBUTTONDOWN del mismo hay lo siguiente:

 

void CEnviarmensajesDlg::OnLButtonDown(UINT nFlags, CPoint point)
{

    AfxMessageBox("Mensaje WM_LBUTTONDOWN");   
    CDialog::OnLButtonDown(nFlags, point);
}

 

Obviamente al pulsar con el mouse en el diálogo se mostrará el mensaje pasado por parámetro a la función AfxMessageBox().

Si además tenemos un botón y queremos que al pulsarlo se ejecute el mensaje WM_LBUTTONDOWN del diálogo deberemos enviar este mensaje a Windows, (que es lo que en realidad ocurre si pulsamos con el mouse sobre el diálogo), deberíamos escribir:

 

void CEnviarmensajesDlg::OnClickdiag()
{
    //Envió el mensaje WM_LBUTTONDOWN
    //también podríamos haber escrito: this->SendMessage (WM_LBUTTONDOWN);   

    SendMessage(WM_LBUTTONDOWN);
    AfxMessageBox("Se envió el mensaje WM_LBUTTONDOWN al pulsar el botón");
}

 

Simplemente se llama a la función SendMessage del diálogo, ya que el mensaje a enviar pertenece al él, y listo.

Una última cosa: a SendMessage() se le puede pasar dos parámetros más, wParam y lParam, que varían de acuerdo al mensaje. Para WM_LBUTTONDOWN wParam indica si se tiene pulsada alguna tecla y lParam el punto en el diálogo donde se pulsó el mouse.

 

Sugiero que experimenten bastante con esta función, (no puede pasar nada grave, salvo que se "cuelgue" la aplicación), y busquen información en los CD's de MSDN o en la red.

 

 

Acceder a una ventana de otra aplicación:

 

Una vez me preguntaba si se podría desde mi aplicación acceder a una ventana de otra aplicación que en ese momento esté en ejecución para, por ejemplo, cambiar el título de esa otra ventana. Mi pregunta tuvo respuesta luego de leer algunos artículos de MSDN y para mi sorpresa era mucho más fácil de lo que pensaba.

 

Hallé la función FindWindow de CWnd, la cual pide dos parámetros: el primero una cadena expresando el nombre de la clase de ventana a buscar y el segundo el título de la ventana, (se puede poner NULL en uno de ellos y especificar el otro o poner los dos). Y la función devuelve un puntero a CWnd que puede llegar a ser NULL si no se encuentra esa ventana en memoria.

 

Supongamos que en el diálogo del ejemplo anterior tenemos otro botón, y queremos que al pulsarlo, si hay una ventana del explorador de Windows en ejecución, se cambie el título de la misma y el icono, (hemos creado un icono con el ID: IDI_ICON1).

Entonces escribimos en el botón, (cuyo ID es IDC_CAMBIAR):

 

void CEnviarmensajesDlg::OnCambiar()
{
    HICON miIcono;                          //Handle para un icono
    miIcono=AfxGetApp()->LoadIcon (IDI_ICON1);     //cargo el icono

    //Obtengo un handle para una ventana del explorador que esté abierta
    CWnd* pExplo = CWnd::FindWindow("ExploreWClass", NULL);   (1)
   
    if (pExplo!=NULL)                  //si pudo encontrar alguna ventana del explorador de windows
    {
       //le cambio el título.
        pExplo->SetWindowText ("Icono y titulo cambiado desde una aplicación");
        //le cambio el icono
        pExplo->SetIcon(miIcono,TRUE);
       
    }
   else
        AfxMessageBox("No se encuentra ninguna ventana del Explorador de Windows");

}

 

Bueno, las primeras líneas simplemente declaran un manejador para el icono y se carga el icono. En (1) está la clave de todo, se hace una llamada a FindWindow() pasándole como parámetro el nombre de clase para el explorador de Windows sin importar el título.

Esta llamada devuelve un puntero a CWnd que si es distinto a NULL es porque se encontró la ventana y entonces tenemos la llave de la misma y podremos hacer cualquier cosa con ella.

Quizás se pregunte cómo "diablos" supe el nombre de clase del explorador de Windows, muy simple, usé el utilitario SPY++ que viene con Visual Studio.

Este programa muestra entre muchas otras cosas, toda la información de las ventanas que se encuentran en ejecución.

En el menú Find de Spy++, seleccione Find Window y luego tilde la opción Hide Spy. Esta es la ventana FIND WINDOW:

 

 

 

Si arrastra el icono que tiene el dibujo de una mira, (Finder Tool), hasta alguna ventana en ejecución verá el nombre de la clase en el cuadro de edición CLASS, (además de otra info interesante). De aquí obtuve el nombre de la clase.

A continuación listo las clases de ventana de algunas aplicaciones:

 

Class Name                  Application
SciCalc                           CALC.EXE

CalWndMain                  CALENDAR.EXE
Cardfile                          CARDFILE.EXE

Clipboard                       CLIPBOARD.EXE
Clock                             CLOCK.EXE

CtlPanelClass                 CONTROL.EXE
XLMain                         EXCEL.EXE

Session                          MS-DOS.EXE
Notepad                        NOTEPAD.EXE

pbParent                        PBRUSH.EXE
Pif                                  PIFEDIT.EXE

PrintManager                 PRINTMAN.EXE
Progman                        PROGMAN.EXE (Windows Program Manager)
Recorder                       RECORDER.EXE

Solitaire                         SOL.EXE
Terminal                        TERMINAL.EXE

WFS_Frame                 WINFILE.EXE
MW_WINHELP         WINHELP.EXE

#32770                         WINVER.EXE
OpusApp                      WINWORD.EXE

MSWRITE_MENU     WRITE.EXE
Windows 95 Only:

MSPaintApp                  PBRUSH.EXE
ExploreWClass              EXPLORER.EXE

WordPadClass             WORDPAD.EXE

 

(información extraída del articulo Knowledge Base Q88167).

 

Así quedaría la ventana del explorador de Windows luego de pulsar el botón de nuestra aplicación, (observe la barra de título):

 

 

 

Para finalizar, hago notar, a modo de relación entre los dos ejemplos de este artículo, que teniendo un puntero a CWnd de cualquier ventana, se podría enviar algún mensaje de la misma por medio de SendMessage().

 

 

Descargar fuente de los ejemplos: enviarmensajes.zip (28 Kb).

Volver a la página principal