![]() |
Region vom Typ THandle abspeichern
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??? :wall: Hoffe irgendjemand konnte meinem verzweifeltem Versuch euch das Problem zu erklären folgen :gruebel: *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); ... |
Re: Region vom Typ THandle abspeichern
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! |
Re: Region vom Typ THandle abspeichern
@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:
würde man neu allerdings so definieren
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);
Delphi-Quellcode:
so funktioniert das ganze nicht mehr - leider :(
neu: array of TPoint;
begin setlength(neu, 9); |
Re: Region vom Typ THandle abspeichern
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... :kotz:
@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; |
Re: Region vom Typ THandle abspeichern
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
|
Re: Region vom Typ THandle abspeichern
Öhm... entweder ick hab' dich jetz irjendwie nich so janz verstanden oder du mich net... :gruebel:
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... :duck: *mal vorsichtig in Deckung geht nur falls ich jetz totalen Müll geredet hab* |
Re: Region vom Typ THandle abspeichern
Vielleicht kommst Du auch mit
![]() ![]() Vorschlag: Region erstellen, mit GetData auslesen und in einem Stream ablegen. Einmal gemacht kannst Du dann mit ExCreateRegion die Region direkt erstellen. MfG, Tryer |
Re: Region vom Typ THandle abspeichern
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.!!! :wall:
Hab mir bis jetzt folgenden Code gebastelt:
Code:
Entschuldige bitte meine heutige sehr niedrige Frustrationstoleranz... *hmpf*
...
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; |
Re: Region vom Typ THandle abspeichern
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:
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.
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; MfG, Tryer |
Re: Region vom Typ THandle abspeichern
:bounce2: Jiiieeeeehhhhaaaaaaa... *mal vor freude en Luftsprung und anschließend en dreifachen Rittberger macht* "ceeeeeeleeebrate good time, c'mon..." *tralala* :dancer:
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:
So hab jetzt den Drang auch andern Leuten hier zu helfen, allerdings sind die anderen immer so wahnsinnig schnell mit ihren Antworten... lol
...
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 ... Also nochmal vielen dank! Sile :-D :dp: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 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