PDA

Ver la Versión Completa : Recoger informacion de todas las ventanas de una aplicación


Joviali
17-06-2012, 21:05:51
Buenas,me gustaria saber como recorrer todas las ventas de una aplicación y guardarme el nombre de la ventana, caption y la case de esta.

He estado mirando y se como hacerlo de todo lo que esta en ejecucion en el sistema, pero me insteresa hacerlo de una aplicacion en concreta.

Gracias.

ecfisa
17-06-2012, 22:19:39
HolaJoviali y bienvenido a Club Delphi :)

Como a todos los que se inician te invitamos a que leas nuestra guía de estilo (http://www.clubdelphi.com/foros/guiaestilo.php).

Para obtener los valores de las propiedades Name y Caption de los forms creados en una aplicacion podes utilizar la variable Screen.

Un ejemplo:

...
var
i: Integer;
begin
with Screen do
for i:= 0 to FormCount-1 do
ListBox1.Items.Add(Forms[i].Name + ' ' + Forms[i].Caption)
end;

En cuanto a "la case" no se que significa.

Saludos.

ecfisa
17-06-2012, 22:30:44
Hola de nuevo.

Releyendo tu mensaje, creo que te referis al nombre de la clase (no me dí cuenta en la primera leida).

En ese caso cambiá en el código anterior esta linea:

ListBox1.Items.Add(Forms[i].Name + ' ' + Forms[i].Caption)


Por esta:

ListBox1.Items.Add(Format('Name: %s, Caption: %s, ClassName: %s',
[Forms[i].Name ,Forms[i].Caption, Forms[i].ClassName]))


Saludos. :)

Joviali
18-06-2012, 08:01:23
Buenas, esto funciona para la misma aplicacion en ejecución , lo que busco son esos mimos datos que me has comentado anteriormente pero de otra aplición . Yo he estado probando con las siguientes funciones:

FindWindow //Para encontrar la aplicacione en concreto.

GetWindowText(wnd, WinName, 144); // Obtiene el texto de la ventana actual
GetClassName(wnd, CName, 144); // Obtiene el nombre de la clase

siendo wnd el Handle de la aplicacion principal.

Pero esto no me funciona ya que no me recorre las ventanas hijas de la apliccion.



En definitiva lo que busco es que una aplicación "A" busque cuantas ventanas tiene la aplicación "B" abiertas. y me de la información de la clase de cada una de ellas:
b--->TF_principal.
b1--->Tf_aux1
b2--->tf_aux2.

Todo esto viene porque estoy haciendo un programa que actualiza otro y necesito saber que esta en la ventana principal de la aplicacion para poder cerrarla y actualizar la aplicación.


Gracias.

Casimiro Notevi
18-06-2012, 08:42:13
Recuerda poner los tags al código fuente, ejemplo:

http://neftali.clubdelphi.com/images/UtilizarTAGs.png

Gracias :)

escafandra
18-06-2012, 11:29:55
Quizás esto te de pistas:


procedure ListWinInfoFromPId(PId: DWORD; Strings: TStrings);
type
TWinParam = record
Handle: THandle;
PId: DWORD;
end;
PWinParam = ^TWinParam;
var
WinParam: TWinParam;
Buffer: array [1..255] of char;

function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
var
PId: DWORD;
begin
Result:= true;
PId:= 0;
GetWindowThreadProcessId(Handle, PId);
if PWinParam(lParam).PId = PId then
begin
PWinParam(lParam).Handle:= Handle;
Result:= false;
end;
end;

begin
WinParam.PId:= PId;
EnumWindows(@EnumWindowsProc, LPARAM(@WinParam));
Strings.Clear;
repeat
Strings.Add('hWnd: ' + IntToHex(WinParam.Handle, 8));
GetWindowText(WinParam.Handle, @Buffer, 255);
Strings.Add('Caption: ' + Buffer);
GetClassName(WinParam.Handle, @Buffer, 255);
Strings.Add('Clase: ' + Buffer);
Strings.Add('-----------------------------------------------');
WinParam.Handle:= Windows.GetParent(WinParam.Handle);
until WinParam.Handle = 0;
end;


Ejemplo de uso:

ListWinInfoFromPId(4800, Memo1.Lines);



Saludos.

escafandra
18-06-2012, 12:19:32
Y mejor de esta otra forma:


procedure ListWinInfoFromPId(PId: DWORD; Strings: TStrings);
type
TWinParam = record
PId: DWORD;
S: TStrings;
end;
PWinParam = ^TWinParam;
var
WinParam: TWinParam;

function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
var
PId: DWORD;
Buffer: array [1..255] of char;
begin
Result:= true;
PId:= 0;
GetWindowThreadProcessId(Handle, PId);
if PWinParam(lParam).PId = PId then
begin
PWinParam(lParam).S.Add('hWnd: ' + IntToHex(Handle, 8)+'h');
GetWindowText(Handle, @Buffer, 255);
PWinParam(lParam).S.Add('Caption: ' + Buffer);
GetClassName(Handle, @Buffer, 255);
PWinParam(lParam).S.Add('Clase: ' + Buffer);
PWinParam(lParam).S.Add('-----------------------------------------------');
Result:= true;
end;
end;

begin
Strings.Clear;
WinParam.PId:= PId;
WinParam.S:= Strings;
EnumWindows(@EnumWindowsProc, LPARAM(@WinParam));
end;


Con el mismo ejemplo de uso:

ListWinInfoFromPId(4800, Memo1.Lines);


Saludos.

Joviali
18-06-2012, 20:46:09
Buenas,
La funcion que me has pasado me ha ayudado mucho, por cierto he tenido que cambiar esto para que funcione

Código Delphi [-] (http://www.clubdelphi.com/foros/#)GetWindowThreadProcessId(Handle, PId);
por GetWindowThreadProcessId(Handle,@ PId);



La funcion me ha devuelto mas informacion de la que esperaba y me ha surgido la siguiente duda.
¿Puedo preguntar si la Clase TF_MULTICONSULTA es una calse class(TForm) ?.Esto me ayudaria ya
que me mostraria solo los formularios de la aplicacion.

hWnd: 000202B6h
Caption: MultiConsulta
Clase: TF_MULTICONSULTA
-----------------------------------------------
hWnd: 000102B0h
Caption: Aplicación Servidor -
Clase: TF_Principal
-----------------------------------------------
hWnd: 000202A2h
Caption:
Clase: TfrProgressForm
-----------------------------------------------
hWnd: 00060248h
Caption: Servidor -
Clase: TApplication
-----------------------------------------------
hWnd: 011B04D2h
Caption:
Clase: ComboLBox
-----------------------------------------------
hWnd: 000102CAh
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102C8h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102C6h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102C4h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102C2h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102C0h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102BEh
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102BCh
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102B4h
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102AEh
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102ACh
Caption:
Clase: TPUtilWindow
-----------------------------------------------
hWnd: 000102D8h
Caption: M
Clase: MSCTFIME UI
-----------------------------------------------
hWnd: 0004022Ch
Caption: Default IME
Clase: IME
-----------------------------------------------

escafandra
19-06-2012, 00:05:02
...he tenido que cambiar esto para que funcione

Código Delphi [-] (http://www.clubdelphi.com/foros/#)GetWindowThreadProcessId(Handle, PId);
por GetWindowThreadProcessId(Handle,@ PId);


Me extraña, al menos en mi delphi 7 el PID se para por referencia aunque la API usada en C/C++ recibe un pintero. :cool:

En principio estás explorando ventanas con la API, de cualquier APP. Sólo las aplicaciones basadas en la VCL tienen ventanas del tipo TForm. No se debe confundir la Clase de POO con la clase de ventana de windows, que no tiene nada que ver con la POO.

La VCL da nombres de clase de ventana (WindowClass) similares a los de la clase POO lo que ayuda al explorar ventanas de una APP escrita en delphi o Builder. Esto puede aproximarte a tu duda.

Puedes saber mas de las ventanas con otras API. Estudia GetWindowLong (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633584(v=vs.85).aspx). Con ella sabrás los estilos de ventada (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx) y deducir si la ventana que buscas es un TForm, pero nunca estarás seguro de ello con esta función.


Saludos.

Joviali
19-06-2012, 21:59:42
Puede que sea porque uilizo para este proyecto delphi 5

Al final voy a coger las clases y meterlas en una lista y comparla con otra lista de clases con el programa en reposo.De esta manera sabre si la APP este en el menu principal.Creo que con esto esta solucionado.
Una pregunta más cuando voy a guardar el buffer de la clase en un string me aperele lo siguiente:
TF_MULTICONSULTA'#0'’|º¡’|'#0#0#$15#0'`'#0#0'@]'#0'’|ð '#$16#0'#'#0#0'À-ÿ‘|ÿÿÿÿË£’|º¡’|'#0#0#$15#0'`'#0#0'@]'#0'’|'#0#0#0#0'-ÿ‘|ô'#3#3#0#0#0#0#0#1#0#0#0#0#0#$15#0'Äð'#$12#0#0#0'É'#0'”ó'#1#0' '#0#0#0'8ò'#$12#0'0ó'#$12#0'”ó'#$12#0' é‘|`'#0'’|ÿÿÿÿ]'#0'’|¬'#4'’|'#0#0#$15#0#0#0#0#0#$10#$17#$16#0#$18'ó'#$12#0'‚'#4'’|'#$10#$17#$16#0#0#0#$15#0#0#0#0#0 #0#0#0#0#0#0#0#0'üó'#$12#0'b4@'#0'þ!'#0#0#0#0#$15#0',ñ'#$12#0#0#0#$15#0'¦¥:~`ó:~'#0#0#0#0#0#0#0#0#0# 0#0#0#0#0#0#0'Ê'#0#0#0'`q'#$16#0'pó'#$12#0'ì'#$1B'£'#0'„õ'#$12#0'ø'#$C#0#0




. He intentando lipiarlo y dejar lo que me interesa(TF_MULTICONSULTA) con funciones que limpiar caracteres dobles, tambien con la siguiente funcion:
Código Delphi [-] (http://www.clubdelphi.com/foros/#)function TFORM1.QuitarCaracteres(Str: String): String; var i: Integer; begin Result:= EmptyStr; for i:= 1 to Length(Str) do if (Str[i] < #123)AND(Str[i] > #64) then Result:= Result + Str[i]; end;




y no hay manera siempre me encuentro algo de basura en algun caso.¿Se te ocurre algo?

Joviali
20-06-2012, 13:29:22
Perdon por el mensaje anterior, ya he solocionado el problema de la cadena con basura .Muchas gracias por haberme pasado esa funcion.