Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi "Echte" Sichtbarkeitsprüfung (https://www.delphipraxis.net/67565-echte-sichtbarkeitspruefung.html)

DGL-luke 16. Apr 2006 20:21


"Echte" Sichtbarkeitsprüfung
 
Moin moin,

für mein aktuelles Projekt versuche ich herauszufinden, ob ein Fenster sich in einem bestimmten Bereich befindet. Allerdings ist das ganze ein wenig verzwickter, ich hab da nämlich noch ein boolean, das sagt "soll im bereich sein" bzw. sagt "soll nicht im bereich sein".

Ich zeige mal ein wenig code...

Delphi-Quellcode:
GetWindowRect(handle,r);
IntersectRect(ir,r,area);
intersectspace := abs((ir.Right - ir.Left) * (ir.Bottom - ir.Top));

if ((intersectspace >= puffer) xor IsValidSpace) then
  begin
    machwas;
  end;
ich rechne also zuerst das schnittrechteck zwischen dem zu überprüfenden bereich und dem fenster aus. dann den flächeninhalt dieses rechtecks. wenn der größer ist als ein bestimmter puffer, ist das fenster im bereich.

Wenn das Boolean IsValidSpace wahr ist UND das fenter sich im bereich befindet, dann ist für mich alles ok, und es muss nichts gemacht werden.

Am besten mach ich mal ne wahrheitstabelle...

Code:
A = "fenster im bereich?"
B = "Bereich valide?"
C = "Muss ich was tun?"

1 = wahr
0 = falsch

A|B|C
-+-+-
0|0|0 => fenster ist nicht im nicht validen bereich => alles ok
0|1|1 => fenster ist nicht im validen bereich => was tun!
1|0|1 => fenster ist im nicht-validen bereich => was tun!
1|1|0 => fenster ist im validen bereich => alles ok
Das ist doch eindeutig ein Fall für eine XOR-Verknüpfung, oder?
Warum funktioniert es dann nicht? Ich bekomme ziemlich unerklärliche (wenn auch reproduzierbare^^) Ergebnisse.
Mach ich beim Schneiden irgendwas falsch?

Hawkeye219 16. Apr 2006 20:32

Re: "Echte" Sichtbarkeitsprüfung
 
Hallo Lukas,

GetWindowRect liefert Bildschirmkoordinaten. Befinden sich in der Variablen area vielleicht lokale Koordinaten, welche erst in Bildschirmkoordinaten umgerechnet werden müssen?

Gruß Hawkeye

marabu 16. Apr 2006 20:36

Re: "Echte" Sichtbarkeitsprüfung
 
Hallo Lukas,

deine Flächenberechnung solltest du davon abhängig machen, ob das Rechteck ir leer ist:

Delphi-Quellcode:
begin
  // ...
  if not IsRectEmpty(ir) then
    if ((intersectspace >= puffer) xor IsValidSpace) then
    begin
      machwas;
    end;
  // ...
end;
Ostergrüße vom marabu

DGL-luke 16. Apr 2006 20:39

Re: "Echte" Sichtbarkeitsprüfung
 
@hawkeye: nein. Kann ich ausschließen. area ist normalerweise der gesamte Bildschirm, also 0|0-1024|768 oder ähnlich.

@marabu: werd ich probieren... aber wenn es leer ist, heisst das doch nur, dass der erste teil false ergibt, also "nicht im bereich" -> as expected...

EDIT: das muss sogar mit aufgenommen werden. denn wenn das rect leer ist und IsValidSpace true, also "nicht im validen Bereich", will ich ja was machen.

marabu 16. Apr 2006 20:50

Re: "Echte" Sichtbarkeitsprüfung
 
Zitat:

Zitat von DGL-luke
aber wenn es leer ist, heisst das doch nur, dass der erste teil false ergibt

Würde ich so nicht behaupten wollen:

Delphi-Quellcode:
function InterSectRect(var rect: TRect; const r1, r2: TRect): Boolean;
begin
  rect.Left := Max(r1.Left, r2.Left);
  rect.Top := Max(r1.Top, r2.Top);
  rect.Right := Min(r1.Right, r2.Right );
  rect.Bottom := Min(r1.Bottom, r2.Bottom);
  Result := (rect.Left <= rect.Right) and (rect.Top <= rect.Bottom);
end;
Durch deinen Einsatz von Abs() ignorierst du die Bedingung für ein leeres Rechteck.

Zitat:

Zitat von DGL-luke
das muss sogar mit aufgenommen werden. denn wenn das rect leer ist und IsValidSpace true, ... will ich ja was machen.

Okay, dann so:

Delphi-Quellcode:
begin
  // ...
  if IsRectEmpty(ir)
    then intersectspace := 0
    else intersectspace := abs((ir.Right - ir.Left) * (ir.Bottom - ir.Top));
 
  if ((intersectspace >= puffer) xor IsValidSpace) then
  begin
    machwas;
  end;
  // ...
end;
marabu

Hawkeye219 16. Apr 2006 21:04

Re: "Echte" Sichtbarkeitsprüfung
 
@marabu:
Jetzt hast Du ja doch noch Deinen InterSectRect-Algorithmus verraten! 3_of_8 wird sich freuen. :mrgreen:

Falls Lukas aber die Routine aus Windows.pas nimmt, dann gilt das hier:

Zitat:

Zitat von Win32 Programmer's Reference
If the source rectangles do not intersect, an empty rectangle (in which all coordinates are set to zero) is placed into the destination rectangle.

Vielleicht sollte er das mal prüfen. Möglicherweise benutzt er ja eine andere Routine und erwartet ein leeres Rechteck bei sich nicht überschneidenen Rechtecken.

Gruß Hawkeye

DGL-luke 16. Apr 2006 21:07

Re: "Echte" Sichtbarkeitsprüfung
 
Zitat:

Überlappen sich R1 und R2 nicht, gibt IntersectRect false zurück und dem Parameter Rect wird ein Rechteck mit der Position (0,0), der Breite 0 und der Höhe 0 zugewiesen.
Belügt mich da die Delphi-OH?! Wohl eher die als dein Source-Code(hab ja keine vcl-sourcen)...

hab das jetzt so nachgebildet:

Delphi-Quellcode:
if not IntersectRect(ir,r,area) then
    begin
      ir.left := 0;
      ir.Top := 0;
      ir.Right := 0;
      ir.Bottom := 0;
    end;
und dann folgerichtig meinen anfänglichen code wieder eingetragen:

Delphi-Quellcode:
intersectspace := abs((ir.Right - ir.Left) * (ir.Bottom - ir.Top));

if ((intersectspace > 50) xor IsValidSpace) then
  begin
    machwas;
  end;
Kurioserweise bekomme ich jetzt nur die Borland-IDE und die Anwendung selbst in machwas geliefert (das ist ein teil einer EnumWindowsProc)...

//roter Kasten:
Ja, genau....

marabu 16. Apr 2006 21:21

Re: "Echte" Sichtbarkeitsprüfung
 
Zitat:

Zitat von DGL-luke
Belügt mich da die Delphi-OH?! Wohl eher die als dein Source-Code(hab ja keine vcl-sourcen)...

Ist meine Implementierung von IntersectRect. Delphi kapselt lediglich die gleichnamige API Funktion. Ich hatte mich wohl zu sehr von dem hier leiten lassen:

Im PSDK steht
The IsRectEmpty function determines whether the specified rectangle is empty. A empty rectangle is one that has no area; that is, the coordinate of the right side is less than or equal to the coordinate of the left side, or the coordinate of the bottom side is less than or equal to the coordinate of the top side.

Jetzt bin ich auch etwas ratlos. Werde mal drüber schlafen.

Zitat:

Zitat von Hawkeye219
Jetzt hast Du ja doch noch Deinen InterSectRect-Algorithmus verraten! 3_of_8 wird sich freuen.

Ob er es merkt? Und selbst wenn - ob er es dann auch erklären kann?

marabu

DGL-luke 16. Apr 2006 21:36

Re: "Echte" Sichtbarkeitsprüfung
 
OK, dann is das klar.

Ich werd jetzt meinen Code noch mal von anfang an aufziehen.

Inzwischen hab ich auch die Abfrage geändert:

Delphi-Quellcode:
if (inspace and (not spacevalid)) or ((not inspace) and spacevalid) then
    machwas;
das sollte ja hoffentlich funktionieren... (oder schlägt da eh die compiler-optimierung zu? :mrgreen:)

DGL-luke 16. Apr 2006 23:02

Re: "Echte" Sichtbarkeitsprüfung
 
Sodele... hab das jetzt gelöst. Der relevante Code:
Delphi-Quellcode:
GetWindowRect(handle,wr);

  //wenn das fenster die Höhe/Breite 0 hat, ist es offensichtlich kein
  //relevantes fenster.
  if (wr.Right = wr.Left) or (wr.Bottom = wr.Top) or
     ((wr.Left = -32000) and Form1.CBSkipMaximized.Checked) then
    Exit;

if (IntersectRect(ir,wr,Form1.area) xor Form1.RBValid.Checked) then
    Form1.ListBox1.AddItem(c,TObject(handle));
Hab den Puffer einfach rausgenommen.

So einfach isses :gruebel:

Tut wunderbar.. hab übrigens nicht deine Intersectrect hergenommen.

Haben maximierte Fenster eigentlich immer das offset (-32000|-32000) ?!

Den kompletten Code gibts hier: http://www.delphipraxis.net/internal...ct.php?t=80732


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz