 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Lun 12 Jul, 2004 6:32 pm Asunto: habilitar botón de un programa externo |
|
|
Hola, dado el handle de un botón de un programa externo quisiera saber como cambiar su propiedad enable. _________________ Adrián
http://adrian.org.ar |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Lun 12 Jul, 2004 7:05 pm Asunto: |
|
|
Hola, tienes las funciones del API:
EnableWindow para cambiar el estado.
IsWindowEnabled para averiguar el estado. |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Lun 12 Jul, 2004 7:54 pm Asunto: |
|
|
gracias Leo, pero lo que busco es cambiar la propiedad enabled del botón, no de la ventana. _________________ Adrián
http://adrian.org.ar |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Lun 12 Jul, 2004 8:26 pm Asunto: |
|
|
Para Windows todo son ventanas, incluidos los botones.
Un ejemplo con un botón de nuestro programa por no complicarnos mucho:
EnableWindow(Button1->Handle, false);
Pues mas o menos lo mismo una vez tenemos el Handle del botón externo. |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Mar 13 Jul, 2004 7:49 pm Asunto: |
|
|
Gracias nuevamente Leo, ahora mi problema es que no puedo obtener el handle del boton
1ro Obtengo el handle del control AfxControlBar42s.
Dentro de el accedo a un componente del tipo ToolbarWindow32.
Pero aparentemente este no es un contenedor de los botones.
¿Como puedo dado el handle del Toolbar habilitar el botón que me interesa? |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Mie 14 Jul, 2004 7:39 pm Asunto: |
|
|
Básicamente seria así:
| Código: | // Para el ejemplo lo probamos con una barra de botones de nuestro propio programa
HWND handle = ToolBar1->Handle;
int btIndex = 0;
TBBUTTON bt;
SendMessage(handle, TB_GETBUTTON, btIndex, (LPARAM)&bt);
SendMessage(handle, TB_ENABLEBUTTON, bt.idCommand, MAKELONG(true,0)); |
Esto funciona perfectamente para acceder a la barra de botones de nuestro propio programa, pero para acceder a la de otro proceso como estamos pasándole un puntero del espacio de direcciones de nuestro proceso la cosa se complica un poco. Necesitamos pasarle un puntero que pertenezca a su mismo espacio de direcciones.
Hay varias formas de hacer esto. Un libro que lo explica muy bien es "Programación avanzada en Windows" de Jeffrey Richter.
El ejemplo anterior quedaría así para WinNT/2000/XP/2003:
| Código: | // HWND handle = ...; <-- el handle de la barra (ToolbarWindow32)
// Indice del botón en la barra (puede coincidir con el nº de posición)
int btIndex = 0;
// Averiguamos el identificador del proceso al que pertenece la barra
DWORD pid;
GetWindowThreadProcessId(handle, &pid);
// Reservamos memoria en el espacio de direcciones
// del proceso al que pertenece la barra
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
int len = sizeof(TBBUTTON);
void* buffer = VirtualAllocEx(proc, 0, len, MEM_COMMIT, PAGE_READWRITE);
// Averiguamos el identificador de comando del botón
TBBUTTON bt;
SendMessage(handle, TB_GETBUTTON, btIndex, (LPARAM)buffer);
// Copiamos la memoria reservada en el proceso de la barra
// en la estructura TBBUTTON de nuestro proceso
ReadProcessMemory(proc, buffer, (void*)&bt, len, 0);
// Liberamos la memoria
VirtualFreeEx(proc, buffer, len, MEM_RELEASE);
CloseHandle(proc);
// Cambiamos el estado del botón
SendMessage(handle, TB_ENABLEBUTTON, bt.idCommand, MAKELONG(true,0)); |
y así para Win95/98/ME:
| Código: | // HWND handle = ...; <-- el handle de la barra (ToolbarWindow32)
// Indice del botón en la barra (puede coincidir con el nº de posición)
int btIndex = 0;
// Creamos un archivo mapeado en memoria, que en el caso de
// Win95/98/ME se comparte para todos los procesos
int len = sizeof(TBBUTTON);
HANDLE map = CreateFileMapping((HANDLE)0xffffffff, 0,
PAGE_READWRITE, 0, len, 0);
void* buffer = MapViewOfFile(map, FILE_MAP_WRITE, 0, 0, len);
// Averiguamos el identificador de comando del botón
TBBUTTON* bt = (TBBUTTON*)buffer;
SendMessage(handle, TB_GETBUTTON, btIndex, (LPARAM)buffer);
// Cambiamos el estado del botón
SendMessage(handle, TB_ENABLEBUTTON, bt->idCommand, MAKELONG(true,0));
// Cerramos el archivo mapeado en memoria
UnmapViewOfFile(buffer);
CloseHandle(map); |
Pero aún así nada es perfecto, ya que depende de como cada programa guarde el estado de los botones, con algunos funcionara perfectamente, pero con otros el botón recuperara el estado original al pasar por encima o al pulsarlo. |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Vie 16 Jul, 2004 7:29 pm Asunto: |
|
|
Leo, lo tuyo es excelentisimo, especialmente por el nivel de respuesta dado.
Pero lamentablemente no funcionó, si te sirve de algo, también he probado este código:
| Código: |
//1. handle de la ventana padre
HWND hMain = FindWindow(NULL, "NN");
//2. Handle del Control Bar
HWND hCB = FindWindowEx(hMain,0,"AfxControlBar42s","");
//3. Handle del Toolbar
HWND hTB = FindWindowEx(hCB, 0, "ToolbarWindow32", "");
//4. cantidad de botones
int iMaxBtn = SendMessage(hTB, TB_BUTTONCOUNT,0 ,0);
for (int i = 0;i < iMaxBtn; i++){
SendMessage(hTB, TB_ENABLEBUTTON,i , MAKELONG(true,0));
}
|
En este caso, la variable iMaxBtn me devuelve 9, lo cual es correcto, pero el mensaje, no causa efecto.
gracias por tu tiempo
atte _________________ Adrián
http://adrian.org.ar |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 16 Jul, 2004 8:03 pm Asunto: |
|
|
Las primeras líneas de código que puse solo eran como ejemplo de como hacerlo, pero ya digo que hacerlo así solo serviría para nuestro propio programa, o sea, desde dentro del mismo proceso al que pertenece la barra, cosa que no nos sirve en tu caso ya que intentas modificar la barra de otro proceso, por eso puse los dos ejemplos de abajo que son los que debes usar.
En el código que has puesto estas intentando habilitar el botón mandándole el indice y lo que debes enviarle realmente es el identificador de comando, que solo puedes obtenerlo leyendo antes con TB_GETBUTTON (enviándole a este si el indice). Y como para leer esta estructura necesitamos especificarle un puntero que pertenezca al espacio de direcciones del proceso donde esta la barra es por eso que usamos todo el lío de abajo.
Convertimos el código de arriba en una función para usarlo más fácil (este ejemplo solo es para WinNT/2K/XP/2K3, para Win95/98/ME mirar mas arriba):
| Código: | void HabilitarBoton(HWND handle, int indice, bool habilitar)
{
DWORD pid;
GetWindowThreadProcessId(handle, &pid);
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
int len = sizeof(TBBUTTON);
void* buffer = VirtualAllocEx(proc, 0, len, MEM_COMMIT, PAGE_READWRITE);
TBBUTTON bt;
SendMessage(handle, TB_GETBUTTON, indice, (LPARAM)buffer);
ReadProcessMemory(proc, buffer, (void*)&bt, len, 0);
VirtualFreeEx(proc, buffer, len, MEM_RELEASE);
CloseHandle(proc);
SendMessage(handle, TB_ENABLEBUTTON, bt.idCommand, MAKELONG(habilitar,0));
}
//1. handle de la ventana padre
HWND hMain = FindWindow(NULL, "NN");
//2. Handle del Control Bar
HWND hCB = FindWindowEx(hMain,0,"AfxControlBar42s","");
//3. Handle del Toolbar
HWND hTB = FindWindowEx(hCB, 0, "ToolbarWindow32", "");
//4. cantidad de botones
int iMaxBtn = SendMessage(hTB, TB_BUTTONCOUNT, 0, 0);
// Los habilitamos todos
for (int i = 0; i < iMaxBtn; i++) {
HabilitarBoton(hTB, i, true); // <---
} |
Si aún con esto te da problemas y si el programa del que intentas modificar la barra de botones no es privado y me dices cual es, así como la versión de Windows y BCB que usas intentare ayudarte en lo que pueda.
Saludos. |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Vie 16 Jul, 2004 8:46 pm Asunto: |
|
|
| Muy agradecido por la respuesta. El código funciona perfecto. Ahora me debo enfrentar a otros problemas. |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Jue 22 Jul, 2004 9:35 pm Asunto: |
|
|
Leo, una consulta, necesito tambien presionar ese botón, lo he intentado agregando un par de líneas a la función de habilitación, pero no funcionó
| Código: |
SendMessage(handle, TB_PRESSBUTTON, bt.idCommand, MAKELONG(TRUE,0));
SendMessage(handle, TB_PRESSBUTTON, bt.idCommand, MAKELONG(FALSE,0));
|
Otra curiosidad es que el botón se deshabilita solo luego de habilitarse.
¿alguna idea?
gracias por anticipado,
atte _________________ Adrián
http://adrian.org.ar |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 23 Jul, 2004 12:04 am Asunto: |
|
|
Es más sencillo y efectivo una vez tenemos el identificador de comando del botón en cuestión enviarlo directamente a la ventana donde esta la barra:
| Código: | PostMessage(GetParent(handle), WM_COMMAND, bt.idCommand, (LPARAM)handle);
|
|
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Vie 23 Jul, 2004 12:24 am Asunto: |
|
|
| gracias Leo, mañana lo pruebo |
|
| Volver arriba |
|
 |
ikis Master


Registrado: 28 Dic 2002Mensajes: 703Ubicación: Madrid, España
|
Publicado: Vie 23 Jul, 2004 6:45 pm Asunto: |
|
|
| Gracias Leo, funciona perfecto. |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|