Solved

Drawing a highlighted bitmap

Posted on 2001-06-04
11
327 Views
Last Modified: 2013-12-03
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?
0
Comment
Question by:bugroger
11 Comments
 
LVL 9

Expert Comment

by:ginsonic
ID: 6154938
Can you give me more details , please?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6155284
listening...
0
 
LVL 2

Author Comment

by:bugroger
ID: 6155371
more details:

ex.
 When you click on an exe-file in the explorer
 the text changed to clHighlightText/clhighlight
 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?


0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 2

Author Comment

by:bugroger
ID: 6155811
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.


0
 
LVL 33

Expert Comment

by:Slick812
ID: 6157531
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_HIGHLIGHT)};
{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(OpenpictureDialog1.FileName);
{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.Bitmap := bmp;

{you can try FirstPic.Canvas.Brush.Color := 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.Handle, 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.
0
 
LVL 33

Expert Comment

by:Slick812
ID: 6158116
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;
0
 
LVL 2

Author Comment

by:bugroger
ID: 6158859
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((BlendColor 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;
0
 
LVL 33

Expert Comment

by:Slick812
ID: 6162005
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
0
 
LVL 2

Author Comment

by:bugroger
ID: 6162936
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(SourceColorFaktor *     SrcRGBPixel.r  + BlendingColorFaktor *        BlendColorChannels.r));
    DestRGBPixel.g := ROUND(INT(SourceColorFaktor *      SrcRGBPixel.g  + BlendingColorFaktor *       BlendColorChannels.g));
    DestRGBPixel.b := ROUND(INT(SourceColorFaktor * SrcRGBPixel.b  + BlendingColorFaktor * BlendColorChannels.b));

   //Set Pointer to next Pixel
   Inc(DestRGBPixel);
   Inc(SrcRGBPixel);
  End;
 
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 100 total points
ID: 6165783
this looks like a match for me
 - - - - - -

var
Dot: Integer;

Dot := 0;
For x := 0 to Dest.Width -1 do
 Begin
  if ((x+ Dot) mod 2) = 0 then
  begin
  DestRGBPixel.r := Round(0.38 * SrcRGBPixel.r  + 0.4 * BlendColorChannels.r);
  DestRGBPixel.g := Round(0.38 * SrcRGBPixel.g  + 0.4 * BlendColorChannels.g);
  DestRGBPixel.b := Round(0.38 * SrcRGBPixel.b  + 0.4 * BlendColorChannels.b);
  end else
  begin
  DestRGBPixel.r := Round(0.38 * SrcRGBPixel.r  + 0.62 * BlendColorChannels.r);
  DestRGBPixel.g := Round(0.38 * SrcRGBPixel.g  + 0.62 * BlendColorChannels.g);
  DestRGBPixel.b := Round(0.38 * SrcRGBPixel.b  + 0.62 * BlendColorChannels.b);
  end;
  //Set Pointer to next Pixel
  Inc(DestRGBPixel);
  Inc(SrcRGBPixel);

 End;
 Inc(Dot);
End;
0
 
LVL 6

Expert Comment

by:edey
ID: 6484042
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_bmp);
bmp.canvas.copymode := cmMergePaint;
bmp.canvas.draw(0,0,mask_bmp);


GL
Mike
0

Featured Post

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

831 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question