How to make text glow - delphi

Having my self-written button control (TMyButton) derived from TCustomControl I want to add an ability to make glow effect for MyButton's caption. After long time in Goolge I understood that the best way to create glow is to draw text with specify color, then blurring all - text and surface on which it is lies, and then draw text again. It will works perfectly only if surface is solid, e.g. fills with red color.
I have created procedure that make Bitmap blurred, but my button can have non-solid background, e.g bitmap which can be filled gradient. If I will blur that background it became very awful, but glow looks nice.
I suggest that this task could be solved by using Scanline, but I have no idea what exactly I should do with it.
If use solid fill I have this (filled with clWhite):
If use bitmap fill I have this ("Text" has clBlack shadow):
That is how looks blurred bitmap shown above, without blur:
Does anybody has any idea how to make glow effect for text without blurring a result bitmap?
P.S.
code to blur bitmap
procedure DrawBlurEffect(BmpInOut: TBitmap; Radius: Integer);
var
A, B, C, D: PRGBArray;
x, y, i: Integer;
begin
BmpInOut.PixelFormat := pf24bit;
for i:=0 to Radius do
begin
for y:=2 to BmpInOut.Height - 2 do
begin
A := BmpInOut.ScanLine[y-1];
B := BmpInOut.ScanLine[y];
C := BmpInOut.ScanLine[y+1];
D := BmpInOut.ScanLine[y];
for x:=1 to BmpInOut.Width - 2 do
begin
B[x].Red := Trunc(C[x].Red + A[x].Red + B[x-1].Red + D[x+1].Red) div 4;
B[x].Green := Trunc(C[x].Green + A[x].Green + B[x-1].Green + D[x+1].Green) div 4;
B[x].Blue := Trunc(C[x].Blue + A[x].Blue + B[x-1].Blue + D[x+1].Blue) div 4;
end;
end;
end;
end;

Draw text on the glass (vista and above) using DrawThemeTextEx with set DTTOPT glow flag.
uses Types, UxTheme, Themes, Graphics;
procedure DrawGlassText(Canvas: TCanvas; GlowSize: Integer; var Rect: TRect;
var Text: UnicodeString; Format: DWORD); overload;
var
DTTOpts: TDTTOpts;
begin
if Win32MajorVersion < 6 then
begin
DrawTextW(Canvas.Handle, PWideChar(Text), Length(Text), Rect, Format);
Exit;
end;
ZeroMemory(#DTTOpts, SizeOf(DTTOpts));
DTTOpts.dwSize := SizeOf(DTTOpts);
DTTOpts.dwFlags := DTT_COMPOSITED or DTT_TEXTCOLOR;
if Format and DT_CALCRECT = DT_CALCRECT then
DTTOpts.dwFlags := DTTOpts.dwFlags or DTT_CALCRECT;
DTTOpts.crText := ColorToRGB(Canvas.Font.Color);
if GlowSize > 0 then
begin
DTTOpts.dwFlags := DTTOpts.dwFlags or DTT_GLOWSIZE;
DTTOpts.iGlowSize := GlowSize;
end;
with ThemeServices.GetElementDetails(teEditTextNormal) do
DrawThemeTextEx(ThemeServices.Theme[teEdit], Canvas.Handle, Part, State,
PWideChar(Text), Length(Text), Format, #Rect, DTTOpts);
end;
There is TransparentCanvas that can be used to set glow color.
As a funfact :). I remember, that some components (d2) to mimic glow-effect, used simple (poor) technique - text behind with specific glow color - shadow.
procedure TExampleGlowLabel.DoDrawText( var Rect : TRect; Flags : Word );
var
Text : array[ 0..255 ] of Char;
TmpRect : TRect;
begin
GetTextBuf(Text, SizeOf(Text));
if ( Flags and DT_CALCRECT <> 0) and
( ( Text[0] = #0 ) or ShowAccelChar and
( Text[0] = '&' ) and
( Text[1] = #0 ) ) then
StrCopy(Text, ' ');
if not ShowAccelChar then
Flags := Flags or DT_NOPREFIX;
Canvas.Font := Font;
if FGlowing and Enabled then
begin
TmpRect := Rect;
OffsetRect( TmpRect, 1, 1 );
Canvas.Font.Color := GlowColor;
DrawText(Canvas.Handle, Text, StrLen(Text), TmpRect, Flags);
TmpRect := Rect;
OffsetRect( TmpRect, -1, -1 );
Canvas.Font.Color := GlowColor;
DrawText(Canvas.Handle, Text, StrLen(Text), TmpRect, Flags);
TmpRect := Rect;
OffsetRect( TmpRect, -1, 1 );
Canvas.Font.Color := GlowColor;
DrawText(Canvas.Handle, Text, StrLen(Text), TmpRect, Flags);
TmpRect := Rect;
OffsetRect( TmpRect, 1, -1 );
Canvas.Font.Color := GlowColor;
DrawText(Canvas.Handle, Text, StrLen(Text), TmpRect, Flags);
end;
Canvas.Font.Color := Font.Color;
if not Enabled then
Canvas.Font.Color := clGrayText;
DrawText(Canvas.Handle, Text, StrLen(Text), Rect, Flags);
end;
As mentioned in comment TButton with transparent PNG image and glowing hover effect has answer with some non-free components.
edit
Different approach would be to use FireMonkey Effects (really cool) TGlowEffect, but probably, it applies to whole canvas.

Related

Combination of Canvas.TransparentColor and Canvas.Draw with Opacity

i want to draw a bitmap on a canvas with opacity where the bitmap has a transparent color.
i could create a bitmap with transparent color and draw it to a
canvas i could create a bitmap and draw it to a canvas with opacity
but i couldn't combine it. if i combine it the opacity is ignored.
here is the code i wrote:
procedure TForm1.FormPaint(Sender: TObject);
var b1,b2:TBitmap;
begin
// Example how it opacity works:
b1 := TBitmap.Create;
b1.SetSize(20,20);
b1.Canvas.Brush.Color := clBlue;
b1.Canvas.Rectangle(0,0,20,20);
Canvas.Draw(10,10,b1,$ff); // Works
Canvas.Draw(40,10,b1,$66); // Works
// I need it in combination with TransparentColor:
b2 := TBitmap.Create;
// next 3 lines are different from above
b2.Transparent := true;
b2.TransparentColor := clFuchsia;
b2.Canvas.Brush.Color := clFuchsia;
b2.SetSize(20,20);
b2.Canvas.Brush.Color := clBlue;
b2.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,40,b2,$ff); // Works (full opacity)
Canvas.Draw(40,40,b2,$66); // Ignores the $66 Opacity
b1.Free;
b2.Free;
end;
produces:
how could i draw (f.e. a blue circle) with transparent background and just 40% opacity?
i would prefere a solution without direct winapi (like bitblt, ...) if possible.
i tried a few hacks like bitshifting a alpha channel to a TColor value but it didn't work.
here i what i tried:
procedure TForm1.FormPaint(Sender: TObject);
var b:TBitmap;
begin
b := TBitmap.Create;
b.PixelFormat := pf32bit;
b.AlphaFormat := afDefined;
b.Canvas.Brush.Color := 0 and ($ff shl 32); // Background Transperency
b.SetSize(20,20);
b.Canvas.Brush.Color := clBlue + (($ff-$66) shl 32);
b.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,10,b);
b.Free;
end;
produces:
thanks in advance!
EDIT: my system: delphi xe 5 on windows 7 64bit (but using the 32bit compiler)
What happens can be seen in procedure TBitmap.DrawTransparent in the unit Graphics.
If the property of the image is set to transparent as show for b2 in your example the Bitmap will be drawn with
Graphics.TransparentStretchBlt which is using StretchBlt with differnt masks to draw the image and is not able to use the alpha channel.
A not tranparent Bitmap , your b1, will be draw with
AlphaBlend.
To reach your goal you might use another bitmap b2, set the Alphachannel to 0, paint b2 with opacity $66 on b3, set set the Alphachannel to 255 for every pixel which is clFuchsia in b2 and then paint this bitmap with the desired opacity
type
pRGBQuadArray = ^TRGBQuadArray;
TRGBQuadArray = ARRAY [0 .. 0] OF TRGBQuad;
TRefChanel=(rcBlue,rcRed,rcGreen);
procedure SetBitmapAlpha(ABitmap: TBitMap; Alpha: Byte);
var
pscanLine32: pRGBQuadArray;
nScanLineCount, nPixelCount : Integer;
begin
with ABitmap do
begin
PixelFormat := pf32Bit;
HandleType := bmDIB;
ignorepalette := true;
alphaformat := afDefined;
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32 := Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
with pscanLine32[nPixelCount] do
begin
rgbReserved := Alpha;
end;
end;
end;
end;
procedure AdaptBitmapAlpha(ABitmap,TranspBitmap:TBitmap);
var
pscanLine32,pscanLine32_2: pRGBQuadArray;
nScanLineCount, nPixelCount : Integer;
begin
with ABitmap do
begin
PixelFormat := pf32Bit;
HandleType := bmDIB;
ignorepalette := true;
alphaformat := afDefined;
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32 := Scanline[nScanLineCount];
pscanLine32_2 := TranspBitmap.Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
with pscanLine32[nPixelCount] do
begin
// all picels with are not clFuchsia in the transparent bitmap
if NOT ((pscanLine32_2[nPixelCount].rgbBlue=255) AND (pscanLine32_2[nPixelCount].rgbRed=255) AND (pscanLine32_2[nPixelCount].rgbGreen=0) ) then
begin
rgbReserved := 255;
end
else
begin
rgbBlue := 0;
rgbRed := 0;
rgbGreen := 0;
end;
end;
end;
end;
end;
procedure TAForm.FormPaint(Sender: TObject);
var b1,b2,b3:TBitmap;
BF: TBlendFunction;
begin
// Example how it opacity works:
b1 := TBitmap.Create;
b1.SetSize(20,20);
b1.Canvas.Brush.Color := clBlue;
b1.Canvas.Rectangle(0,0,20,20);
Canvas.Draw(10,10,b1,$ff); // Works
Canvas.Draw(40,10,b1,$66); // Works
// I need it in combination with TransparentColor:
b3 := TBitmap.Create;
b3.PixelFormat := pf32Bit;
b2 := TBitmap.Create;
b2.PixelFormat := pf32Bit;
// next 3 lines are different from above
b2.Transparent := true;
b2.TransparentColor := clFuchsia;
b2.Canvas.Brush.Color := clFuchsia;
b2.SetSize(20,20);
b2.Canvas.Brush.Color := clBlue;
b2.Canvas.Ellipse(0,0,20,20);
Canvas.Draw(10,40,b2,$ff); // Works (full opacity)
b3.SetSize(20,20);
SetBitmapAlpha(b3,0);
b3.Canvas.Draw(0,0,b2,$66);
AdaptBitmapAlpha(b3,b2);
Canvas.Draw(40,40,b3,$66);
b1.Free;
b2.Free;
b3.Free;
end;
thanks to bummi (accepted answer)!
i put his solution in a class helper. here is the code if anybody need it:
unit uBitmapHelper;
interface
uses
Vcl.Graphics;
type
TBitmapHelper = class Helper for TBitmap
private
type
TRgbaRec = packed record
r,g,b,a:Byte;
end;
PRgbaRec = ^TRgbaRec;
PRgbaRecArray = ^TRgbaRecArray;
TRgbaRecArray = array [0 .. 0] of TRgbaRec;
public
procedure TransparentMaskedDraw(ACanvas:TCanvas;AX:Integer;AY:Integer;AMask:TColor;AOpacity:Byte);
end;
implementation
{ TBitmapHelper }
procedure TBitmapHelper.TransparentMaskedDraw(ACanvas:TCanvas;AX,AY:Integer;AMask:TColor;AOpacity:Byte);
var i,j:Integer;
line1,line2:PRgbaRecArray;
mask:PRgbaRec;
tmp:TBitmap;
begin
mask := #AMask;
tmp := TBitmap.Create;
tmp.SetSize(self.Width,self.Height);
tmp.PixelFormat := pf32Bit;
tmp.HandleType := bmDIB;
tmp.IgnorePalette := true;
tmp.AlphaFormat := afDefined;
for i := 0 to tmp.Height - 1 do begin
line1 := tmp.Scanline[i];
for j := 0 to tmp.Width - 1 do begin
line1[j].a := 0;
end;
end;
tmp.Canvas.Draw(0,0,self,AOpacity);
for i := 0 to tmp.Height - 1 do begin
line1 := tmp.ScanLine[i];
line2 := self.ScanLine[i];
for j := 0 to tmp.Width - 1 do begin
if not((line2[j].r = mask.r) and (line2[j].g = mask.g) and (line2[j].b = mask.b)) then begin
line1[j].a := $ff;
end else begin
line1[j].r := 0;
line1[j].g := 0;
line1[j].b := 0;
end;
end;
end;
ACanvas.Draw(AX,AY,tmp,AOpacity);
tmp.Free;
end;
end.
The oldest answer is fine, please find some easy reshuffle.
This example also shows how to put one png-image with opacity on another by respecting the transparency.
procedure TForm2.FormCreate(Sender: TObject);
//define your own transparent color by setting RGB-values
const cTransR=255; cTransG=255; cTransB=255;
clTrans= $10000*cTransB + $100*cTransG + cTransR;
var bmp1,bmp2:TBitmap;
pngTemp: TPngImage;
I:integer;
procedure SetAlphaTransparent(VAR LBitmap:TBitmap);
type TRGBQuadArray = ARRAY [0..0] OF TRGBQuad;
var I, J: integer;
LscanLine32:^TRGBQuadArray;
begin
// I found no other way than scanning pixel by pixel to recover default opacity
for I := 0 to LBitmap.Height - 1 do begin
LscanLine32:=LBitmap.ScanLine[I];
for J := 0 to LBitmap.Width - 1 do
with LscanLine32[J] do
if NOT((rgbRed=cTransR)AND(rgbGreen=cTransG)AND(rgbBlue=cTransB)) then
rgbReserved := 255; // make pixel visible, since transparent is default
end;
end;
Procedure SetAlphaProperty(Var LBitmap:TBitmap; LWidth, LHeight:integer);
begin
// You will need a different format Bitmap to allow alpha values
LBitmap.PixelFormat := pf32Bit;
LBitmap.HandleType := bmDIB;
LBitmap.alphaformat := afDefined;
LBitmap.Canvas.Brush.Color := clTrans;
LBitmap.SetSize(LWidth,LHeight);
end;
begin
// create any background on your Form, by placing IMG:Timage on the From
pngTemp := TPngImage.Create;
pngTemp.LoadFromFile( GetCurrentDir()+'\figure1.png' );
IMG.Canvas.Draw((IMG.Width-pngTemp.Width) div 2, // fit png into the center
(IMG.Height-pngTemp.Height) div 2,pngTemp);
pngTemp.Free;
// First example how it opacity works with transparency
bmp1 := TBitmap.Create;
SetAlphaProperty(bmp1,35,35);
// a circle has a surrouding area, to make transparent
bmp1.Canvas.Brush.Color := clBlue;
bmp1.Canvas.Ellipse(5,5,30,30);
SetAlphaTransparent(bmp1);
// show some circles with different opacity
for I := 0 to 7 do
IMG.Canvas.Draw(I*40-30,10,bmp1,(8-I)*32);
bmp1.Free;
// Another example using a different png-file
bmp2 := TBitmap.Create;
SetAlphaProperty(bmp2,Img.Width,Img.Height);
// load a transparent png-file and put it into the alpha bitmap:
pngTemp := TPngImage.Create;
pngTemp.LoadFromFile( GetCurrentDir()+'\figure2.png' );
pngTemp.Transparent := true;
bmp2.Canvas.Draw((bmp2.Width-pngTemp.Width) div 2,// fit png into the center
(bmp2.Height-pngTemp.Height) div 2,pngTemp);
pngTemp.Free;
// draw the second image with transparancy and opacity onto the first one
SetAlphaTransparent(bmp2);
IMG.Canvas.Draw(0,0,bmp2,$66);
bmp2.Free;
end;

How to draw a solid color bitmap with a Text Centered?

The code below should be creating a bitmap that is a 48x48 rectangle, of blue background color and a Text (actually just a letter) centered horizontally and vertically of white color.
However nothing happens.
procedure MakeCustomIcon(AText: string; AWidth: Integer; AHeight: Integer; AColor: TAlphaColor; var ABlob: TBlob);
var
Bitmap: TBitmap;
Rect: TRectF;
InStream: TMemoryStream;
begin
Bitmap := TBitmap.Create;
InStream := TMemoryStream.Create;
try
Bitmap.SetSize(AWidth, AHeight);
Bitmap.Canvas.Clear(AColor);
Bitmap.Canvas.Stroke.Kind := TBrushKind.bkSolid;
Bitmap.Canvas.StrokeThickness := 1;
Bitmap.Canvas.Fill.Color := TAlphaColorRec.White;
Bitmap.Canvas.BeginScene;
Rect.Create(0, 0, AWidth, AHeight);
Bitmap.Canvas.FillText(Rect, AText, true, 100, [TFillTextFlag.ftRightToLeft], TTextAlign.taCenter, TTextAlign.taCenter);
Bitmap.Canvas.EndScene;
Bitmap.SaveToStream(InStream);
InStream.Position := 0;
ABlob.Clear;
ABlob.LoadFromStream(InStream);
finally
Bitmap.Free;
InStream.Free;
end;
I have tested the rest of my program to make sure the image (that Blob) is actually transporting and getting displayed, and it is doing so. The problem is fully contained on the way it is drawn the bitmap on the method above.
This TBlob is an array of byte.
I am looking to do rectangles like this below, to be used in TListView:
I have prepared a project.
1-) Write Text on TImage
2-) Draw on TImage
3-) Effect to TImage
I Try on XE5
Samples:
procedure ReDraw(Image: TImage);
var
MyRect: TRectF;
begin
if Image.Bitmap.IsEmpty then Exit;
MyRect := TRectF.Create(0, Ozellik.SeritTop, Image.Bitmap.Width, Ozellik.SeritBot);
with Image.Bitmap.Canvas do
begin
BeginScene;
if not Seffaf.IsChecked then
Fill.Color := Ozellik.SeritRenk
else
Fill.Color := TAlphaColorRec.Null;
FillRect(MyRect, 0, 0, [], 1);
Fill.Color := Ozellik.YaziRenk;
if FontCombo.ItemIndex <> -1 then
Font.Family := FontCombo.Items[FontCombo.ItemIndex];
Font.Size := Ozellik.YaziBoyut;
FillText(MyRect,FonYazi.Text.Trim,True,1,[],TTextAlign.taCenter,TTextAlign.taCenter);
EndScene;
end;
Image.Repaint;
end;
http://www.dosya.tc/server32/vHsbaC/CapsYapMasa_st_.rar.html
All canvas drawings must be grouped into a BeginScene/EndScene block. Also, it is recommended to draw within a try-finally block.
So, instead of
Bitmap.Canvas.Clear(AColor);
...
Bitmap.Canvas.BeginScene;
...
Bitmap.Canvas.EndScene;
you should do:
Bitmap.Canvas.BeginScene;
try
Bitmap.Canvas.Clear(AColor);
...
finally
Bitmap.Canvas.EndScene;
end;
-- Regards

Display extra text in treeview nodes, not just node.text

I have a TTreeView in Delphi, with nodes at three levels.
I use node data to store another label besides the node text.
Type
TNodeData = class
ExtraNodeLabel: WideString;
//... other members
end;
I have an OnAdvancedCustomDrawItem event, where i want to display this ExtraNodeLabel before the node text.
I wish to achieve this:
The blue text would be the extra label.
higlighted item: first two words are also an extra label
What i got so far, is this:
Problems:
For some reason i can't draw text with different style if i use DrawText/drawTextW (I need drawtextW because of unicode data)
The other problem is, that anything outside the dotted focus rectangle is unclickable
What needs to be solved:
How can i draw text with different style using DrawText/DrawtextW
How can i make the whole text clickable?
Code:
procedure TMainForm.TntTreeView1AdvancedCustomDrawItem(
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
var
txtrect, fullrect : TRect;
DC: HDC;
fs: integer;
fc: TColor;
ExtralabelRect: TRect;
nData: TNodeData;
begin
nData := nil;
if assigned(Node.Data) then begin
nData := TNodeData(Node.Data);
end;
DC := TntTreeView1.canvas.Handle;
txtRect := Node.DisplayRect(True);
fullrect := Node.DisplayRect(False);
if stage = cdPostPaint then begin
TntTreeView1.Canvas.FillRect(txtRect);
if (cdsFocused In State) And (cdsSelected in State) then begin
DrawFocusRect(DC,txtRect);
end;
txtRect.Left := txtRect.Left + 1;
txtRect.Top := txtRect.Top + 1;
txtRect.Right := txtRect.Right - 1;
txtRect.Bottom := txtRect.Bottom - 1;
ExtralabelRect := txtRect;
fs := TntTreeView1.Canvas.Font.size;
fc := TntTreeView1.Canvas.Font.Color;
if (nData <> nil) And (nData.ExtraNodeLabel <> '') then begin
TntTreeView1.Canvas.Font.Size := 7;
TntTreeView1.Canvas.Font.color := clBlue;
DrawTextW(
DC,
PWideChar(nData.ExtraNodeLabel),
Length(nData.ExtraNodeLabel),
ExtraLabelRect,
DT_LEFT or DT_CALCRECT or DT_VCENTER
);
DrawTextW(
DC,
PWideChar(nData.ExtraNodeLabel),
Length(nData.ExtraNodeLabel),
ExtraLabelRect,
DT_LEFT or DT_VCENTER
);
txtRect.right := txtRect.Right + ExtraLabelRect.Right + 5;
txtRect.Left := ExtraLabelRect.Right + 5;
end;
TntTreeView1.Canvas.Font.Size := fs;
TntTreeView1.Canvas.Font.color := fc;
DrawTextW(
DC,
PWideChar((Node as TTntTreeNode).Text),
-1,
txtRect,
DT_LEFT or DT_VCENTER
);
end;
end;
Solution by the OP
I managed to partially solve custom drawing, by defining a TFont variable, and using SelectObject and setTextColor. Setting font color and style works, but setting the font size doesn't.
var
nFont: TFont;
begin
DC := TntTreeView1.Canvas.Handle;
NFont := TFont.Create;
// rest of the code here ...
// i tried to set nFont.Size, but it doesn't seem to work
nFont.Size := 7;
nFont.Color := colorToRGB(clBlue);
nFont.Style := TntTreeview1.Font.Style + [fsBold];
SelectObject(DC,NFont.Handle);
SetTextColor(DC,colortoRGB(clBlue));
DrawTextW(
DC,
PWideChar(nData.nodeLabel),
Length(nData.nodeLabel),
ExtraLabelRect,
DT_LEFT or DT_VCENTER
);
// rest of the code here
end;
Source:
I used the idea from here
Update 2
I solved the second problem by setting the treeview's RowSelect property to true.
For this, to work, i had to set the ShowLines property to false, and custom draw the lines and the buttons. It works now.
Update 3
I improved the solution for the first problem, by not creating a new font, but selecting the canvas font for displaying text, and this way i was able to change any aspect of the font, and the system cleartype settings are also applied:
// set font size for the canvas font (font style can be set the same time)
TntTreeView1.Canvas.Font.Size := 7;
// select canvas font for DC
SelectObject(DC,TntTreeView1.Canvas.Font.Handle);
// set font color
SetTextColor(DC,colortoRGB(clBlue));

Create an image and colored ir?

how can I create an image and how can I colored it pixel by pixel using hexadecimal code of colors?
For ex. I wanna create a 100x100 pixel image and I wanto to 1x1 area's color is '$002125',2x2 area's color is '$125487'.... How can I do it?
Thank you for your answers..
Made a simple sample for you. Using Canvas.Pixels not Scanline. Scanline is faster though but for start I think it suits just fine. The colors are randomly generated, so you just need to replace this part of the code.
procedure TForm1.GenerateImageWithRandomColors;
var
Bitmap: TBitmap;
I, J: Integer;
ColorHEX: string;
begin
Bitmap := TBitmap.Create;
Randomize;
try
Bitmap.PixelFormat := pf24bit;
Bitmap.Width := 100;
Bitmap.Height := 100;
for I := 0 to Pred(Bitmap.Width) do
begin
for J := 0 to Pred(Bitmap.Height) do
begin
Bitmap.Canvas.Pixels[I, J] := RGB(Random(256),
Random(256),
Random(256));
// get the HEX value of color and do something with it
ColorHEX := ColorToHex(Bitmap.Canvas.Pixels[I, J]);
end;
end;
Bitmap.SaveToFile('test.bmp');
finally
Bitmap.Free;
end;
end;
function TForm1.ColorToHex(Color : TColor): string;
begin
Result :=
IntToHex(GetRValue(Color), 2) +
IntToHex(GetGValue(Color), 2) +
IntToHex(GetBValue(Color), 2);
end;

Custom MessageBox icon background white

I'm using a class for custom messageboxes. But my problem is that, icon background is always white. Code below displays the icons. Can somebody tell me what is wrong in this code? I want icon background to be transparent.
try
if not custb then
case i of
MB_ICONINFORMATION:ico.Handle := LoadIcon( 0, IDI_INFORMATION);
MB_ICONEXCLAMATION:ico.Handle := LoadIcon( 0, IDI_EXCLAMATION);
MB_ICONQUESTION:ico.Handle := LoadIcon( 0, IDI_QUESTION);
MB_ICONERROR:ico.Handle := LoadIcon( 0, IDI_ERROR);
end;
with timage.Create( frm) do
begin
parent := frm;
transparent := True;
if custb then
begin
height := glyph.Height;
width := Glyph.Width;
end
else
begin
height := ico.Height;
width := ico.Width;
end;
ih := height;
top := Height div 2 + 2;
it := Top;
left := Width div 2 + 2;
il := Left + width + width div 2;
if width <= 16 then
begin
il := il + 16;
left := left + 8;
end;
if height <= 16 then
begin
it := it + 8;
top := top + 8;
end;
if custb then picture := Glyph else canvas.Draw( 0, 0, ico);
end;
finally
end;
if not custb then ico.Free;
end
Best wishes,
evilone
My code to do this very thing looks like this:
function StandardDialogIcon(DlgType: TMsgDlgType): PChar;
begin
case DlgType of
mtWarning:
Result := IDI_WARNING;
mtError:
Result := IDI_ERROR;
mtInformation:
Result := IDI_INFORMATION;
mtConfirmation:
Result := IDI_QUESTION;
else
Result := nil;
end;
end;
...
Image.Picture.Icon.Handle := LoadIcon(0, StandardDialogIcon(DlgType));
There's no need to set any properties on Image, you can simply ignore Transparent.
Extract from online help for TImage.Transparent:
Setting Transparent sets the
Transparent property of the Picture.
Note: Transparent has no effect
unless the Picture property specifies
a TBitmap object.
This means two things for you:
only set transparent property after the picture has been assigned
Use TBitmap for your image and assign thtat to the picture property.
Have a look at the following link, that describes a function that converts an icon to a bitmap: Delph-Library: Convert icon to bitmap.
Excerpt:
// Konvertiert Ico zu Bitmap
procedure IcoToBmpA(Ico: TIcon; Bmp: TBitmap; SmallIcon: Boolean);
var
WH: Byte; // Width and Height
begin
with Bmp do begin
Canvas.Brush.Color := clFuchsia;
TransparentColor := clFuchsia;
Width := 32; Height := 32;
Canvas.Draw(0, 0, Ico);
if SmallIcon then WH := 16 else WH := 32;
Canvas.StretchDraw(Rect(0, 0, WH, WH), Bmp);
Width := WH; Height := WH;
Transparent := True;
end;
end;

Resources