AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Region vom Typ THandle abspeichern
Thema durchsuchen
Ansicht
Themen-Optionen

Region vom Typ THandle abspeichern

Ein Thema von Silenoz84 · begonnen am 11. Mai 2004 · letzter Beitrag vom 12. Mai 2004
Antwort Antwort
Seite 1 von 2  1 2      
Silenoz84

Registriert seit: 11. Mai 2004
Ort: Frankfurt
18 Beiträge
 
#1

Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 01:17
Servus Leute,

wollte mir en komplett eigenes Fensterdesign für mein Proggi machen! Hatte das zuerst mit den API Funktionen CreateRectRgn, CreateEllipticalRgn und CombineRgn und anschließend mit SetWindowRgn wo ich dann diese Regionen auf das Handle meiner Form setzten kann!

War mir allerdings zu blöd nur auf Kreise und Rechtecke zurückgreifen zu müssen! Also habe ich mir ein Proggi geschrieben mit dem ich eine beliebige Region erstelle (ich grenze Pixel für Pixel einer Bitmap aus). Mein Problem ist jetzt aber, wie bekomme ich diese Region abgespeichert um sie später wieder laden zu können???

Mit TFilestream hatte ich's schon probiert, musste dann allerdings frustriert festellten, dass das ja nicht so einfach geht, da THandle ja nur ne Art Zeiger ist! Aber wie komme ich jetz an diese Region die ich erstellt habe???

Hoffe irgendjemand konnte meinem verzweifeltem Versuch euch das Problem zu erklären folgen

*greetZ* Sile

P.S.: Hier nochmal ein paar Codefragmente dazu:

Code:
...
var rgnFinal, rgnTemp: THandle;
    x, y: Integer;
begin
  //Erstmal eine Rechteeckige Region um das gesamte Bild
  rgnFinal:= CreateRectRgn(0,0,bckBitmap.width,bckBitmap.height);

  //Anschließend Pixel für Pixel was TRansparentsfarbe
  //entspricht aus diesem Rechteck entfernen
  for x:= 0 to bckBitmap.width do
  begin
      for y:= 0 to bckBitmap.height do
      begin
          if bckBitmap.Canvas.Pixels[x,y] = clblack then
          begin
             rgnTemp:= CreateRectRgn(x,y,x+1,y+1);
             CombineRgn(rgnFinal,rgnFinal,rgnTemp, RGN_XOR);
             deleteobject(rgnTemp);
          end;
      end;
  end;

  SetWindowRgn(Form1.handle, rgnFinal, true);
  deleteobject(rgnFinal);
...
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#2

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 06:22
Du hast Recht: Regions SIND eine Art Zeiger, es ist aber nicht ganz das selbe. Ich glaube, es gibt eine Funktion, die als Eckpunkte für Regions ein dynamisches Array nimmt. Damit könntest du so viele punkte erzeugen wie du willst. Also:

-Finde irgendwie die Koordinaten der Punkte heraus
-Lade sie ins Array
-MakeRgn (Kann sein, das es anders heisst)
-Array speichern

Wie man das Array am besten speichert, weiss ich nicht, aber versuchs mal so:

Jeden Integer-Wert in eine Zeile der Datei
Zeilenweise einlesen
IntToStr

Have fun!
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 06:46
@Dax: ich muss leider enttäuchen. Es gibt eine Funktion die ein Array von punkten nimmst um die Region zu setzen aber bei dynamichen Array schlägt das fehl, man muss da ein statiches Angeben
So funktionierts:
Delphi-Quellcode:
var HR: HRgn;
     neu:array[0..8] of TPoint;
begin
 neu[0] := Point(1,1);
 neu[1] := Point(80,1);
 neu[2] := Point(80,50);
 neu[3] := Point(1,50);
 neu[4] := Point(1,1);
 neu[5] := Point(400,1);
 neu[6] := Point(400,150);
 neu[7] := Point(90,150);
 neu[8] := Point(90,1);
 HR:= CreatePolygonRgn(neu, length(neu), ALTERNATE);
 SetWindowRgn(Handle, HR, True);
würde man neu allerdings so definieren
Delphi-Quellcode:
neu: array of TPoint;
begin
  setlength(neu, 9);
so funktioniert das ganze nicht mehr - leider
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Silenoz84

Registriert seit: 11. Mai 2004
Ort: Frankfurt
18 Beiträge
 
#4

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 15:05
Hey thx, für die schnellen Antworten... aber die Sache mit der CreatePolygonRgn API hatte ich auch schon dran gedacht, allerdings wollte ich mich die ganze Zeit um den Algorithmus drücken, der die Punkte einer beliebigen polygonen(!?) Figur in einem Bitmap herausfindet. Also meinetwegen bei einer schwarzweißen Bitmap alle weißen Flächen als Polygon zusammenfast (würde glaube ich en oredntlich stück arbeit sein) und hatte desshalb gehofft, direkt en Region abspeichern zu können...

@Dax: is übrigens kein Prob en Array abzuspeichern, hab das mal für en 2D-Vektor-Grafik Proggi gebraucht:

Code:
procedure TPolygon.Save(fs: TFileStream);
var i: Integer;
begin
   ...

   fs.Write(PointsCount, sizeof(Integer));

   for i:= 0 to PointsCount - 1 do
       fs.Write(Points[i], sizeof(TPoint));

   ...
end;
I bin einfach mit der g'sammt Situation unzufrieden...
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 15:14
warum machst du nicht einfach noch eine config-datei zu deinen bitmaps? Oder du legst fest das pink zum beispiel transparent ist und machst dann alles was durchsichtig sein soll pink. Simit ersparst du dir auch das mit den Regions
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Silenoz84

Registriert seit: 11. Mai 2004
Ort: Frankfurt
18 Beiträge
 
#6

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 15:44
Öhm... entweder ick hab' dich jetz irjendwie nich so janz verstanden oder du mich net...

Die Region brauch ich ja aufjedenfall, damit ich die an das Fenster Handle übergebn kann! Und öhm... naja ob das jetzt pink is oder schwarz (wie ich das ja bei mir definiert hatte) spielt da ja nicht wirklich ne Rolle... ich muss so oder so aus diesem als Transparent definierten Bereich die Region herausfinden ob als Polygon oder durch meine Ausgrenzmethode...

*mal vorsichtig in Deckung geht nur falls ich jetz totalen Müll geredet hab*
I bin einfach mit der g'sammt Situation unzufrieden...
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#7

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 16:02
Vielleicht kommst Du auch mit GetRegionData() und ExCreateRegion() weiter.
Vorschlag: Region erstellen, mit GetData auslesen und in einem Stream ablegen. Einmal gemacht kannst Du dann mit ExCreateRegion die Region direkt erstellen.

MfG,
Tryer
  Mit Zitat antworten Zitat
Silenoz84

Registriert seit: 11. Mai 2004
Ort: Frankfurt
18 Beiträge
 
#8

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 17:53
hmmm... du könntest damit recht haben, so könnt's klappen... allerdings hab ich ja mal überhaupt keine Ahnung wie ich diese API verwende, denn um diese sch*** API Hilfe von Delphi verstehen zu können muss man Wissenschaftler sein, außerdem kommt dabei auch überhaupt nicht raus, als was die einzelnen Parameter deklariert sind bzw. deren Übergabewerte usw.!!!

Hab mir bis jetzt folgenden Code gebastelt:
Code:
...
var ...    
      rgnFinal: THandle;
      rgnData: PRgnData; //Ja, das funktioniert wirklich!!!
      rgnSize: Cardinal;
begin
  ...
  //Gibt als Rückgabewert die Größe der Region in Byte (soviel habe ich schonmal rausgefunden)
  rgnSize:= GetRegionData(rgnFinal,0,0);

  //Bekomme hier für rgnData wieder nur ein Zeiger auf ein Objekt, dessen Eigenschaft Buffer
  //laut Anleitung irgendwie als Array die Rechtecke beinhaltet, oder habe ich das komplett falsch
  //verstanden?
  GetRegionData(rgnFinal,rgnSize,rgnData);
  ...
end;
Entschuldige bitte meine heutige sehr niedrige Frustrationstoleranz... *hmpf*
I bin einfach mit der g'sammt Situation unzufrieden...
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#9

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 19:51
Der Ansatz ist richtig, Du ermittelst erstmal die Grösse des benötigten Buffers.

Als nächstes must Du dann einen Buffer mit der entsprechenden Grösse bereitstellen und einen Zeiger darauf übergeben.
Dieser Buffer wird dann von der Funktion mit den Daten gefüllt.

Wenn man das ganze als Datei speichern will, dann bietet sich z.B. ein TMemoryStream als Buffer an:
Delphi-Quellcode:
function SaveRgn(Rgn: HRgn; Filename: string): Boolean;
var
  RgnSize: Cardinal;
  MStream: TMemoryStream;
begin
  Result := False;
  MStream := TMemoryStream.Create;
  try
    RgnSize := GetRegionData(Rgn, 1, nil);
    if RgnSize > 0 then
    begin
      MStream.SetSize(RgnSize);
      if GetRegionData(Rgn, RgnSize, PRgnData(MStream.Memory)) = RgnSize then
      begin
        MStream.SaveToFile(Filename);
        Result := True;
      end;
    end;
  finally
    MStream.Free;
  end;
end;

function LoadRgn(AHandle: HWnd; Filename: string): Boolean;
var
  MStream: TMemoryStream;
  Rgn: HRgn;
begin
  Result := False;
  if not FileExists(Filename) then Exit;
  MStream := TMemoryStream.Create;
  try
    MStream.LoadFromFile(FileName);
    Rgn := ExtCreateRegion(nil, MStream.Size , TRgnData(MStream.Memory^));
    try
      if Rgn <> 0 then
        Result := SetWindowRgn(AHandle, Rgn, True) <> 0;
    finally
      DeleteObject(Rgn);
    end;
  finally
    MStream.Free;
  end;
end;
Mir schien es beim testen so das die Region nachdem sie mit SetWindowRgn auf ein Fenster übertragen wurde nicht mehr gültig ist, das speichern schlägt dann fehl. Du must die Region also vor der Zuweisung abspeichern.

MfG,
Tryer
  Mit Zitat antworten Zitat
Silenoz84

Registriert seit: 11. Mai 2004
Ort: Frankfurt
18 Beiträge
 
#10

Re: Region vom Typ THandle abspeichern

  Alt 11. Mai 2004, 22:44
Jiiieeeeehhhhaaaaaaa... *mal vor freude en Luftsprung und anschließend en dreifachen Rittberger macht* "ceeeeeeleeebrate good time, c'mon..." *tralala*

Hey ich dank dir echt für die Mühe die du dir gemacht hast, hast mir echt geholfen!!!
Dass eine Region nicht mehr verfügbar ist, nach der Übergabe an ein Fenster hatte mich auch schon genervt... naja egal... in deinem Code war übrigens noch en kleiner Bug drin (hat das bei dir keinen Fehler verursacht?):

Code:
...
       if GetRegionData(Rgn, RgnSize, PRgnData(MStream.Memory)) = 1 then
      //In der Hilfe steht "If the function fails, the return value is zero" d.h. wenn sie nicht
      //failed kommt irgendein anderer Wert raus aber nicht unbedingt 1 (bei mir zumindest nicht),
      //deshalb ist er auch nie in dieses If Anweisung gegangen... also hab ich die en bissl
      //umgeändert in:
      if GetRegionData(Rgn, RgnSize, PRgnData(MStream.Memory)) <> 0 then

...
So hab jetzt den Drang auch andern Leuten hier zu helfen, allerdings sind die anderen immer so wahnsinnig schnell mit ihren Antworten... lol


Also nochmal vielen dank! Sile

I bin einfach mit der g'sammt Situation unzufrieden...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 06:13 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