Recent

Author Topic: Redimensionar y reposicionar ventanas con Lazarus  (Read 8381 times)

mgayo

  • New Member
  • *
  • Posts: 17
Redimensionar y reposicionar ventanas con Lazarus
« on: November 27, 2021, 01:00:04 pm »
Hola:
Necesito crear una aplicación que me permita redimensionar y reposicionar ventanas. No solo las de mi aplicación sino las del resto de aplicaciones que estén abiertas en ese momento. Sería sobre Windows.
La idea sería sacar un listado de todas esas ventanas, elegir aquella que quiero manipular y después redimensionarla o reposicionarla.
He hecho alguna búsqueda por Internet pero redimensionar, Windows, resize ... son palabras tan generales que no he encontrado nada útil.
¿Alguna sugerencia de por dónde tengo que empezar a tirar del hilo?
Gracias.

Edson

  • Hero Member
  • *****
  • Posts: 1232
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #1 on: November 29, 2021, 05:22:07 am »
Hola.

Nunca lo he intentado desde Lazarus, pero recuerdo que para Windows tendrías que hacer uso de las llamadas a las API de windows. Algo como SetWindowPos() y similares, que deben ser accesibles desde Lazarus.

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos

Todo esto es a muy bajo nivel. No conozco otra forma.
Lazarus 2.0.10 - FPC 3.2.0 - x86_64-win64 on Windows 8

mosquito

  • Full Member
  • ***
  • Posts: 101
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #2 on: December 02, 2021, 09:58:12 am »
Usando Linux uso 'xprop' que me devuelve el 'WM_CLASS' de una ventana, con este dato puedo trastear con la ventana hasta donde me deja el entorno gráfico.

Aunque no tengo mucha idea de Windows, juraría que lo que necesitas es recibir es el HWND, debe ser como el identificador de la ventana (lo recuerdo de usar AutoHotkey).

Si consigues disparar llamadas a la winapi, podrías usar estas  funciones, aunque ni idea de su estructura interna:

BeginDeferWindowPos()
DeferWindowPos()
EndDeferWindowPos()
SetWindowPlacement

Estas están 'deprecated' por no evitar flick.
SetWindowPos()
MoveWindow()
AdjustWindowRectEx()

Para recibir el listado de todas las ventanas abiertas quizás alguna de estas, pero no te lo puedo asegurar:

GetWindowText
GetClassName

Al menos en Linux a veces hay problema a la hora de identificar la WM_CLASS si no conoces el nombre exacto (Case Sensitive).

Suponiendo que GetClassName haga algo similar, yo usaría
getclassname('google-chrome') OR getclassname('Google-Chrome').

Pero a ver si contesta algún experto, porque yo, ni idea.
 

RayoGlauco

  • Full Member
  • ***
  • Posts: 123
  • Beers: 1567
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #3 on: December 02, 2021, 11:30:28 am »
Hola,

Yo tengo este código que usé hace tiempo, para localizar los handles de todas las ventanas.

Code: Pascal  [Select][+][-]
  1. uses
  2.   Windows;
  3.  
  4. procedure BuscarVentanas;
  5. var
  6.   NextHandle: Hwnd;
  7. begin
  8.   // Buscar handle de la primera ventana
  9.   NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  10.   while (NextHandle > 0) do
  11.   begin
  12.     // hacer lo que sea con NextHandle
  13.     ...
  14.     // buscar la siguiente ventana
  15.     NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  16.   end;
  17. end;
« Last Edit: December 02, 2021, 11:38:22 am by RayoGlauco »
To err is human, but to really mess things up, you need a computer.

mgayo

  • New Member
  • *
  • Posts: 17
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #4 on: December 03, 2021, 01:13:41 pm »
Muchas gracias a todos por las respuestas.
Me proporcionan el punto de inicio para tratar de encontrar la solución.
Ahora no tengo tiempo de probar, pero lo intentaré.
Un saludo.

mgayo

  • New Member
  • *
  • Posts: 17
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #5 on: December 22, 2021, 07:44:08 pm »
Ya me he puesto con el tema y con vuestra ayuda ha resultado fácil. Muchas gracias.
Ya consigo un listado de ventanas y puedo redimensionar la que quiero.
El problema es que el listado contiene cientos de ventanas pero solo me interesan las que se corresponden con las aplicaiones que hay abiertas. Tal y como está me obliga a recorrer infinidad de opciones en el listado y es muy incómodo.
He intentado buscar una manera de filtrar pero no la encuentro.
¿Alguna sugerencia de como puedo hacer ese filtrado?
Gracias.

RayoGlauco

  • Full Member
  • ***
  • Posts: 123
  • Beers: 1567
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #6 on: December 23, 2021, 11:28:09 pm »
Tengo un par de pistas:

1) buscar la ventana propietaria de la que hemos encontrado (quizás recursivamente, hasta encontrar una que ya no tenga propietaria)
2) descartar las ventanas no visibles

Code: Pascal  [Select][+][-]
  1. // Hallar la ventana propietaria de otra
  2. handlepropietario := GetWindow(handle, GW_OWNER);  // devuelve 0 si no hay propietario
  3.  
  4. // Saber si una ventana es visible
  5. if IsWindowVisible(handle) then // ...
  6.  
To err is human, but to really mess things up, you need a computer.

mgayo

  • New Member
  • *
  • Posts: 17
Re: Redimensionar y reposicionar ventanas con Lazarus
« Reply #7 on: January 08, 2022, 11:25:39 am »
En primer lugar muchas gracias a todos los que habéis arrojado algo de luz en el tema.

He conseguido el propósito de aislar las ventanas de las aplicaciones pero no me parece una solución muy elegante y además no es portable. He usado una combinación de condiciones y al final he añadido la condición de parar al encontrar la ventana con título "Microsoft Text" que he observado que es la primera que corresponde al SO. A partir de esa, hay alguna otra del SO que no me interesa. Os pongo el código por si a alguien le interesa o puede sugerir alguna mejora:

Code: Pascal  [Select][+][-]
  1.      { Eliminamos las que tengan 0 píxeles de anchura o de altura }
  2.      DwmGetWindowAttribute(hw,DWMWA_EXTENDED_FRAME_BOUNDS,@rect,sizeof(rect));
  3.      nula:=(rect.Bottom-rect.Top=0) or (rect.Right-rect.Left=0);
  4.      Getwindowtext(hw, titulo, 255);
  5.      final:=pos('Microsoft Text',titulo)=1; { Marca la ventana final }
  6.      if IsWindowVisible(hW) and { que sea visible }
  7.         ((getwindow(hw,GW_OWNER)=0) or form1.cb_hijas.checked) and { Que sea padre o estén habilitadas las hijas }
  8.         (GetWindowTextLength(hw)>0) and { que el título no sea nulo }
  9.         (pos('RedimensionaVentana',titulo)<>1) and { Elimina esta aplicación }
  10.         not nula and  { Que no tenga dimensiones nulas (ni altura ni anchura) }
  11.         not final then { Elimina las ventanas iniciales del sistema operativo. (Esto es arbitrario) }
  12.         begin
  13.         inc(contvent);
  14.         form1.listbox1.Items.Add(inttostr(contvent)+': '+inttostr(hW)+' --- '+titulo);
  15.         end;
« Last Edit: January 08, 2022, 11:28:58 am by mgayo »

 

TinyPortal © 2005-2018