De igual forma, al enviar un mensaje a una ventana, salta a la vista que lo que se necesita es, el handler de la ventana destinataria, el ID del mensaje que se le enviará y el par de parámetros a ser procesados o interpretados.
El ID del mensaje es un número que va desde el 0x0000 al 0xFFFF, pero no todo el rango puede ser utilizado para los mensajes privados, de usuario, personalizados, etc., algunos de ellos están reservados para ser utilizados solamente por el sistema.
La teoría de los Mensajes de Windows es un poco más amplia, si te interesa saber más acerca de este tema y sobre los rangos disponibles para los ID de los mensajes sería conveniente que googles Windows Messages y consultes la ayuda en el MSDN de Microsoft. El objetivo es explicarte como puedes hacerlo en el environment de Builder C++.
Para definir mensajes personalizados para un control o formulario debemos derivar la clase del control o formulario e indicar entre las macros BEGIN_MESSAGE_MAP y END_MESSAGE_MAP por medio de la macro MESSAGE_HANDLER los mensajes que podrá procesar el control. Dentro de los parámetros que recibe la macro MESSAGE_HANDLER están el ID del mensaje y la función que se ejecutará o se encargará de "hacer ese algo" al recibir el mensaje. Tanto la definición de los nuevos mensajes como la declaración de las funciones que los procesarán deben escribirse en la sección private de la definición de la clase, sin olvidar que estás últimas deben precederse de la palabra clave de Builder C++ __fastcall.
Como ejemplo escribiremos las instrucciones para enviar un mensaje a un control Edit (TEdit) al presionar un botón, al recibir el mensaje el control Edit mostrará el texto "He recibido un mensaje de un botón.". Entonces comenzamos derivando la clase TEdit:
//---------------------------------------------------------------------------
//Derivamos la clase TEdit para manejar nuestros propios mensajes
class MiEdit : public TEdit
{
public:
MiEdit(TfrmMandaMensaje *);
protected:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_MSGEDIT1, TMessage, WMMsgEdit1);
END_MESSAGE_MAP(TEdit)
void __fastcall WMMsgEdit1(TMessage &Message);
};
//---------------------------------------------------------------------------
Al mismo tiempo estamos creando el control Edit en tiempo de ejecución por eso declaramos el constructor de MiEdit para recibir el apuntador del formulario y así enviarlo al constructor de la clase base TEdit. No debemos olvidar definir el ID del mensaje WM_MSGEDIT1, esto lo hacemos en la cabeza de nuestro *.h
#define WM_MSGEDIT1 (WM_APP + 1)
La constante WM_APP nos indica el inicio de los valores que podemos utilizar para los ID de nuestros mensajes personalizados (o de usuario o de aplicación). Bien, en nuestro archivo *.cpp definimos el constructor de nuestra clase hija MiEdit, así como las instrucciones de la función WMMsgEdit1 que procesará el mensaje.
//---------------------------------------------------------------------------
MiEdit::MiEdit(TfrmMandaMensaje *handler):TEdit(handler)
{
}
//---------------------------------------------------------------------------
void __fastcall MiEdit::WMMsgEdit1(TMessage &Message)
{
this->Text = "He recibido un mensaje de un botón.";
}
//---------------------------------------------------------------------------
La única función del constructor es la de enviar el apuntador del formulario TfrmMandaMensaje a la clase padre TEdit ya que en este formulario es donde colocaremos nuestro Edit. Ya sólo nos falta instanciar nuestra clase MiEdit, presentar el control en el formulario y postear o enviar el mensaje. En este ejemplo la instancia la hacemos dentro del formulario TfrmMandaMensaje declarando un apuntador a la clase MiEdit.
//---------------------------------------------------------------------------
class TfrmMandaMensaje : public TForm
{
__published: // IDE-managed Components
TButton *btnEnviaMensaje;
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall btnEnviaMensajeClick(TObject *Sender);
private: // User declarations
MiEdit *edtEdit;
public: // User declarations
__fastcall TfrmMandaMensaje(TComponent* Owner);
};
//---------------------------------------------------------------------------
La presentación del control edtEdit la hacemos dentro del constructor de nuestro formulario
//---------------------------------------------------------------------------
__fastcall TfrmMandaMensaje::TfrmMandaMensaje(TComponent* Owner)
: TForm(Owner)
{
unsigned offset = 20;
//Creamos el control tipo Edit
edtEdit = new MiEdit(this);
edtEdit->Parent = this;
//Cambiamos las propiedades del control tipo Edit
edtEdit->Left = btnEnviaMensaje->Left + btnEnviaMensaje->Width + offset;
edtEdit->Top = btnEnviaMensaje->Top;
edtEdit->Width = 3 * edtEdit->Width;
}
//---------------------------------------------------------------------------
y la liberación del control al cierre de nuestra aplicación.
//---------------------------------------------------------------------------
void __fastcall TfrmMandaMensaje::FormClose(TObject *Sender,
TCloseAction &Action)
{
//Liberamos la memoria ocupada por el control
if(edtEdit!=NULL)
{
delete edtEdit;
edtEdit = NULL;
}
}
//---------------------------------------------------------------------------
Finalmente en el evento click de nuestro botón btnEnviaMensaje posteamos el mensaje al control edtEdit usando la instrucción PostMessage la cual como parámetros requiere el handler del control, el ID del mensaje y dos parámetros: el primero WParam y el segundo LParam, ambos enteros.
//---------------------------------------------------------------------------
void __fastcall TfrmMandaMensaje::btnEnviaMensajeClick(TObject *Sender)
{
PostMessage(edtEdit->Handle, WM_MSGEDIT1, 25, 30);
}
//---------------------------------------------------------------------------
Listo, al presionar el botón el control edtEdit mostrará el mensaje "He recibido un mensaje de un botón.". Aunque este pudo haberse hecho fácilmente poniendo directamente el texto en la propiedad edtEdit->Text en lugar de postear el mensaje, el ejemplo sirve para ilustrar como puedes manejar tus propios mensajes en Builder. Lo mismo aplica para un formulario, en este caso al crear un formulario en tiempo de diseño ya estas derivando la clase TForm, así que sólo necesitas agregar las macros y la definición de unas cuantas funciones para definir tus propios mensajes y así comunicarte con tu aplicación desde otra aplicación si desde esa aplicación dispones de los handlers de tus formularios. Aunque aquí podrías encontrarte con problemas de memoria al tratar de compartirla entre aplicaciones si lo que envías como parámetros es el apuntador de un bloque de memoria de la aplicación remitente del mensaje.
Nota: Como comentario final deja explicarte lo sig., seguramente habrán notado que las funciones que procesan los mensajes reciben el parámetro por referencia Message y que este es del tipo TMessage, bueno esta clase es la estructura siguiente
struct TMessage{
Cardinal Msg;
union{
struct{
Word WParamLo;
Word WParamHi;
Word LParamLo;
Word LParamHi;
Word ResultLo;
Word ResultHi;
};
struct{
Word WParam;
Word LParam;
Word Result;
};
};
};Así que ya sabes donde caen los parámetros que envías con la función PostMessage y como acceder a ellos en las funciones con las que procesas tus mensajes; puedes acceder tanto al ID del mensaje que estas procesando como a las partes altas y bajas de los parámetros WParam y LParam que envías.En el siguiente tip, explicaré que son las listas ligadas y porque son muy útiles cuando desarrollas aplicaciones. Suerte y hasta la próxima.
