bugroger
asked on
Drawing a highlighted bitmap
I want to draw a highlighted bitmap like
the explorer when you select a item (with icon).
Does anyone knows how can i do that?
the explorer when you select a item (with icon).
Does anyone knows how can i do that?
Can you give me more details , please?
listening...
ASKER
more details:
ex.
When you click on an exe-file in the explorer
the text changed to clHighlightText/clhighligh t
and the icon from the exe-file will be displayed
darker.
How can I "convert" a normal icon/bitmap to such
a "darker" icon/bitmap?
ex.
When you click on an exe-file in the explorer
the text changed to clHighlightText/clhighligh
and the icon from the exe-file will be displayed
darker.
How can I "convert" a normal icon/bitmap to such
a "darker" icon/bitmap?
ASKER
I found the ImgList_DrawEx function.
With this function you can draw a "selcected Bitmap".
So you can write a function which convert a Bitmap to
a "darker" bitmap.
With this function you can draw a "selcected Bitmap".
So you can write a function which convert a Bitmap to
a "darker" bitmap.
hello bugroger, here is some code that I used to TRY to simulate the Icon hilighting used in windows explorer windows. This uses a PatBlt with the dwRop set to $A000C9, which might be undocumented, it is a pixel blending dwRop operation. I never got an exact match for the windows highlighting operation, but this was close enough for me to use as a visual image highlighting method.
private
bmp: TBitmap;
procedure TForm1.FormCreate(Sender: TObject);
var
i, k, Dot: Integer;
begin
{this creates a 8x8 bitmap for your Brush, I put it in create because I used this bmp many, many times}
bmp:= TBitmap.Create;
With bmp Do
Begin
width := 8;
height:= 8;
PixelFormat := pf24Bit;
Dot := 0;
for i:= 0 to 7 do
begin
for k:= 0 to 7 do
if ((k+ Dot) mod 2) <> 0 then
canvas.Pixels[k,i] := clSilver
else
canvas.Pixels[k,i] := GetSysColor(COLOR_HIGHLIGH T)};
{if you don't need the same color highlight as windows, you can try clGray here or your own color}
Inc(Dot)
end;
End;
end;
procedure TForm1.Button_HiLiteClick( Sender: TObject);
var
FirstPic: TBitmap;
begin
if OpenpictureDialog1.Execute then
begin
FirstPic := TBitmap.Create;
FirstPic.LoadFromFile(Open pictureDia log1.FileN ame);
{if the bitmap is not 24 Bit then colors will be blocky}
FirstPic.PixelFormat := pf24bit;
{set brush bitmap to the one you created}
FirstPic.Canvas.Brush.Bitm ap := bmp;
{you can try FirstPic.Canvas.Brush.Colo r := clHighlight ,
and you don't need the bmp or bitmap brush at all,
but this didn't look close enough to the windows highlight for me}
{this will blend the FirstPic with the bmp brush, and then it's ready to use}
PatBlt(FirstPic.Canvas.Han dle, 0, 0, FirstPic.Width, FirstPic.Height, $A000C9);
Canvas.Draw(0,0,FirstPic); // use bitmap
FirstPic.Free;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
bmp.Free;
end;
- - - - - - - - - - - - - - - - - - - - - -
there must be an undocumented dwRop for the windows highlighting operation, but I couldn't find it.
private
bmp: TBitmap;
procedure TForm1.FormCreate(Sender: TObject);
var
i, k, Dot: Integer;
begin
{this creates a 8x8 bitmap for your Brush, I put it in create because I used this bmp many, many times}
bmp:= TBitmap.Create;
With bmp Do
Begin
width := 8;
height:= 8;
PixelFormat := pf24Bit;
Dot := 0;
for i:= 0 to 7 do
begin
for k:= 0 to 7 do
if ((k+ Dot) mod 2) <> 0 then
canvas.Pixels[k,i] := clSilver
else
canvas.Pixels[k,i] := GetSysColor(COLOR_HIGHLIGH
{if you don't need the same color highlight as windows, you can try clGray here or your own color}
Inc(Dot)
end;
End;
end;
procedure TForm1.Button_HiLiteClick(
var
FirstPic: TBitmap;
begin
if OpenpictureDialog1.Execute
begin
FirstPic := TBitmap.Create;
FirstPic.LoadFromFile(Open
{if the bitmap is not 24 Bit then colors will be blocky}
FirstPic.PixelFormat := pf24bit;
{set brush bitmap to the one you created}
FirstPic.Canvas.Brush.Bitm
{you can try FirstPic.Canvas.Brush.Colo
and you don't need the bmp or bitmap brush at all,
but this didn't look close enough to the windows highlight for me}
{this will blend the FirstPic with the bmp brush, and then it's ready to use}
PatBlt(FirstPic.Canvas.Han
Canvas.Draw(0,0,FirstPic);
FirstPic.Free;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
bmp.Free;
end;
- - - - - - - - - - - - - - - - - - - - - -
there must be an undocumented dwRop for the windows highlighting operation, but I couldn't find it.
correction, I should have put this
for k:= 0 to 7 do
if ((k+ Dot) mod 2) <> 0 then
canvas.Pixels[k,i] := $00AAAAAA
else
canvas.Pixels[k,i] := clHightLight;
for k:= 0 to 7 do
if ((k+ Dot) mod 2) <> 0 then
canvas.Pixels[k,i] := $00AAAAAA
else
canvas.Pixels[k,i] := clHightLight;
ASKER
I have written my own function to highlight a bitmap.
I have used ALPHA-BLENDING to realized that.
NewRed = Rs*Sr+Rd*Dr
NewGreen = Gs*Sg+Gd*Dg
NewBlue = Bs*Sb+Bd*Db
NewFactor = As*Sa+Ad*Da
Rs=FactorSourceRed | Sr=SourceRed |
Rd=FactorDestRed | Dr=DestRed
Gs=FactorSourceGreen | Sg=SourceGreen |
Gd=FactorDestGreen | Dg=DestGreen
Bs=FactorSourceBlue | Sb=SourceBlue |
Bd=FactorDestBlue | Db=DestBlue
As=FactorSourceFactor | Sa=SourceFactor |
Ad=FactorDestFactor | Da=DestFactor
//Alpha 0.0 - 1.0
Procedure BlendWithColor(Src, Dest : TBitmap; BlendColor : TColor; Alpha : Real);
TYPE
TRGB = record
r, g, b, PALType : Byte;
end;
TpRGB = packed record
b, g, r : Byte;
end;
VAR
BlendColorChannels : TRGB;
DestRGBPixel : ^TpRGB;
SrcRGBPixel : ^TpRGB;
y, x : Integer;
SourceColorFaktor : real;
Begin
//Set BitPerPixel -> 24Bit
Src.PixelFormat := pf24Bit;
Dest.PixelFormat := pf24Bit;
Dest.Width := Src.Width;
Dest.Height := Src.Height;
//Get RGB-Channels from Color
BlendColorChannels := TRGB(BlendColor);
IF BlendColorChannels.PalType = 128 then
BlendColorChannels := TRGB(GetSysColor((BlendCol or AND $0000FFFF)));
//Get SourceColorFaktor
SourceColorFaktor := 1.0 - Alpha;
//Get all Pixels
For y := 0 to Dest.Height -1 do
Begin
//Get Pixel
SrcRGBPixel := Src.ScanLine[y];
DestRGBPixel := Dest.ScanLine[y];
For x := 0 to Dest.Width -1 do
Begin
DestRGBPixel.r := Round(SourceColorFaktor * SrcRGBPixel.r + Alpha * BlendColorChannels.r);
DestRGBPixel.g := Round(SourceColorFaktor * SrcRGBPixel.g + Alpha * BlendColorChannels.g);
DestRGBPixel.b := Round(SourceColorFaktor * SrcRGBPixel.b + Alpha * BlendColorChannels.b);
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
End;
End;
I have used ALPHA-BLENDING to realized that.
NewRed = Rs*Sr+Rd*Dr
NewGreen = Gs*Sg+Gd*Dg
NewBlue = Bs*Sb+Bd*Db
NewFactor = As*Sa+Ad*Da
Rs=FactorSourceRed | Sr=SourceRed |
Rd=FactorDestRed | Dr=DestRed
Gs=FactorSourceGreen | Sg=SourceGreen |
Gd=FactorDestGreen | Dg=DestGreen
Bs=FactorSourceBlue | Sb=SourceBlue |
Bd=FactorDestBlue | Db=DestBlue
As=FactorSourceFactor | Sa=SourceFactor |
Ad=FactorDestFactor | Da=DestFactor
//Alpha 0.0 - 1.0
Procedure BlendWithColor(Src, Dest : TBitmap; BlendColor : TColor; Alpha : Real);
TYPE
TRGB = record
r, g, b, PALType : Byte;
end;
TpRGB = packed record
b, g, r : Byte;
end;
VAR
BlendColorChannels : TRGB;
DestRGBPixel : ^TpRGB;
SrcRGBPixel : ^TpRGB;
y, x : Integer;
SourceColorFaktor : real;
Begin
//Set BitPerPixel -> 24Bit
Src.PixelFormat := pf24Bit;
Dest.PixelFormat := pf24Bit;
Dest.Width := Src.Width;
Dest.Height := Src.Height;
//Get RGB-Channels from Color
BlendColorChannels := TRGB(BlendColor);
IF BlendColorChannels.PalType
BlendColorChannels := TRGB(GetSysColor((BlendCol
//Get SourceColorFaktor
SourceColorFaktor := 1.0 - Alpha;
//Get all Pixels
For y := 0 to Dest.Height -1 do
Begin
//Get Pixel
SrcRGBPixel := Src.ScanLine[y];
DestRGBPixel := Dest.ScanLine[y];
For x := 0 to Dest.Width -1 do
Begin
DestRGBPixel.r := Round(SourceColorFaktor * SrcRGBPixel.r + Alpha * BlendColorChannels.r);
DestRGBPixel.g := Round(SourceColorFaktor * SrcRGBPixel.g + Alpha * BlendColorChannels.g);
DestRGBPixel.b := Round(SourceColorFaktor * SrcRGBPixel.b + Alpha * BlendColorChannels.b);
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
End;
End;
well bugroger, I like your code and it works real good, but its not an exact match for the windows icon highlighting effect, at least not on my puters. I got very close results with the alpha set to .61 - I added a line to help the highlighted look with dark colors
For x := 0 to Dest.Width -1 do
Begin
if SrcRGBPixel.r + SrcRGBPixel.g + SrcRGBPixel.b < 64 then
begin
DestRGBPixel.r := SrcRGBPixel.r;
DestRGBPixel.g := SrcRGBPixel.g;
DestRGBPixel.b := SrcRGBPixel.b;
end else
begin
DestRGBPixel.r := Round(SourceColorFaktor * SrcRGBPixel.r + Alpha * BlendColorChannels.r);
DestRGBPixel.g := Round(SourceColorFaktor * SrcRGBPixel.g + Alpha * BlendColorChannels.g);
DestRGBPixel.b := Round(SourceColorFaktor * SrcRGBPixel.b + Alpha * BlendColorChannels.b);
end;
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
- - - - - - -
good work
For x := 0 to Dest.Width -1 do
Begin
if SrcRGBPixel.r + SrcRGBPixel.g + SrcRGBPixel.b < 64 then
begin
DestRGBPixel.r := SrcRGBPixel.r;
DestRGBPixel.g := SrcRGBPixel.g;
DestRGBPixel.b := SrcRGBPixel.b;
end else
begin
DestRGBPixel.r := Round(SourceColorFaktor * SrcRGBPixel.r + Alpha * BlendColorChannels.r);
DestRGBPixel.g := Round(SourceColorFaktor * SrcRGBPixel.g + Alpha * BlendColorChannels.g);
DestRGBPixel.b := Round(SourceColorFaktor * SrcRGBPixel.b + Alpha * BlendColorChannels.b);
end;
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
- - - - - - -
good work
ASKER
Here is my new code to get an exact match
for the "windows icon highlighting effect."
I have used ROUND(INT(......))...
For y := 0 to Dest.Height -1 do
Begin
//Get Pixel
SrcRGBPixel := Src.ScanLine[y];
DestRGBPixel := Dest.ScanLine[y];
For x := 0 to Dest.Width -1 do
Begin
DestRGBPixel.r := ROUND(INT(SourceColorFakto r * SrcRGBPixel.r + BlendingColorFaktor * BlendColorChannels.r));
DestRGBPixel.g := ROUND(INT(SourceColorFakto r * SrcRGBPixel.g + BlendingColorFaktor * BlendColorChannels.g));
DestRGBPixel.b := ROUND(INT(SourceColorFakto r * SrcRGBPixel.b + BlendingColorFaktor * BlendColorChannels.b));
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
for the "windows icon highlighting effect."
I have used ROUND(INT(......))...
For y := 0 to Dest.Height -1 do
Begin
//Get Pixel
SrcRGBPixel := Src.ScanLine[y];
DestRGBPixel := Dest.ScanLine[y];
For x := 0 to Dest.Width -1 do
Begin
DestRGBPixel.r := ROUND(INT(SourceColorFakto
DestRGBPixel.g := ROUND(INT(SourceColorFakto
DestRGBPixel.b := ROUND(INT(SourceColorFakto
//Set Pointer to next Pixel
Inc(DestRGBPixel);
Inc(SrcRGBPixel);
End;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Actually, if you look very carefully at a "selected" icon you can see that it's just had a mask drawn over it like this:
* * * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * *
* * * * * * * *
where the spaces are transparent & the *'s are dark blue. You could (if you've already got the "checkerboard" mask) do this with a couple of blts:
bmp.canvas.copyMode := cmMergeCopy;
bmp.canvas.draw(0,0,mask_b mp);
bmp.canvas.copymode := cmMergePaint;
bmp.canvas.draw(0,0,mask_b mp);
GL
Mike
* * * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * *
* * * * * * * *
where the spaces are transparent & the *'s are dark blue. You could (if you've already got the "checkerboard" mask) do this with a couple of blts:
bmp.canvas.copyMode := cmMergeCopy;
bmp.canvas.draw(0,0,mask_b
bmp.canvas.copymode := cmMergePaint;
bmp.canvas.draw(0,0,mask_b
GL
Mike