Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

habilitar botón de un programa externo

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: habilitar botón de un programa externo Responder citando

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
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Hola, tienes las funciones del API:
EnableWindow para cambiar el estado.
IsWindowEnabled para averiguar el estado.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Muy agradecido por la respuesta. El código funciona perfecto. Ahora me debo enfrentar a otros problemas.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

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
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

gracias Leo, mañana lo pruebo
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Gracias Leo, funciona perfecto.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor
Mostrar mensajes de anteriores:   
Cambiar a:  
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


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.