Einzelnen Beitrag anzeigen

EWeiss
(Gast)

n/a Beiträge
 
#17

AW: Region vom Bitmap erstellen...

  Alt 1. Aug 2011, 02:31
Will immer noch nicht so wie ich es will

Siehe Bild!

Delphi-Quellcode:
      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
Ich erstelle ein HBitmap vom Bitmap
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:
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;
Jetzt jage ich ABitmap2 ebenfalls durch diese Function.
Aber der Magenta bereich wird nicht ausgeschnitten bzw. das Bitmap nicht aktualisiert.

Delphi-Quellcode:
ARgn2 := RegionFromBitmap(hbmReturn, $FF00FF);
SetWindowRgn(ABitmap2.Handle, ARgn2, true);
Ist das Handle vom ABitmap2 nicht gültig ?
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

Geändert von EWeiss (11. Jul 2019 um 16:40 Uhr)
  Mit Zitat antworten Zitat