Programaticamente pressionar um botão no outro aplicativo (C, Windows)
Pergunta
Eu estou tentando usar o seguinte código ao pressionar um botão no meu outro aplicativo:
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);
}
Ele não funciona. Eu tentei passar diferentes alças para MAKEWORD e para alterar o WPARM e LPARAM, mas nada.
Algumas ideias sobre como clicar em um botão na janela de outro aplicativo?
Código é apreciado. Obrigado.
EDIT: A razão pela qual não parece permissões de trabalho. Enviei uma PostMessage () eo resultado foi um erro com GetLastError () = 5 (ou acesso negado). Alguma idéia?
EDIT2 Eu não quero ser rude, mas por favor, por favor, por favor, eu já procurou toda a API de incluindo obter e definir as regiões para o botão e, em seguida, enviar um botão para baixo e botão para cima, ficando a identificação do controle, ficando o ID de classe e uma mais zilhão. A razão pela qual eu fiz a pergunta aqui, em primeiro lugar é porque eu já esgotou a minha pesquisa na internet. Se você sabe a resposta Por favor, poste CÓDIGO , não sugerem uma API e é isso, mostre-me como é que isso resolve API do problema. Não é díficil. obrigado.
EDIT 3: A resposta da questão ter sido seleccionado automaticamente quando a recompensa terminou. A questão ainda permanece sem resposta.
Solução
- Você tem certeza que "SaveButton" nome da classe é válido? Você começa o botão alça?
- Tente enviar mensagens para a janela ButtonHandle (diretamente para o botão).
Update: Eu acredito que isso deve funcionar,
SendMessage(ButtonHandle, BM_CLICK, 0, 0);
Outras dicas
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
Você tem que enviar um clique de botão duas vezes. Não sei por que (talvez o primeiro clique só ativa a janela do botão), mas eu estou usando este código por um longo tempo e ele sempre trabalhou para mim.
talvez isso pode ajudar: http://www.cplusplus.com/forum/beginner/8806/
Veja a seguinte solução, você também pode usar
SendMessage(ButtonHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(ButtonHandle, WM_LBUTTONUP, 0, 0);
ou
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: Obtendo certeza do texto da janela, o texto do botão (verificar se há espaço no final do título da janela)
Erros de acesso negado no SendMessage ou PostMessage não fazem sentido, a menos que o processo de enviar a mensagem está sendo executado em um nível de integridade mais baixo do que o processo de destino.
Este não deve estar acontecendo a menos que o processo que possui a janela de destino está sendo executado "asAdministrator" ou é um serviço. E sua maldita duro para serviços para criar janelas na área de trabalho interativa com Windows 6 e para cima.
Você pode fazer algumas leituras sobre Níveis Integridade Aqui se aplicam-se mesmo remotamente a esta situação. Internet Explorer é sobre a única outra aplicação que 'opta em' para o modelo de segurança da integridade de redução propositadamente o nível de integridade de si mesmo, a fim de sandbox-se de forma mais eficaz.
Se você pode levantar a janela que contém o botão você pode enviar evento raw mouse para uma posição dentro dos limites do botão.
Existem duas funções para o evento simular rato SendInput e mouse_event
. Eu recomendo usar a função mouse_event
. Para elevar uma janela que você pode usar ShowWindow . Eu não sei como obter o identificador de um botão, mas se você tiver seu hWnd é fácil encontrar a sua posição absoluta usando função GetWindowRect . Tente usar estes, se você tiver quaisquer problemas eu vou ser feliz para ajudar.
Ou definir um WM personalizado dentro de sua aplicação janela para lidar com save pedido. WM_CUSTOM
ou WM_USER
(não consigo lembrar qual) marca o início de mensagens de janela definidos pelo usuário.
Quando eu tenho que fazer este tipo de coisas que eu uso SendKeys. É VB-ish e C # fornece uma interface agradável de usar, mas para C / C ++ você terá que fazê-lo << a href = "http://www.codeproject.com/KB/cpp/sendkeys_cpp_Article.aspx" rel = "noreferrer nofollow"> desta forma >. O que é bom com ele é que você pode escrever scripts e executá-los em vez de codificar-lo em seu código.
A Microsoft está empurrando agora Active Accessibility (MSAA) para UI Automation, (Ele foi renomeado várias vezes ao longo dos anos) veja
- UI Automation e Microsoft Active Accessibility
- Usando UI Automation para Automated Testing
- Clientes de Automação de IU para código gerenciado
Desculpe eu não tenho qualquer código simples para você começar. Como “SendMessage ()” não parece estar a trabalhar para você, eu não sei de outra opção além de “UI Automation”
Eu estou supondo que você tenha verificar com Spy ++ (instalado com MsDev) que você mensagem estão sendo envie o botão correto etc - e que o botão é um padrão de botões das janelas. Meu primeiro instante diria uso “SendMessage () 'ou' PostMessage ()” mas dado o número de respostas sobre ‘SendMessage ()’ e o fato de ele não está funcionando para você. Espero que alguém está acontecendo ...
Você pode usar sendkeys (como tr3 disse) para enviar cliques do mouse, que é diferente do que usar SendMessage. Também é menos direta e mais corte-ish, mas é útil para automação (em VBS).
Além disso, apenas um palpite, mas o problema pode ser que seu manuseio mensagem é quebrado em algum lugar não chamando o membro da classe base. Exemplo:
void CMyClass::OnMessageY(CWnd *cwnd)
{
CBaseClass::OnMessageY(cwnd);
//... my code
}
Se você certeza ButtonHandle são manipulador válido você pode usar par WM_LBUTTONDOWN e WM_LBUTTONUP mensagem em vez 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);
}
A abordagem não-C: Use Java ea classe java.awt.Robot para mover o mouse ao redor executar cliques reais (Eu acho que há algo no mundo Windows para isso, também). Problema: Você tem que saber onde o botão é: D