PDA

Ver la Versión Completa : Problemas con checkado en checkbox de otra aplicacion


aguml
30-09-2014, 12:47:03
hola amigos, estoy viendo como puedo hacer para, desde mi proceso, marcar un checkbox de otro proceso. 
Lo primero que hago es usar FindWindow para obtener el hwnd de la ventana. 
Luego uso EnumChildWindow para recorrer todos los elementos de la ventana. 
En el callback busco que la clase sea TCheckBox y si es asi retorno en LParam el hwnd del TCheckBox.
Luego uso la siguiente macro para activar/desactivar el checkbox: 
http://msdn.microsoft.com/en-us/library/windows/desktop/bb849167(v=vs.85).aspx 

Todo funciona correctamente ¿Donde está el problema? El problema es que, aunque aparezca checkado, si pongo una comprobacion en la "victima" tipo if(CheckBox1->Checked == true)... La comprobacion da como resultado que no está checkado y al pulsar sobre el se vuelve a marcar como si no lo estuviese antes. 
¿Alguna idea de como arreglarlo?


escafandra
30-09-2014, 19:24:42
En teoría no vas mal encaminado, debería funcionar, si no lo hace se debe a la gestión de la VCL. Puedes ir un paso más allá y simular un click del ratón (http://www.delphiaccess.com/forum/trucos-y-consejos-16/como-simular-un-click-de-raton/)

Saludos.

aguml
30-09-2014, 19:39:09
Como las dos aplicaciones son mias ¿que tal si cambio el wndproc del checkbox por uno mio y dentro gestiono el evento BM_SETCHECK?

escafandra
30-09-2014, 20:02:09
En ese caso usa un mensaje de usuario y lo gestionas como quieras.

Saludos.

aguml
30-09-2014, 20:42:05
escafandra no se ni que es eso de un mensaje de usuario pero supongo será un mensaje inventado por mi ¿no?
Ya lo he conseguido así pero mandando el mensaje original. ¿es mejor usar uno propio para no pisar la funcion original o algo asi?

Te pongo el link con los fuentes de los dos procesos que son clones pero solo cambia que uno busca a Proceso A y el otro a Proceso B, y en todas las partes que uno hace referencia a Proceso B, el otro hace referencia a Proceso A.
Link: Aqui (https://mega.co.nz/#!5k8GmIYb!3DS9VFxkNSUDV3pIFJfITv4Rmdqgv695tEGwl06aFPE)

Me gustaria que le echaras un vistazo y me comentaras que cambiarias. Es el proyecto que uso en el tema de procesos que charlan entre si pero para hacerlos sincronicos o asincronicos uso un checkbox que al marcarlo en un proceso tambien se marca en el otro y, dependiendo del estado de ese checkbox, se desactiva el boton de enviar mensaje al enviar y se activa al recibir para hacerlo sincronico o nunca se desactiva para hacerlo asincronico.

escafandra
01-10-2014, 00:39:30
Los mensajes de usuario comienzan a partir del WM_USER (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931%28v=vs.85%29.aspx), sirven para crear tus propios mensajes.

Cuando tenga un rato miro ese código. :)


Saludos.

ecfisa
01-10-2014, 01:37:07
Hola aguml.

Creo que lo complicas usando WndProc para capturar el mensaje, es mas simple:

Emisor:
codigo

...
void wmCopyData(char* WndClass, char* WndTitle, char* msg)
{
HANDLE hRecept;
COPYDATASTRUCT cds;

hRecept = FindWindow(WndClass, WndTitle);
if (hRecept != 0) {
cds.dwData = 0;
cds.cbData = strlen(msg)+1;
cds.lpData = (char*)msg;
SetForegroundWindow(hRecept);
SendMessage(hRecept, WM_COPYDATA, 0, (LPARAM)& cds);
} else
MessageBox(0,"Receptor no encontrado","", MB_ICONERROR);
}

// ej. envio
void __fastcall TfrmSender::Button1Click(TObject *Sender)
{
wmCopyData("TfrmReceiver", "Receiver", Edit1->Text.c_str());
}


Receptor:
header

...
class TfrmReceiver : public TForm
{
__published:

private:
void __fastcall OnWMCopyData(TWMCopyData& msg);

protected:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, OnWMCopyData)
END_MESSAGE_MAP(TForm)

public:
__fastcall TfrmReceiver(TComponent* Owner);
};
...

codigo

...
void __fastcall TfrmReceiver::OnWMCopyData(TWMCopyData& msg)
{
ShowMessage("Mensaje recibido: " + String((char*)msg.CopyDataStruct->lpData));
}
...


Saludos :)

aguml
01-10-2014, 10:20:43
Ok, cambiado.
Con respecto a lo que hago para gestionar lo del CheckBox ¿como lo ves? ¿como lo mejorarías? Es que acabo de aprender lo de cambiar el WndProc y lo aplico a todo jejeje :o

ecfisa
01-10-2014, 17:59:36
Hola aguml.

No estoy diciendo que esté mal usar WndProc, lo que sucede es que Builder ya tiene definido ese mensaje y te evitas la comprobación de si el mensaje fué otro.

A ver si este ejemplo te dá otra idea... En el form emisor pone un TButton y un TCheckBox y en el receptor tres TCheckBox (CheckBox1, CheckBox2 y CheckBox3) .

Emisor:

...
struct data_struct {
char className[255];
char caption[255];
int x, y;
TColor color;
bool state;
} ds;

void __fastcall TfrmSender::Button1Click(TObject *Sender)
{
HANDLE hRecept = FindWindow("TfrmReceiver", "Receiver");
if (hRecept != 0) {
COPYDATASTRUCT cds;
strcpy(ds.className, "TCheckBox");
strcpy(ds.caption,"CheckBox2");
ds.x = 50;
ds.y = 30;
ds.color = clYellow;
ds.state = CheckBox1->Checked;
cds.dwData = 0;
cds.cbData = sizeof(ds);
cds.lpData = &ds;
ShowWindow(hRecept, SW_SHOW);
SetForegroundWindow(hRecept);
SendMessage(hRecept, WM_COPYDATA, 0, (LPARAM)& cds);
} else
MessageBox(0,"Receptor no encontrado","", MB_ICONERROR);
}


Receptor:

header

class TfrmReceiver : public TForm
{
__published:
TCheckBox *CheckBox1;
TCheckBox *CheckBox2;
TCheckBox *CheckBox3;

private:
void __fastcall OnWMCopyData(TWMCopyData& msg);

protected:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, OnWMCopyData)
END_MESSAGE_MAP(TForm)

public:
__fastcall TfrmReceiver(TComponent* Owner);
};


code

struct data_struct {
char className[255];
char caption[255];
int x, y;
TColor color;
bool state;
} ds;

void __fastcall TfrmReceiver::OnWMCopyData(TWMCopyData& msg)
{
memcpy(&ds, msg.CopyDataStruct->lpData, sizeof(data_struct));

for(int i = 0; i < ComponentCount; i++) {
TCheckBox *cb = static_cast<TCheckBox*>(Components[i]);
if (cb->ClassNameIs(ds.className) && cb->Caption == ds.caption) {
cb->Left = ds.x;
cb->Top = ds.y;
cb->Color = ds.color;
cb->Checked = ds.state;
}
}
}


Saludos :)

aguml
01-10-2014, 19:08:36
Guauuu pues si que es potente este método.