[ Genesis @ 18.01.2005. 00:07 ] @
Hi !
Zanima me da li je moguće promjeniti standardni oblik delphi formi?
Kako je moguće učitati neku sliku koja bi mogla da bude umjesto standardne forme ?

Cao!
[ bancika @ 18.01.2005. 01:23 ] @
napravi u nekom programu slicicu kako hoces da ti izgleda forma i postavi boju pozadine koja hoces da ti bude transparentna. Obrati paznju da se ta boja ne javlja nigde drugde na formi jer ce delphi sve pixele te boje napraviti providnim. Najbolje je koristiti onu pedersku roze clFuschia jer nju sigurno neces da koristis (nadam se) u ostatku slike ili forme.
Sad tu sliku postavi u tImage i njega stavi preko cele forme, postavi svojstvo forme Style na fsNone (moze i ne mora), Transparent (valjda je tako) na True a TransparentColor na clFuschia. Pritisni F9 i probaj...
postoji i drugi nacin, ako ne zelis da se vidi ostatak slike koji nije transparentan...ak treba tu sam.

pozdrav
[ _v!rus_ @ 18.01.2005. 05:14 ] @
Ne mogu da verujem, toliko radim u delphiu i nisam znao da D6 native podrzava transparentne forme, mislio sam da treba da koristim neke hardcore API pozive za tako nesto...Extra...

Btw., radi li na non-NT platformama (95 :), 98, ME)?
[ dogriz @ 18.01.2005. 06:47 ] @
Ne radi na Win9x-ovima
[ bancika @ 18.01.2005. 11:35 ] @
probaj sledece:
ubaci proceduru
Code:

function TForm1.BitmapToRegion(bmp: TBitmap; TransparentColor: TColor=clBlack;
  RedTol: Byte=1; GreenTol: Byte=1; BlueTol: Byte=1): HRGN;
const
  AllocUnit = 100;
type
  PRectArray = ^TRectArray;
  TRectArray = Array[0..(MaxInt div SizeOf(TRect))-1] of TRect;
var
  pr: PRectArray;    // used to access the rects array of RgnData by index
  h: HRGN;           // Handles to regions
  RgnData: PRgnData; // Pointer to structure RGNDATA used to create regions
  lr, lg, lb, hr, hg, hb: Byte; // values for lowest and hightest trans. colors
  x,y, x0: Integer;  // coordinates of current rect of visible pixels
  b: PByteArray;     // used to easy the task of testing the byte pixels (R,G,B)
  ScanLinePtr: Pointer; // Pointer to current ScanLine being scanned
  ScanLineInc: Integer; // Offset to next bitmap scanline (can be negative)
  maxRects: Cardinal;   // Number of rects to realloc memory by chunks of AllocUnit
function min(a,b:integer):integer;
begin
 if a<b then Result:=a else Result:=b;
end;

begin
  Result := 0;
  { Keep on hand lowest and highest values for the "transparent" pixels }
  lr := GetRValue(TransparentColor); 
  lg := GetGValue(TransparentColor); 
  lb := GetBValue(TransparentColor); 
  hr := Min($ff, lr + RedTol);
  hg := Min($ff, lg + GreenTol); 
  hb := Min($ff, lb + BlueTol); 
  { ensures that the pixel format is 32-bits per pixel } 
  bmp.PixelFormat := pf32bit; 
  { alloc initial region data } 
  maxRects := AllocUnit; 
  GetMem(RgnData,SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * maxRects)); 
  try 
    with RgnData^.rdh do 
    begin 
      dwSize := SizeOf(RGNDATAHEADER); 
      iType := RDH_RECTANGLES; 
      nCount := 0;
      nRgnSize := 0; 
      SetRect(rcBound, MAXLONG, MAXLONG, 0, 0); 
    end; 
    { scan each bitmap row - the orientation doesn't matter (Bottom-up or not) } 
    ScanLinePtr := bmp.ScanLine[0]; 
    ScanLineInc := Integer(bmp.ScanLine[1]) - Integer(ScanLinePtr);
    for y := 0 to bmp.Height - 1 do 
    begin 
      x := 0; 
      while x < bmp.Width do 
      begin 
        x0 := x; 
        while x < bmp.Width do 
        begin 
          b := @PByteArray(ScanLinePtr)[x*SizeOf(TRGBQuad)]; 
          // BGR-RGB: Windows 32bpp BMPs are made of BGRa quads (not RGBa) 
          if (b[2] >= lr) and (b[2] <= hr) and 
             (b[1] >= lg) and (b[1] <= hg) and
             (b[0] >= lb) and (b[0] <= hb) then 
            Break; // pixel is transparent 
          Inc(x); 
        end; 
        { test to see if we have a non-transparent area in the image } 
        if x > x0 then
        begin 
          { increase RgnData by AllocUnit rects if we exceeds maxRects } 
          if RgnData^.rdh.nCount >= maxRects then 
          begin 
            Inc(maxRects,AllocUnit); 
            ReallocMem(RgnData,SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects)); 
          end; 
          { Add the rect (x0, y)-(x, y+1) as a new visible area in the region } 
          pr := @RgnData^.Buffer; // Buffer is an array of rects 
          with RgnData^.rdh do 
          begin 
            SetRect(pr[nCount], x0, y, x, y+1);
            { adjust the bound rectangle of the region if we are "out-of-bounds" } 
            if x0 < rcBound.Left then rcBound.Left := x0; 
            if y < rcBound.Top then rcBound.Top := y; 
            if x > rcBound.Right then rcBound.Right := x; 
            if y+1 > rcBound.Bottom then rcBound.Bottom := y+1; 
            Inc(nCount);
          end; 
        end; // if x > x0 
        { Need to create the region by muliple calls to ExtCreateRegion, 'cause } 
        { it will fail on Windows 98 if the number of rectangles is too large   } 
        if RgnData^.rdh.nCount = 2000 then 
        begin 
          h := ExtCreateRegion(nil, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * maxRects), RgnData^); 
          if Result > 0 then 
          begin // Expand the current region 
            CombineRgn(Result, Result, h, RGN_OR); 
            DeleteObject(h); 
          end
          else  // First region, assign it to Result 
            Result := h; 
          RgnData^.rdh.nCount := 0; 
          SetRect(RgnData^.rdh.rcBound, MAXLONG, MAXLONG, 0, 0); 
        end; 
        Inc(x);
      end; // scan every sample byte of the image 
      Inc(Integer(ScanLinePtr), ScanLineInc); 
    end; 
    { need to call ExCreateRegion one more time because we could have left    } 
    { a RgnData with less than 2000 rects, so it wasn't yet created/combined  } 
    h := ExtCreateRegion(nil, SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects), RgnData^); 
    if Result > 0 then 
    begin 
      CombineRgn(Result, Result, h, RGN_OR); 
      DeleteObject(h); 
    end 
    else
      Result := h; 
  finally 
    FreeMem(RgnData,SizeOf(RGNDATAHEADER) + (SizeOf(TRect) * MaxRects));
  end; 
end; 


i u OnCreate forme stavi:
Code:

var Rgn:Hrgn;
begin
  rgn:=BitmapToRegion(Image1.Picture.Bitmap, clFuschia);
  SetWindowRgn(handle,Rgn,false);


to daje slican efekat, samo mislim da je brze od onog delphi-jevog jer se sa ovim ne desava da forma "zablinka" kada se pokaze, nego je odmah cool. cak *mozda* i radi pod 9x...onaj drugi metod sigurno ne.
[ _v!rus_ @ 19.01.2005. 01:11 ] @
Znao sam da ima neki zez sa API-jem :)
Trebalo bi da radi posto se svi 32-bit windowsi oslanjaju na regione za definiciju izgleda prozora. Moram da probam da li radi mozda @real-time (ako bi vise puta pozvao SetWindowRgn u nekom timeru, da li bi mogao da menjam oblik forme u toku rada aplikacije, interesantno za desktop applete kao npr. bancikin merac kilometraze misa).
[ bancika @ 19.01.2005. 02:00 ] @
moze real-time. nemoj da ocekujes previse ali par fps-ova je sasvim izvodljivo. ne mozes da pravis sexy dancere, ali za neke satove ili slicno je odlicno :)
pozdrav
[ Nemanja Avramović @ 19.01.2005. 11:16 ] @
na drugom disku delphija 6 enterprise se dobija dxfforumlibrary i tu ima jedna komponenta koja moze da "isece" form po slici i u win9x
[ bancika @ 19.01.2005. 12:39 ] @
verovatno moze i ovo zadnje sto sam dao...to sam koristio u proslom veku, tad nije bilo winXP-a :)