AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Durch ein Bild "hindurchklicken"? Darunterliegendes Bild erm
Thema durchsuchen
Ansicht
Themen-Optionen

Durch ein Bild "hindurchklicken"? Darunterliegendes Bild erm

Ein Thema von blackdrake · begonnen am 15. Mär 2009 · letzter Beitrag vom 24. Mär 2009
Antwort Antwort
Seite 2 von 2     12   
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#11

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 20. Mär 2009, 18:53
Hallo.

Ich habe nichts zu dem Thema "Regions" außer einer kostenpflichtigen VCL bei Torry gefunden. Wo finde ich weitere Informationen zu Panels, die eine Maske besitzen?

Ich werde mir mal das Coolform anschauen, doch ich befürchte, solche Masken gelten nur für Forms ( https://forums.codegear.com/thread.j...9066&tstart=75 ). Ich möchte aber auch ein TImage in beliebige Formen zuschneiden können, sodass der Benutzer das Darunterliegende Anklickt/Verschiebt/etc, wenn er in das Transparente klickt. Was gibt es da für Lösungen?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#12

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 20. Mär 2009, 21:39
Hi blackdrake,

mit regions kannst du die Transparenten Teile deiner Controls "durchklickbar" machen. Das gilt nicht nur für Forms. Klappt bei jedem WinControl. Such mal hier nach regions und du wirst ne Menge Beiträge dazu finden.

Gruß oki
42
  Mit Zitat antworten Zitat
Benutzerbild von _frank_
_frank_

Registriert seit: 21. Feb 2003
Ort: Plauen / Bamberg
922 Beiträge
 
Delphi 3 Professional
 
#13

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 20. Mär 2009, 22:24
ein Beispiel für bitmap-gesteuerte regions: http://www.delphi-central.com/BitmapShapedForm.aspx

HTH Frank
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#14

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 21. Mär 2009, 20:49
Hallo.

Vielen Dank für den Hinweis. Ich habe ein paar Informationen gefunden, jedoch ist es mit den Regions ziemlich umständlich. Ich habe jetzt folgende Komponente, die jedoch extrem unperformant ist. Die Pixels werden abgeglichen und ggf. zu langgezogenen Rects zusammengefasst, die dann mit CombineRgn vereinigt werden. Das ist aber bereits bei meiner Beispielgrafik mit 300x200 Pixeln bei 7 Sekunden Berechnungszeit inakzeptabel. Gibt es irgendeine Lösung dafür?

Delphi-Quellcode:
type
  TTransClickMask = class(TCustomControl)
  private
    FImage: TImage;
    FPicture: TPicture;
    procedure SetPicture(Value: TPicture);
    procedure MakeTransparent;
    // procedure DestroyTransparency;
    procedure PictureChanged(Sender: TObject);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  published
    property Picture: TPicture read FPicture write SetPicture;
  end;

{ TTransClickMask ... BETA }

constructor TTransClickMask.Create(AOwner: TComponent);
begin
  inherited;

  FImage := TImage.Create(Self);
  FImage.Parent := Self;
  FImage.AutoSize := true;

  FPicture := TPicture.Create;
  FPicture.OnChange := PictureChanged;

  FImage.Picture.Assign(FPicture);
end;

destructor TTransClickMask.Destroy;
begin
  FPicture.Free;
  FImage.Free;
  inherited;
end;

(* procedure TTransClickMask.DestroyTransparency;
var
  Rgn: THandle;
begin
  Rgn := CreateRectRgn(0, 0, Width, Height);
  SetWindowRgn(Handle, Rgn, true);
  DeleteObject(Rgn);
end; *)


procedure TTransClickMask.MakeTransparent;
var
   x,y                        : integer;
   rgn1,
   rgn2                     : hrgn;
   startx,endx            : integer;
begin
  // Code entnommen aus der Demo von TCoolForm, mit einem Bugfix

   // for every line do...
   rgn1 := 0;
   for y := 0 to FImage.Picture.BitMap.Height-1 do
   begin
      x := -1;
    repeat
         // look for the beginning of a stretch of non-transparent pixels
         while (FImage.Picture.bitmap.canvas.pixels[x,y] = $00FFFFFF) and (x = FImage.Picture.BitMap.width) do
      begin
           inc(x);
      end;
         startx := x;

         // look for the end of a stretch of non-transparent pixels
         inc(x);
         while (FImage.Picture.bitmap.canvas.pixels[x,y]<>$00FFFFFF) and (x<(*=*)FImage.Picture.BitMap.width) do
      begin
           inc(x);
      end;
         endx := x;

         // do we have some pixels?
         if startx <> FImage.Picture.BitMap.Width then
         begin
            // do we have a region already?
            if rgn1 = 0 then
            begin
               // Create a region to start with
               rgn1 := CreateRectRgn(startx+1,y,endx,y+1);
            end else
            begin
               // Add to the existing region
               rgn2 := CreateRectRgn(startx+1, y, endx, y+1);
               if rgn2 <> 0 then CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
               DeleteObject(rgn2);
            end;
         end;
      until x >= FImage.Picture.BitMap.width - 1;
   end;

  SetWindowRgn(Handle, Rgn1, true);
  DeleteObject(Rgn1);
end;

procedure TTransClickMask.PictureChanged(Sender: TObject);
begin
  // DestroyTransparency;

  FImage.Picture.Assign(FPicture);

  Width := FPicture.Width;
  Height := FPicture.Height;

  MakeTransparent;
end;

procedure TTransClickMask.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  if AWidth <> FPicture.Width then AWidth := FPicture.Width;
  if AHeight <> FPicture.Height then AHeight := FPicture.Height;
  inherited;
end;

procedure TTransClickMask.SetPicture(Value: TPicture);
begin
  FPicture.Assign(Value);
end;
Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#15

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 21. Mär 2009, 22:08
Hi,

ich find den Thread im Moment nicht, aber ich hatte mir den code seinerzeit auf die Platte geholt. Hier mal für dich zum Testen.

ich hatte auch noch ein Beispiel mit "Pixelauswertung". ich such noch mal.

Gruß oki
Angehängte Dateien
Dateityp: zip tranform_131.zip (2,1 KB, 10x aufgerufen)
42
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#16

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 21. Mär 2009, 22:12
Auch hier hab ich aktuell nur den Code gefunden. Vielleicht finde ich auch noch den Thread.

Gruß oki
Angehängte Dateien
Dateityp: zip formdemo_208.zip (317,4 KB, 11x aufgerufen)
42
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#17

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 24. Mär 2009, 09:29
Hallo.

Vielen Dank für die Beispiele.

Bei dem FormDemo habe ich noch einen Bugfix machen müssen, damit auch 1-Pixel-Breite Linien dargestellt werden können:

Excl := CreateRectRGN(StartX, Y, X (** Bugfix: hier war +1 **), Y + 1); Bei dem FrmDemo, das mit ScanLines arbeitet, geht es jetzt schon viel schneller. Natürlich ist es je nach Grafik unterschiedlich. Hier mein aktueller Testlauf:

Testcomputer: 500 MHz; 2 Durchläufe innerhalb Debugger, gemessen mit Now+TimeToStr+ShowMessage.
Referenz-Testgrafik siehe Anhang.

Modifizierter TCoolForm Code (siehe oben)
--> 23 Sekunden

FrmDemo
--> 4 Sekunden

Tranform
--> (hat ja gar nichts mit BMP-Masken zu tun)

* 4 Sekunden sind hingegen trotzdem ein bisschen lahm, auch wenn ich zugeben muss, dass meine Referenzgrafik darauf optimiert ist, den Code auszubremsen. Gibt es denn keine andere Möglichkeit als CreateRectRgn+CombineRgn z.B. mit Assembler oder API-Varianten, bei denen man die BMP direkt übergibt?

Was ich bei den Scanlines aber noch nicht ganz verstehe, ist die Implementierung im FrmDemo.

In der Delphi-Hilfe steht im Beispiel PByteArray.

Dieser ist in Delphi definiert als:

Delphi-Quellcode:
type
  PByteArray = ^TByteArray;
  TByteArray = array[0..32767] of Byte;

var
  P: PByteArray;
begin
  P := Bmp.ScanLine[i];
end;
In deinem Beispiel ist die Verwendung:

Delphi-Quellcode:
type
  PRGBTriple = ^TRGBTriple;
  {$EXTERNALSYM tagRGBTRIPLE}
  tagRGBTRIPLE = packed record
    rgbtBlue: Byte;
    rgbtGreen: Byte;
    rgbtRed: Byte;
  end;
  TRGBTriple = tagRGBTRIPLE

type
  TRGBArray = array[0..32767] of TRGBTriple;
  PRGBArray = ^TRGBArray;

var
  P: PRGBArray;
begin
  P := Bmp.ScanLine[i];
end;
* Seltsam:
- Im Delphi-Beispiel wird ScanLine[] in ein 32767x1 Byte großen Typ gepackt
- Im FormDemo-Beispiel wird ScanLine[] in ein 32767x3 Byte großen packed Typ gepackt
Wird es bei letzterem Probleme geben, weil der Typ 3fach so groß ist? Komisch, dabei ist 32768 (Länge des Arrays) nicht mal durch 3 teilbar... Welche Werte repräsentieren dann die Elemente? Wäre die Reihenfolge RGBRGBRGB... wäre es doch ein Vielfaches von 3.

* Wo die Zahl 32767 (2^15-1) herkommt bzw. wer dieses Limit vorschreibt, ist mir ebenfalls rätselhaft und ich weiß nicht, ob es dabei zu Limitationen beim Einlesen von großen BMPs kommen könnte.

Gruß
blackdrake
Angehängte Dateien
Dateityp: zip referenzgrafik_338.zip (2,0 KB, 13x aufgerufen)
Daniel Marschall
  Mit Zitat antworten Zitat
Benutzerbild von _frank_
_frank_

Registriert seit: 21. Feb 2003
Ort: Plauen / Bamberg
922 Beiträge
 
Delphi 3 Professional
 
#18

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 24. Mär 2009, 10:49
Zitat von blackdrake:
Vielen Dank für die Beispiele.
eins hab ich noch...

und zwar gibts noch die möglichkeit sich selbst ein canvas zu basteln und anhand diesem die region auszuschneiden. ich hab das damals mal für ein OnScreenDisplay genommen, wo der dargestellte Text ausgeschnitten wurde

zu finden ist ein Beispielprojekt als OSD.zip auf http://www.fw-web.de/units.htm

Zitat von blackdrake:
* Wo die Zahl 32767 (2^15-1) herkommt bzw. wer dieses Limit vorschreibt, ist mir ebenfalls rätselhaft und ich weiß nicht, ob es dabei zu Limitationen beim Einlesen von großen BMPs kommen könnte.
das is der positive Wertebereich eines 16 bit integertypen...warum dieser genommen wird, weis ich nicht vielleicht lässt es sich auch auf 32bit und/oder Cardinal aufbohren.

Gruß Frank
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#19

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 24. Mär 2009, 21:35
Zitat von _frank_:
eins hab ich noch...
OK, schau ich mir gleich mal an.

Zitat von _frank_:
das is der positive Wertebereich eines 16 bit integertypen...
Hört sich irgendwie gefährlich an. Borland verwendet also einen Pointer, der auf einen 16-Bit-Bereich (32767 Byte) zugreift. Man muss also davon ausgehen, dass das Bitmap im Speicher (auf das der Pointer zeigt) maximal 32767 groß ist. Du (oder der Verfasser des Codes) verwendet aber durch die R+G+B-Kombination einen 3-fach so großen Speicher, also 3x32767. Bedeutet dass, dass nach 10922 Bytes (32767 div 3) die Anwendung auf den Nachbarspeicher zugreift? Dann brennt's.

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
Benutzerbild von _frank_
_frank_

Registriert seit: 21. Feb 2003
Ort: Plauen / Bamberg
922 Beiträge
 
Delphi 3 Professional
 
#20

Re: Durch ein Bild "hindurchklicken"? Darunterlieg

  Alt 24. Mär 2009, 22:16
ich denke mal, das mit dem array of record ist eine reine dimensionierungsgeschichte...
soweit ich mich erinnere, holt man sich ja scanline nur den poiter pro zeile im bitmap, und holt sich nicht einen Pointer, um das ganze Bitmap durchzugehen...
d.h. es wären maximal 32767 pixel (bei 3 byte-record) in horizontaler Ausdehnung möglich. sollte reichen, oder?

willst du letzteres erreichen (1 Pointer pro bitmap), wäre evtl. ein dynamisches Array sinnvoll, weis aber nicht, ob das mit dem Pointer-Typ damit funktioniert.

Gruß Frank
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz