Pregunta

Estoy tratando de usar el siguiente código para presionar un botón en mi otra aplicación:

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
   ButtonHandle = FindWindowEx(wnd, 0, "SaveButton", "&Save");
   SendMessage(wnd, WM_COMMAND, MAKEWORD(GetDlgCtrlID(ButtonHandle), BN_CLICKED ), (LPARAM)ButtonHandle);

}

No funciona. Intenté pasar diferentes identificadores a MAKEWORD y cambiar WPARM y LPARAM pero nada.

¿Alguna idea sobre cómo hacer clic en un botón en la ventana de otra aplicación?

El código es apreciado. Gracias.

EDITAR: La razón por la que no parece funcionar permisos. Envié un PostMessage () y el resultado fue un error con GetLastError () = 5 (o Acceso denegado). ¿Alguna idea?

EDIT2 No pretendo ser grosero, pero por favor, por favor, ya busqué en todas las API, incluyendo obtener y configurar las regiones para el botón y luego enviar un botón hacia abajo y hacia arriba, obteniendo la ID de control, obteniendo la ID de clase y un trillón más. La razón por la que hice la pregunta aquí en primer lugar es porque ya agoté mi búsqueda en Internet. Si conoce la respuesta POR FAVOR PUBLICAR CÓDIGO , no sugiera una API y eso es todo, muéstreme cómo esa API resuelve el problema. No es dificil. gracias.

EDITAR 3: La respuesta de la pregunta se seleccionó automáticamente cuando terminó la recompensa. La pregunta sigue sin respuesta.

¿Fue útil?

Solución

  1. ¿Está seguro de que " SaveButton " el nombre de la clase es valido? ¿Consigues el botón manejar?
  2. Intente enviar mensajes a la ventana ButtonHandle (directamente al botón).

Actualización: creo que esto debería funcionar,

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

Otros consejos

SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);

Tiene que enviar un clic de botón dos veces. No estoy seguro de por qué (tal vez el primer clic solo activa la ventana del botón), pero estoy usando este código durante mucho tiempo y siempre funcionó para mí.

Vea la siguiente solución, también puede usar

SendMessage(ButtonHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(ButtonHandle, WM_LBUTTONUP, 0, 0);

O

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

HWND buttonHandle = 0;

BOOL CALLBACK GetButtonHandle(HWND handle, LPARAM)
{
 char label[100];
 int size = GetWindowTextA(handle,label,sizeof(label));
 if(strcmp(label,"&Save") == 0)
 {
  buttonHandle = handle;
  return false;
 }
 return true;
}
void main()
{
 HWND windowHandle = FindWindowA(NULL,"Do you want to Save?");
 if(windowHandle != 0)
 {
  BOOL ret = EnumChildWindows(windowHandle,GetButtonHandle,0);

  if(buttonHandle != 0)
  {
   LRESULT res = SendMessage(buttonHandle,BM_CLICK,0,0);
   //SendMessage(buttonHandle,WM_LBUTTONDOWN,0,0); 
   //SendMessage(buttonHandle,WM_LBUTTONUP,0,0);
  }

 }



}

Nota: Asegurándose del texto de la ventana, el texto del botón (verifique si hay espacio al final del título de la ventana)

Los errores de acceso denegado en SendMessage o PostMessage no tienen sentido a menos que el proceso que envía el mensaje se ejecute a un nivel de integridad más bajo que el proceso de destino.

Esto no debería suceder a menos que el proceso que posee la ventana de destino se esté ejecutando " asAdministrator " o es un servicio. Y es muy difícil para los servicios crear ventanas en el escritorio interactivo con Windows 6 y versiones posteriores.

Puede leer un poco sobre Niveles de integridad aquí si aplicar incluso remotamente a esta situación. Internet Explorer es casi la única otra aplicación que 'se incorpora' al modelo de seguridad de integridad al reducir deliberadamente el nivel de integridad de sí mismo con el fin de protegerse más efectivamente.

Si puede elevar la ventana que contiene el botón, puede enviar un evento de mouse sin procesar a una posición dentro de los límites del botón.

Hay dos funciones para simular el evento del mouse SendInput y mouse_event . Recomiendo usar la función WM_CUSTOM. Para abrir una ventana, puede utilizar ShowWindow . No sé cómo obtener el control de un botón, pero si tiene su hWnd, es fácil encontrar su posición absoluta usando Función GetWindowRect . Intente usar estos, si tiene algún problema, con gusto lo ayudaré.

O defina un WM personalizado dentro de la ventana de su aplicación para manejar la solicitud de guardado. WM_USER o <=> (no recuerdo cuál) marca el inicio de los mensajes de ventana definidos por el usuario.

Cuando tengo que hacer este tipo de cosas, uso SendKeys. Es VB-ish y C # proporciona una interfaz agradable para usar, pero para C / C ++ tendrá que hacerlo & Lt; de esta manera > ;. Lo que es bueno es que puedes escribir scripts y ejecutarlos en lugar de codificarlos en tu código.

Microsoft ahora está presionando Accesibilidad activa (MSAA) para la automatización de la interfaz de usuario, (Ha sido renombrado varias veces a lo largo de los años)  ver

Lo siento, no & # 8217; no tengo ningún código simple para comenzar. Como & # 8220; SendMessage () & # 8221; no parece estar funcionando para usted, no & # 8217; no conozco otra opción aparte de & # 8220; UI Automation & # 8221;

Supongo que ha verificado con Spy ++ (instalado con MsDev) que su mensaje se está enviando al botón correcto, etc. & # 8211; y que el botón es un botón estándar de Windows. Mi primer instante diría use & # 8220; SendMessage () & Quot; o " PostMessage () & # 8221; pero dados los números de respuestas sobre & # 8220; SendMessage () & # 8221; y el hecho de que no te funciona. Espero que alguien esté pasando & # 8230;

Puede usar sendkeys (como dijo tr3) para enviar clics del mouse, que es diferente de usar SendMessage. También es menos directo y más hack-ish, pero es útil para la automatización (en VBS).

Además, solo una suposición, pero el problema podría ser que su manejo de mensajes se rompe en alguna parte al no llamar al miembro de la clase base. Ejemplo:

void CMyClass::OnMessageY(CWnd *cwnd)
{
    CBaseClass::OnMessageY(cwnd);
    //... my code
}

si está seguro de que ButtonHandle es un identificador válido, puede usar el par WM_LBUTTONDOWN y el mensaje WM_LBUTTONUP en lugar de BN_CLICKED

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
    SendMessage(ButtonHandle, WM_LBUTTONDOWN, MK_LBUTTON, 0);
    SendMessage(ButtonHandle, WM_LBUTTONUP, MK_LBUTTON, 0);
}

Un enfoque que no es C: use Java y la clase java.awt.Robot para mover el mouse y realizar clics reales (supongo que también hay algo en el mundo de Windows para esto). Problema: debe saber dónde está su botón: D

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top