Básicamente se trata de un botón con piel que resultará del uso de un bitmap que la dará la forma. Se requieren 2 bitmaps principales con el dibujo del botón en reposo y presionado, más dos bitmaps adicionales con ambos estados "luminosos", si queremos que al pasar por encima el cursor del ratón, muestre ese aspecto.
Por lo demás se trata de un botón delphi normal y corriente.
La magia gráfica se basa en el uso de regiones en Windows y la realiza esta función:
delphi
procedure SkinControl(Control: TWinControl; bmp: TBitmap); var TransparentColor: DWORD; rgn, rgnTemp: HRGN; ini, x, y: integer; Pixel: PADWord; begin bmp.HandleType:= bmDIB; bmp.PixelFormat:= pf32bit; Control.SetBounds(Control.Left, Control.Top, bmp.Width, bmp.Height); TransparentColor:= PADWord(bmp.ScanLine[bmp.Height-1])[0]; rgn:= CreateRectRgn(0, 0, Control.Width, Control.Height); CombineRgn(rgn, rgn, rgn, RGN_DIFF); for y:=0 to bmp.Height-1 do begin Pixel:= PADWord(bmp.ScanLine[y]); ini:= 0; for x:=0 to bmp.Width-1 do begin if pixel[x] <> TransparentColor then begin rgnTemp:= CreateRectRgn(ini, y, x, y+1); CombineRgn(rgn, rgn, rgnTemp, RGN_OR); DeleteObject(rgnTemp); ini:= x; end else inc(ini); end; end; SetWindowRgn(Control.Handle, rgn, true); DeleteObject(rgn); end;
Mientras que el cambio gráfico entre los estados, lo realiza esta otra:
delphi
procedure TSkinButton.CNDrawItem(var Message: TWMDrawItem); var Push: boolean; Bitmap: TBitmap; begin FCanvas.Handle:= Message.DrawItemStruct.hDC; FCanvas.Refresh(); if (csDesigning in ComponentState) then begin if fBmpUp.Empty then fBmpUp.LoadFromResourceName(HInstance, 'SKINBUTTON'); ActivateSkin; FCanvas.Draw(ClientRect.Left, ClientRect.Top, fBmpUp); exit; end; ActivateSkin; Push:= ((Message.DrawItemStruct.itemState and ODS_SELECTED)<>0) and ((Message.DrawItemStruct.itemAction and ODA_SELECT)<>0); if Enabled then begin if Push and (fAllowUp = false) then fDown:= fDown xor true else if fAllowUp then fDown:= Push; end; if fDown then // El botón está pulsado begin if fBmpDown.Empty = false then Bitmap:= fBmpDown else Bitmap:= fBmpUp; if Enabled and fHiLight and not fBmpDownHiLight.Empty then Bitmap:= fBmpDownHiLight; end else begin Bitmap:= fBmpUp; if Enabled and fHiLight and not fBmpUpHiLight.Empty then Bitmap:= fBmpUpHiLight; end; FCanvas.Draw(ClientRect.Left, ClientRect.Top, Bitmap); end;
Adjunto código del control, imagen y aplicación de ejemplo.
Saludos.