Um software em que estou trabalhando recentemente, alguns dos quais precisam ser concluídos chamando outro software, mas esse software possui apenas arquivos executáveis e nenhum código -fonte. Iniciado depois que meu programa é iniciado.
Falando nisso, acredito que você tem algumas idéias preliminares para esta função.
1) Ligue para CreateProcess () para abrir o programa de destino.
2) Use findWindow () para encontrar a alça da janela do programa de destino.
3) Encontre o identificador da caixa de texto e o MessageId do botão, defina o texto usando o método sendMessage () e acione o evento.
OK, isso é realmente muito simples, mas quando eu o implementei, descobri que o resultado disso era: quando meu programa começou e abriu o programa de destino, sua janela de respingo e a janela principal serão exibidas, mesmo que quando eu usar o FindWindow () Para encontrar a alça da janela principal e chamar SendMessage (WindowHandle, SW_HIDE) para ocultar a janela, a janela principal será exibida por um momento.
Então, como resolver esse problema? , não tem efeito. . . . Continue pesquisando o documento. e, se for atribuído a ele após um nome de desktop, o processo será iniciado na área de trabalho especificada.
1) Primeiro, crie uma área de trabalho virtual.
const
Desktopname = 'mydesk';
Fdesktop: = CreateSktop (desktopname, nil, nil, 0, genérico_all, nil);
Vários desktops podem ser criados no Windows, e SwitchDesktop () pode ser usado para alternar qual desktop é exibido. O próprio Windows é implementado pela função de desktop virtual. Material:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/enumdesktops.asp
2) Ao CreateProcess, especifique o programa para executar na minha área de trabalho recém -gerada:
var
StartInfo: tStartupinfo;
Preenchchar (startinfo, sizeof (startinfo), 0);
Startinfo.cb: = sizeof (startinfo);
Startinfo.lpdesktop: = pchar (desktopname);
Startinfo.wsshowWindow: = sw_hide;
Startinfo.dwflags: = startf_useshowwindow;
Startinfo.hstderror: = 0;
Startinfo.hstdinput: = 0;
Startinfo.hstdOutput: = 0;
Se não for CreateProcess (PCHO (nome do arquivo), nil, nil, nil, nil, true, create_new_console+high_priority_class, nil, pchar (extractfilepath (filepath)), startinfo, fproceinfo) então começam
MessageBox (Application.Handle, 'Erro quando Init Voice (5).', PChar (Application.Title), MB_ICONWARNING);
saída;
fim;
3) Use FindWindow para encontrar a janela principal do programa
No começo, escrevi o código como este:
Para i: = 0 a 60, comece // aguarde 30 segundos para abrir a janela principal
WindowHandle: = findWindow (nil, 'windowcaption');
Se WindowHandle <> 0, então comece
quebrar;
fim;
Sono (500);
fim;
No entanto, a prática provou que dessa maneira, a janela que não está na área de trabalho atual não pode ser encontrada.
A resposta é que você pode usar a função setThreadDesktop (), que pode definir a área de trabalho onde o thread funciona, então adicionei outra frase antes do código acima:
se não for setThreadDesktop (fdesktop), então comece
saída;
fim;
No entanto, após a execução do programa, a função retorna falsa, indicando que a chamada do método falhou.
A função SetThreadDeskTop falhará se o encadeamento de chamada tiver alguma janela ou gancho na área de trabalho atual (a menos que o parâmetro HDESKTOP seja um identificador na área de trabalho atual).
Ah, acontece que não há uma coisa da interface do usuário no thread que precisa alternar o desktop, mas eu chamei esse método no thread principal do programa e, é claro, ele falhará. Precisa usar um não é bom ligar o thread "limpo" à nova área de trabalho e, em seguida, use o método findWindow () para encontrar o WindowHandle que estou procurando? O código é o seguinte:
Tfindwindowthread = classe (tThread)
Privado
FDESKTOP: THANDLE;
Fwindowhandle: THANDLE;
protegido
procedimento execute (); substituição;
público
Construtor CREATE (acretesuspended: boolean; const adesktop: thandle); reintroduz;
Propriedade WindowHandle: THANDLE LEIA FWindowHandle;
fim;
{Tfindwindowthread}
procedimento tfindwindowthread.execute ();
var
I: Inteiro;
Começar
// Faça o thread atual encontrar a janela na nova área de trabalho!
se não for setThreadDesktop (fdesktop), então comece
saída;
fim;
Para i: = 0 a 60, comece // aguarde 30 segundos para abrir a janela principal
FwindowHandle: = findWindow (nil, pchar ('windowcaption'));
Se fwindowhandle <> 0, então comece
quebrar;
fim;
Sono (500);
fim;
fim;
construtor tfindwindowthread.create (acretespended: boolean; const adesktop: thandle);
Começar
Criar herdado (acreesuspender);
Fdesktop: = adesktop;
fim;
E o código no programa principal se torna assim:
FindWindowThread: = tfindwindowthread.create (false, fdesktop);
tentar
FindWindowThread.waitfor;
FmainWindowHandle: = findWindowThread.WindowHandle;
Finalmente
FindWindowThread.Free;
fim;
Se fmainWindowHandle = 0, então comece
MessageBox (Application.Handle, 'Erro quando Init Voice (6).', PChar (Application.Title), MB_ICONWARNING);
saída;
fim;
Haha, é bem -sucedido, para que você possa encontrar a janela bem.
4) Finalmente, use esta alça da janela principal para encontrar a alça EditBox dentro, como segue:
FeditWindow: = findWindowex (fmainwindowhandle, 0, pchar ('edit'), nil);
Eu especifiquei o nome da classe desta caixa de texto aqui, e esse nome pode ser obtido com o SPY ++.
O trabalho de inicialização termina aqui. Portanto, a chamada de função é a mesma de sempre:
if (fmainwindowhandle = 0) ou (feditwindow = 0) então comece
saída;
fim;
SendMessage (feditwindow, wm_settext, 0, longnt (@atext [1]));
SendMessage (fmainwindowhandle, wm_command, US $ 8012, $ 0);
O número $ 8012 também é o ID do recurso obtido usando o SPY ++.
Por fim, não se esqueça de fechar o programa e lançar o desktop virtual:
Se fproceinfo.hprocess <> 0, então comece
TermineProcess (fProceInfo.hProcess, 0);
fim;
Se fdesktop <> 0, então comece
Fechesktop (FDESKTOP);
fim;
OK, isso implementa quase perfeitamente a função de um programa de chamadas em segundo plano, que será completamente transparente para o cliente final, e o cliente simplesmente não sente que há outro programa trabalhando em segundo plano. Não é muito bom? Podemos usar diretamente os programas de muitas outras pessoas (é claro, temos que seguir os direitos autorais).
Se você tiver alguma sugestão de melhoria ou troca, poderá enviar para: Tonyki [at] Citiz.net