Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   API de Windows (https://www.clubdelphi.com/foros/forumdisplay.php?f=7)
-   -   Handle disabled (https://www.clubdelphi.com/foros/showthread.php?t=39219)

carlos_nielsen 13-01-2007 14:16:32

Handle disabled
 
Quisiera saber como obtener el handle de un control de un form (como por ejemplo un tedit)
que esta deshabilitado (enabled:=false). Estoy probando con hooks de sistema y logro obtener
los handles de los controles al pasar el mouse por encima pero si el control esta deshabilitado
obtengo el handle del form.
Si alguien puede orientarme un poco por donde buscar o pasarme algun codigo de ejemplo le voy a agradecer.

seoane 13-01-2007 14:52:06

¿Que hooks utilizas? ¿Puedes poner algo de código?

carlos_nielsen 13-01-2007 16:17:19

Utilizo una hook de mouse para obtener los handles de los objetos alm pasar el puntero del mouse por encima. paso codigo de libreria y programa.
Código Delphi [-]
 
 library hookmouse;
 uses
  Windows,
  Messages;
const
  CM_MANDA_DATOS = WM_USER + $1000;
 type
  TCompartido = record
    Receptor,
    wHitTestCode,
    x,y,
    Ventana         : hwnd;
  end;
  PCompartido   =^TCompartido;

 var
  HookDeMouse  : HHook;
  FicheroM     : THandle;
  Compartido   : PCompartido;

 function CallBackDelHook( Code    : Integer;
                           wParam  : WPARAM;
                           lParam  : LPARAM
                           )       : LRESULT; stdcall;
 var
   DatosMouse     : PMouseHookStruct;
   Intentos       : integer;
 begin
  if code=HC_ACTION then
  begin
   FicheroM:=OpenFileMapping(FILE_MAP_WRITE,False,'ElReceptor');
   if FicheroM<>0 then
   begin
     Compartido:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);
     DatosMouse:=Pointer(lparam);
     Compartido^.Ventana:=DatosMouse^.hwnd;
     Compartido^.x:=DatosMouse^.pt.x;
     Compartido^.y:=DatosMouse^.pt.y;
     PostMessage(Compartido^.Receptor,CM_MANDA_DATOS,wParam,lParam);
     UnmapViewOfFile(Compartido);
     CloseHandle(FicheroM);
   end;
  end;
  Result := CallNextHookEx(HookDeMouse, Code, wParam, lParam)
 end;
 procedure HookOn; stdcall;
 begin
   HookDeMouse:=SetWindowsHookEx(WH_MOUSE, @CallBackDelHook, HInstance , 0);
 end;
 procedure HookOff;  stdcall;
 begin
   UnhookWindowsHookEx(HookDeMouse);
 end;
 exports
  HookOn,
  HookOff;
 begin
 end.
 
 
en el programa...........
 
procedure TForm1.LlegaDelHook(var message: TMessage);
var
  DatosMouse     : PMouseHookStruct;
  NombreVentana  : array [0..200] of char;
  Accion         : string;
begin 
  with Compartido^ do 
  begin
    Label1.caption:='['+IntToStr(x)+':'+IntToStr(y)+']';
  end;
  GetWindowText(Compartido^.Ventana,@NombreVentana,200);
  Label2.Caption:=NombreVentana;
  label3.Caption:=inttostr(Compartido^.Ventana);
//aqui en label3 es donde se van mostrando los handles de los controles por los que pasa el puntero del mouse.
Lo que me interesa es obtener el handle pero de un control que esta deshabilitado.

seoane 13-01-2007 16:59:11

Un problema curioso. Y le veo difícil solución, cuando un control (ventana) esta deshabilitado no recibe los mensajes del ratón. También pensé en utilizar la función WindowFromPoint, pero parece que no funciona con las ventanas deshabilitadas.

Se me ocurre que para lo que tu quieres hacer, puede haber otras soluciones que no pasen precisamente por utilizar hooks, quizás enumerando las ventanas podríamos conseguir el handle. ¿Es necesario usar el ratón para seleccionar la ventana? o podemos emplear otros métodos.

roman 13-01-2007 17:30:05

Cita:

Empezado por seoane
También pensé en utilizar la función WindowFromPoint, pero parece que no funciona con las ventanas deshabilitadas.

Aunque el SDK indica que puede usarse ChildWindowFromPoint para esos casos. Claro que si la ventana deshabilitada es la ventana padre pues...

// Saludos

seoane 13-01-2007 18:43:46

1 Archivos Adjunto(s)
Cita:

Empezado por roman
Aunque el SDK indica que puede usarse ChildWindowFromPoint para esos casos. Claro que si la ventana deshabilitada es la ventana padre pues...

Siempre con la última palabra :p :D

Es verdad, ChildWindowFromPoint puede obtener el handle de una ventana deshabilitada, pero primero necesitamos tener el handle de su padre, o en su caso abuelos :D Pero eso lo podemos solucionar fácilmente con un bonito bucle. La cosa quedaría así:

Código Delphi [-]
const
  // Utilizamos un hook de bajo nivel, asi no me lio con dlls
  WH_MOUSE_LL = 14;

type
  ULONG_PTR = ULONG;
  // Esta estructira es necesaria para el Hook
  TMSLLHOOKSTRUCT = record
    pt: TPoint;
    mouseData: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: ULONG_PTR;
  end;
  PMSLLHOOKSTRUCT = ^TMSLLHOOKSTRUCT;

var
  MouseHook: HHook;

// Esta funcion nos devuelve el handle de la ventana mas joven.
function HandleFromPoint(P: TPoint): THandle;
var
  hWnd: THandle;
  ClientP: TPoint;
begin
  hWnd:= WindowFromPoint(P);
  repeat
    Result:= hWnd;
    ClientP:= P;
    if Windows.ScreenToClient(hWnd,ClientP) then
      hwnd:= ChildWindowFromPoint(hWnd,ClientP);
  until (hWnd = 0) or (Result = hWnd);
end;

function MouseProc(Code: Integer; WParam, LParam: DWORD): LRESULT; stdcall;
begin
  if (Code = HC_ACTION) and (WParam = WM_MOUSEMOVE) then
  begin
    frmMain.Caption:= IntToStr(HandleFromPoint(PMSLLHOOKSTRUCT(lParam).pt));
  end;
  Result := CallNextHookEx(MouseHook, Code, WParam, LParam);
end;

Te dejo todo esto envuelto para regalo :p , en este zip:

marcoszorrilla 13-01-2007 19:17:02

Pues acabo de hacer una prueba con el ejemplo que envías y sí que queda bonito el bucle mentado.

Un Saludo.

carlos_nielsen 14-01-2007 21:13:08

Antes de continuar con el tema específico hago una pausa para comentarte que es la primera vez que escribo en un foro, y la verdad es que me veo gratamente sorprendido por la solidaridad demostrada respondiendo a las preguntas y tan rapido! asique renuevo mi agradecimiento.
Te comento que el codigo que me mandaste se compila perfecto pero no me da ningun resultado.(lo unico que quite es la declaracion de variants de las units porque no la tengo, pero no creo que influya, si compilo bien es porque no la necesitaba supongo).
Por otro lado me ayudaste un monton porque resolvi el problema con la funcion ChildWindowFromPoint desde mi programa. Aunque me surgio un nuevo problema. No puedo cambiar el texto de un label de otra aplicacion puesto que esta es un control estatico y no tienen handle. Que me sugeris para resolver el tema.

seoane 14-01-2007 21:23:01

:confused: ¿Probaste el ejemplo que viene en el zip? ¿No te aparece en el caption del form el handle de las ventanas al mover el ratón? Pues no lo entiendo ...

Por otra parte preguntas como cambiar el texto de un control de otra aplicación. ¿Como lo estas intentando ahora?

carlos_nielsen 15-01-2007 00:25:54

Cita:

Empezado por seoane
:confused: ¿Probaste el ejemplo que viene en el zip? ¿No te aparece en el caption del form el handle de las ventanas al mover el ratón? Pues no lo entiendo ...

Por otra parte preguntas como cambiar el texto de un control de otra aplicación. ¿Como lo estas intentando ahora?

Si. probe y no funciona. Cuando tenga mas tiempo lo voy a tratar de analizar a ver porque falla. si obtengo alguna novedad te aviso.
El texto lo cambio como te dije en los anteriores mensaje. Obtengo el handle de cualquier objeto visible al pasar el mouse por encima. Luego cambio el texto del objeto(edit,button,form,etc) pasandole el handle. En unas horas vuelvo al cyber y te paso el codigo completo de la dll y el programa. tengo que hacer un tramite primero y emprolijar primero el codigo porque a esta altura de agregados ya casi ni yo lo entiendo.
si tenes idea de como trabajar con labels pasame alguna idea porque estoy desorientado. no se por donde buscar ya que no se como se identifican. seria interesante tambien si sabes alguna manera de espiar todos los mensajes que procesa una aplicacion desde que se crea (una aplicacion externa a la mia)

seoane 15-01-2007 01:05:14

:confused: Carlos ¿Usas windows 98? porque el hook de bajo nivel solo funciona en 2000/XP. Es la única explicación que se me ocurre ...

Bueno, dejando ese tema aparte, vamos con tu segunda pregunta.
Cita:

Empezado por carlos_nielsen
El texto lo cambio como te dije en los anteriores mensaje

No soy capaz de encontrar donde muestras como cambias el texto de otra ventana, pero lo que si veo es como lo lees.
Cita:

Empezado por carlos_nielsen
GetWindowText(Compartido^.Ventana,@NombreVentana,200);

Como habrás notado tanto esta función, como SetWindowText, no funcionan en ventanas hijas de otras aplicaciones. Por eso te preguntaba como lo hacías, porque así ya podíamos saber si ese era el error.

Cita:

Empezado por carlos_nielsen
En unas horas vuelvo al cyber y te paso el codigo completo de la dll y el programa

Vale, dejemoslo hasta entonces ... ;)

carlos_nielsen 15-01-2007 02:23:23

La funcion que utilizo es sendmessage para enviarle el mesaje que quiero que procese la aplicacion destino.
el formato es el siguiente:
sendmessage(handle,wm_settext,0,longint(pchar('texto')))
el mismo efecto se consigue con postmessage la diferencia es que post pone el mensaje en la cola de mensajes de la aplicacion destino y retorna. send espera a que le devuelva un valor.
el error de la apliacion que me mandaste es como dijiste. lo ejecute en un ordenador con w98.


La franja horaria es GMT +2. Ahora son las 19:52:08.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi