Un software en el que estoy trabajando recientemente, algunos de los cuales deben completarse llamando a otro software, pero ese software solo tiene archivos ejecutables y ningún código fuente. Comenzó después de que se inicie mi programa.
Hablando de esto, creo que tienes algunas ideas preliminares para esta función.
1) Llame a CreateProcess () para abrir el programa objetivo.
2) Use FindWindow () para encontrar el mango de la ventana del programa de destino.
3) Encuentre el mango del cuadro de texto y el MessageId del botón, configure el texto usando el método sendMessage () y active el evento.
Ok, esto es realmente muy simple, pero cuando lo implementé, descubrí que el resultado de esto fue: cuando mi programa comenzó y abrió el programa objetivo, su ventana de salpicaduras y la ventana principal se mostrarán, incluso si cuando uso FindWindow () Para encontrar el mango de la ventana principal y llamar a SendMessage (Windowshandle, SW_HIDE) Para ocultar la ventana, la ventana principal se mostrará por un momento.
Entonces, ¿cómo resolver este problema? , no tiene efecto. . . . Continuar buscando el documento. y si se le asigna después de un nombre de escritorio, el proceso se iniciará en el escritorio especificado.
1) Primero, cree un escritorio virtual.
estúpido
Escritorio de escritorio = 'mydesk';
Fdesktop: = createSktop (DesktoPName, nil, nil, 0, genic_all, nil);
Se pueden crear múltiples escritorios en Windows, y SwitchDeskTop () se puede usar para cambiar qué escritorio se muestra en los que también se usa programas. Windows en sí está implementado por la función de escritorio virtual. . material:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/enumdesktops.asp
2) Cuando CreateProcess, especifique que el programa se ejecute en mi escritorio recién generado:
varilla
StartInfo: TStartUpinfo;
Fillchar (startInfo, sizeof (startInfo), 0);
StartInfo.cb: = sizeof (startInfo);
StartInfo.lpDesktop: = Pchar (DesktoPName);
Startinfo.wshowwindow: = sw_hide;
Startinfo.dwflags: = startf_useshowwindow;
StartInfo.hstderror: = 0;
Startinfo.hstdinput: = 0;
StartInfo.hstdoutput: = 0;
Si no createProcess (pChar (nombre de archivo), nil, nil, nil, nil, true, create_new_console+high_priority_class, nil, pchar (extractFilePath (filepath)), startInfo, fproceinfo) luego comience
MessageBox (Aplicación
salida;
fin;
3) Use FindWindow para encontrar la ventana principal del programa
Al principio escribí el código así:
para i: = 0 a 60 comience // espera 30 segundos para abrir la ventana principal
WindowHandle: = findWindow (nil, 'WindowCaption');
Si WindowHandle <> 0 entonces comience
romper;
fin;
Dormir (500);
fin;
Sin embargo, la práctica ha demostrado que de esta manera, la ventana que no está en el escritorio actual no se puede encontrar.
La respuesta es que puede usar la función setThreadDeskTop (), que puede establecer el escritorio donde funciona el subproceso, por lo que agregué otra oración antes del código anterior:
Si no se setthreaddesktop (fdesktop), entonces comience
salida;
fin;
Sin embargo, después de que se ejecuta el programa, la función devuelve falso, lo que indica que la llamada de método falló.
La función setThreadDeskTop fallará si el hilo de llamadas tiene ventanas o ganchos en su escritorio actual (a menos que el parámetro HDesktop sea un mango en el escritorio actual).
Oh, resulta que no hay cosa de UI en el hilo que necesita cambiar de escritorio, pero llamé a este método en el hilo principal del programa y, por supuesto, será fácil saber esto, solo yo solo Necesito usar uno, ¿no está bien vincular el hilo "limpio" al nuevo escritorio, y luego usar el método FindWindow () para encontrar el WindowsHandle que estoy buscando? El código es el siguiente:
Tfindwindowthread = class (tthread)
Privado
Fdesktop: Thandle;
Fwindowhandle: Thandle;
protegido
procedimiento ejecutar (); anular;
público
constructor create (acreateSaSpended: boolean; const adesktop: thandle); reintroducir;
Propiedad WindowHandle: Thandle lee fwindowhandle;
fin;
{Tfindwindowthread}
procedimiento tfindwindowthread.execute ();
varilla
I: entero;
Comenzar
// ¡Haga que el hilo actual busque la ventana en el nuevo escritorio!
Si no se setthreaddesktop (fdesktop), entonces comience
salida;
fin;
para i: = 0 a 60 comience // espera 30 segundos para abrir la ventana principal
Fwindowhandle: = findwindow (nil, pchar ('WindowCaption'));
Si fwindowhandle <> 0 entonces comienza
romper;
fin;
Dormir (500);
fin;
fin;
constructor tfindwindowthread.create (acreateSuspended: boolean; const adesktop: thandle);
Comenzar
creación hereditaria (acreateSuspended);
Fdesktop: = adesktop;
fin;
Y el código en el programa principal se vuelve así:
Findwindowthread: = tfindwindowthread.create (false, fdesktop);
intentar
Findwindowthread.waitfor;
Fmainwindowhandle: = findwindowthread.windowhandle;
Finalmente
Findwindowthread.free;
fin;
Si fmainwindowhandle = 0 entonces comience
MessageBox (Aplicación
salida;
fin;
Jaja, es exitoso, por lo que puedes encontrar el mango de la ventana sin problemas.
4) Finalmente, use este mango de la ventana principal para encontrar el mango de edición en el interior, de la siguiente manera:
FeditWindow: = findwindowex (fmainwindowhandle, 0, pchar ('editar'), nil);
He especificado el nombre de clase de este cuadro de texto aquí, y este nombre se puede obtener con Spy ++.
El trabajo de inicialización termina aquí. Entonces, la llamada de función es la misma de siempre:
if (fmainwindowhandle = 0) o (feditwindow = 0) luego comience
salida;
fin;
SendMessage (FeditWindow, WM_SETTEXT, 0, Longint (@Adext [1]));
SendMessage (fmainwindowhandle, wm_command, $ 8012, $ 0);
El número de $ 8012 también es la ID de recurso obtenida mediante el uso de SPY ++.
Finalmente, no olvide cerrar el programa y lanzar el escritorio virtual:
Si fproceinfo.hprocess <> 0 entonces comience
Terminadoprocess (fproceinfo.hprocess, 0);
fin;
Si fdesktop <> 0 comienza
CloseDesktop (fdesktop);
fin;
Ok, esto implementa casi perfectamente la función de un programa de llamadas de fondo, que será completamente transparente para el cliente final, y el cliente simplemente no siente que haya otro programa que funcione en segundo plano. ¿No es muy bueno?
Si tiene alguna sugerencia de mejora o intercambio, puede enviar por correo a: Tonyki [At] Citiz.net