Originalmente lo publiqué en delphi pero puede traducirse a C++, esta es la versión:
Crear la región para el Skin:
Código PHP:
void __fastcall SkinControl(TWinControl* Control, Graphics::TBitmap *bmp)
{
bmp->HandleType = bmDIB;
bmp->PixelFormat = pf32bit;
Control->SetBounds(Control->Left, Control->Top, bmp->Width, bmp->Height);
DWORD TransparentColor = static_cast<DWORD*>(bmp->ScanLine[bmp->Height-1])[0];
HRGN rgn, rgnTemp;
rgn = CreateRectRgn(0, 0, 0, 0);
for(int y=0; y<bmp->Height; ++y){
DWORD *pixel = static_cast<DWORD*>(bmp->ScanLine[y]);
for(int x=0, ini = 0; x<bmp->Width; ++x){
if(pixel[x] != TransparentColor){
rgnTemp = CreateRectRgn(ini, y, x, y+1);
CombineRgn(rgn, rgn, rgnTemp, RGN_OR);
DeleteObject(rgnTemp);
ini = x;
} else ini++;
}
}
SetWindowRgn(Control->Handle, rgn, true);
DeleteObject(rgn);
}
El cambio gráfico entre los estados:
Código PHP:
void __fastcall TSkinButton::CNDrawItem(TWMDrawItem& Message)
{
FCanvas->Handle = Message.DrawItemStruct->hDC;
FCanvas->Refresh();
if(ComponentState.Contains(csDesigning)){
if(fBmpUp->Empty)
fBmpUp->LoadFromResourceName((int)HInstance, "SKINBUTTON");
ActivateSkin();
FCanvas->Draw(ClientRect.left, ClientRect.top, fBmpUp);
return;
}
ActivateSkin();
bool Push = Message.DrawItemStruct->itemState & ODS_SELECTED;
if(Enabled){
if(Push && !fAllowUp){
fDown ^= true;
}
else if(fAllowUp){
fDown = Push;
}
}
FBitmap = fBmpUp;
if(fDown){ // El botón está pulsado
if(!fBmpDown->Empty) FBitmap = fBmpDown;
if(Enabled && fHiLight && !fBmpDownHiLight->Empty) FBitmap = fBmpDownHiLight;
}else{
FBitmap = fBmpUp;
if(Enabled && fHiLight && !fBmpUpHiLight->Empty) FBitmap = fBmpUpHiLight;
}
FCanvas->StretchDraw(ClientRect, FBitmap);
}
El código en C++ está
aquí.
Saludos.