AW: Region vom Bitmap erstellen...
Niemand eine Idee? :cry:
gruss |
AW: Region vom Bitmap erstellen...
Ich dachte mal, daß ich da auch irgendwann einmal sowas gesehn hatte,
abr als ich letztens danach suchte, fand ich nur eine (etwas langsame) Funktion, welche das Bild Pixelweise auslas und dieses in eine Region eintrug. :shock: Wäre och gespannt, ob es dennoch was Besseres gibt. |
AW: Region vom Bitmap erstellen...
Wenn du mein projekt im vorherigen Thread mal laden würdest ;)
Button.rar. Grundsätzlich funktioniert das ja aber nur in der VCL mit einem TButton nicht in nonvcl. Das ist was mich stutzig macht. gruss |
AW: Region vom Bitmap erstellen...
Oh komma, hier gibt es ja nocheine Seite. :shock:
Na mal sehn ... vielleicht schau ich am WE nochmal rein. |
AW: Region vom Bitmap erstellen...
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:
Zitat:
Man muss die richtigen Window-Attribute setzen. ;) |
AW: Region vom Bitmap erstellen...
Zitat:
EDIT: Nur WS_CLIPSIBLINGS vergessen? EDIT2: Doch nicht so einfach.. hmmm Warum wird der Button trotzdem gedrückt obwohl ich im leeren bereich klicke? Es sieht also so aus das ich das Bitmap selbst auch noch ausschneiden muss. Was aber eigentlich wenn der bereich Transparent ist nicht nötig sein sollte. gruss Emil |
AW: Region vom Bitmap erstellen...
Will immer noch nicht so wie ich es will :)
Siehe Bild!
Delphi-Quellcode:
Ich erstelle ein HBitmap vom Bitmap
if Region > 0 then
begin Style := WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or BS_PUSHBUTTON; if ButID = ID_LED then Style := Style or WS_DISABLED; GdipLoadImageFromFile(PWideChar(FullPathImageName), img); GdipCreateHBITMAPFromBitmap(pointer(img), hbmReturn, $000000); if hbmReturn <> 0 then begin ABitmap := TBitmap.Create; ABitmap.Handle := hbmReturn; ABitmap.Width := btW; ABitmap.Height:= btH; FHImageButton := CreateWindowEx(WS_EX_TRANSPARENT, SKIMAGEBUTTON, '', Style, x, y, btW, btH, hOwner, ButID, SkinEngine.skInstance, nil); if FHImageButton <> 0 then begin SkinEngine.SetImageProperty(FHImageButton, PROP_IMAGE_BACK, Img); SkinEngine.SetImageProperty(FHImageButton, PROP_STYLE, BS_BITMAP); SkinEngine.SetImageProperty(FHImageButton, PROP_STATEMAX, StateMax); ARgn := RegionFromBitmap(ABitmap.Handle, $FF00FF); SetWindowRgn(FHImageButton, ARgn, true); ABitmap2 := TBitmap.Create; ABitmap2.Width := ImgW; ABitmap2.Height:= ImgH; ARgn2 := RegionFromBitmap(hbmReturn, $FF00FF); SetWindowRgn(ABitmap2.Handle, ARgn2, true); ABitmap2.Free; ABitmap.Free; end else begin // Lösche das Image SkinEngine.DeleteResource(hOwner, Img); end; end; end Danach jage ich ABitmap durch die Function RegionFromBitmap Der Button wird dann Ordnungsgemäß ausgeschnitten. Aber wie man sieht kann man immer noch den Bereich Magenta des Images sehen. Ich dachte eigentlich das der ausgeschnittene Bereich des Button wenn ein Image überlagert wird nicht mehr sichtbar sein sollte. Ist er aber... Nun gehe ich hin und erstelle eine zusätzliche Maske vom Image selbst das als Strip abgelegt ist und 2 Bilder in einem enthält. Down/Up Status.
Delphi-Quellcode:
Jetzt jage ich ABitmap2 ebenfalls durch diese Function.
function TSkinImageButton.RegionFromBitmap(hbmp: HBitmap;
TransColor: ColorRef): HRGN; type TRectArray = array[0..0] of TRect; var bm: Bitmap; pData: PRgnData; lpRect: PRect; hRgn2: HRGN; hRgn1: HRGN; sRegionData: THandle; MaxRegions: integer; I, J, K, M: integer; pr: ^TRectArray; p32: PByte; lPixel: PRGBQuad; begin hRgn1 := 0; lPixel := nil; GetObject(hbmp, SIZEOF(bm), @bm); if TransColor = 0 then TransColor := cardinal(lPixel) and $FFFFFF; MaxRegions := 4000; sRegionData := GlobalAlloc(GMEM_MOVEABLE, SizeOf(RGNDATAHEADER) + SizeOf(TRECT) * MaxRegions); pData := GlobalLock(sRegionData); pData^.rdh.nCount := 0; pData^.rdh.dwSize := sizeof(RGNDATAHEADER); pData^.rdh.iType := RDH_RECTANGLES; pData^.rdh.nRgnSize := 0; pData^.rdh.rcBound.Left := 0; pData^.rdh.rcBound.Top := 0; pData^.rdh.rcBound.Right := bm.bmWidth; pData^.rdh.rcBound.Bottom := bm.bmHeight; lpRect := PRECT(@pData^.Buffer); p32 := PByte(integer(bm.bmBits) + (bm.bmHeight - 1) * bm.bmWidthBytes); for J := 0 to bm.bmHeight - 1 do begin I := 0; while I < bm.bmWidth do begin M := I; lPixel := Pointer(integer(p32) + I * SizeOf(cardinal)); while I < bm.bmWidth do begin K := MakeColor(0, lPixel^.rgbRed, lPixel^.rgbGreen, lPixel^.rgbBlue) and $FFFFFF; if K <> integer(TransColor) then begin Inc(I); Inc(lPixel); end else Break; end; if I > M then begin if integer(pData^.rdh.nCount) >= MaxRegions then begin hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) + (sizeof(TRECT) * pData^.rdh.nCount), PRGNDATA(pData)^); if hRgn1 = 0 then begin hRgn1 := hRgn2; end else begin CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); SkinEngine.skDeleteObject(hRgn2); end; pData^.rdh.nCount := 0; end; pr := @pData^.Buffer; SetRect(pr^[pData^.rdh.nCount], M, J, I, J + 1); if M < lpRect.Left then lpRect.Left := M; if I > lpRect.Right then lpRect.Right := I; if J < lpRect.Top then lpRect.Top := J; if J > lpRect.Bottom then lpRect.Bottom := J + 1; Inc(pData^.rdh.nCount); Inc(lpRect); end; Inc(I); end; Dec(p32, bm.bmWidthBytes); end; hRgn2 := ExtCreateRegion(nil, sizeof(RGNDATAHEADER) + (sizeof(TRECT) * pData^.rdh.nCount), pData^); if hRgn1 = 0 then begin hRgn1 := hRgn2; end else begin CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); DeleteObject(hRgn2); end; GlobalFree(sRegionData); DeleteObject(hbmp); Result := hRgn1; end; Aber der Magenta bereich wird nicht ausgeschnitten bzw. das Bitmap nicht aktualisiert.
Delphi-Quellcode:
Ist das Handle vom ABitmap2 nicht gültig ?
ARgn2 := RegionFromBitmap(hbmReturn, $FF00FF);
SetWindowRgn(ABitmap2.Handle, ARgn2, true); Oder woran hapert es denn jetzt schon wieder. Kann zwar den Magenta Bereich mit den Halbton Button überlagern dann tritt aber das problem hier auf. Klicke ich die C Taste geht alles wunderbar wenn ich aber nach dem loslassen dann C# klicke und in dem Magentabereich der C Taste komme dann werden zwei Töne gleichzeitig gespielt. C+C# Puhh hoffe dass das noch jemand ließt. PS: Das Image transparent im bereich Magenta zu machen (müßte dann ein zusätzliches MaskImg anlegen um den Button auszuschneiden) bringt auch nichts. Auch hier werden 2 Tasten betätigt wenn ich auf den Transparenten bereich klicke (Das ist der aktuelle status was weg soll). gruss |
AW: Region vom Bitmap erstellen...
Es will einfach nicht.
Ich ersetze jetzt die Farbe mit
Delphi-Quellcode:
aber das Resultat ist das gleiche als wenn ich den bereich direkt Transparent mache im Bitmap selbst.
if SkinEngine.GetProperty(Winhandle, PROP_REGION) = 1 then
begin if GdipCreateImageAttributes(ImgAtt) = 0 then begin TransColor := SkinEngine.ColorARGB(255, RGB(255, 0, 255)); if GdipSetImageAttributesColorKeys(ImgAtt, ColorAdjustTypeDefault, True, 0, TransColor) = 0 then begin GdipDrawImageRectRectI(Graphics, Img, x, y, ImgW, ImgH, ImgW * cardinal(UseState) - ImgW, 0, ImgW, ImgH, 2, ImgAtt, False, nil) end; end; end else GdipDrawImageRectRectI(Graphics, Img, x, y, ImgW, ImgH, ImgW * cardinal(UseState) - ImgW, 0, ImgW, ImgH, 2, nil, False, nil); Warum läßt sich das Bitmap nicht ausschneiden? geht doch beim Button auch.. hmmm Oder ist es möglich das nach dem down status des Button die Region von diesen wieder auf default gesetzt wird? Sehen kann ich das nicht. Seltsamerweise Wenn ich noch keinen Button geklickt habe lassen sich keine zwei Button gleichzeitig drücken. gruss |
AW: Region vom Bitmap erstellen...
Warum heißt SetWindowRgn wohl SetWindowRgn?
Richtig, weil es für Fenster, sprich TWinControls funktioniert. Ein TBitmap.Handle hat nichts damit zu tun, ist nur "leider" zuweisungskompatibel da es halt auch eine einfache "Hausnummer" ist(LongWord). Nimm ein TWinControl (z.B. TPanel), packt das Image drauf und wende SetWindowRgn auf Panel.Handle an. Grüsse, Dirk |
AW: Region vom Bitmap erstellen...
Zitat:
Zeig mal wie du in einer Nonvcl Anwendung ein TPanel oder was auch immer deiner meinung nach dafür passt einbinden willst. Mein Problem mit dem Bitmap hab ich schon gelößt wie im vorherigen Beitrag mitgeteilt. GdipSetImageAttributesColorKeys Zitat:
Auch wenn es jetzt wieder transparent ist wird ein Klickevent auf dem Transparenten bereich ausgeführt. Hat mit dem Ausgeschnittenen Button nix zu tun das funktioniert nach nochmaligen testen. PS: Ach so das Panel auf einen Button knallen würde ja auch nicht gehn. So einfach ist es also nicht. gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:48 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