Graphic

Graphic

Convert .ICO to .BMP
Get a DC for a Control
Using icons on a SpeedButton
BMP rotation
Lasso control
TOutline icons
Drawing Graphs
TGraphicComponent child
Converting Icons to Glyphs
Delphi Graphics
Image resizing and displaying
How to dim the colors of a glyph in a button
How Can I Make These Graphics Faster?
Make mouse snap to grid while drawing
Graph to clipboard
Icons loaded and converted for TBitBtn no white
Transparent Forms and Bitmaps
From Sizes on different platforms
Fast way to Clear a TCanvas
Assign a palette to a bitmap
Transparent bitmap brush
Removing TBitMap from TBitBtn
One draw directly onto the screen (not the form)
Bitmap Transparency


Convert .ICO to .BMP

Question


Is there a fairly simple (and on-the-fly) way to convert a .ico to a .bmp (as in getting a speedbutton to display an icon)?



Answer


A:

procedure TIconShow.FileListBox1Click(Sender: TObject);

var

   MyIcon: TIcon;

   MyBitMap : TBitmap;

begin

   MyIcon := TIcon.Create;

   MyBitMap := TBitmap.Create;



   try

	{ get the file name and the icon associated with it}

	strFileName := FileListBox1.Items[FileListBox1.ItemIndex];

	StrPCopy(cStrFileName, strFileName);

	MyIcon.Handle := ExtractIcon(hInstance, cStrFileName, 0);



	{ draw the icon onto the bitmap for the speed button }

	SpeedButton1.Glyph := MyBitMap;

	SpeedButton1.Glyph.Width := MyIcon.Width;

	SpeedButton1.Glyph.Height := MyIcon.Height;

	SpeedButton1.Glyph.Canvas.Draw(0,0, MyIcon);



	SpeedButton1.Hint := strFileName;



   finally

	MyIcon.Free;

	MyBitMap.Free;

   end;

end;




Get a DC for a Control

Question


How to get a DC for delphi VCL? I am trying to use the API function StretchBlt which requires a destDC and a sourceDC.

How do I tell windows to use my TImage or TShape for this purpose?

Answer


A:

{Bitmap in a TImage}

HDC:=Image1.PICTURE.bitmap.canvas.handle;



A DC is anything with a Canvas.handle.




Using icons on a SpeedButton

Question


Probably need a way to extract the application icon into a physical .ICO

file and convert it to a .BMP file.

Answer


A:

You can cheat a little and just copyrect the Icon into the Bitmap of a

Speed button.



var

  imgIcon: TIcon;

  imgRect: TRect;

begin

  imgIcon := TIcon.Create;

  imgIcon.Handle := ExtractIcon( 'EXEFILENAME' );



  with SpeedButton1.Glyph do begin

     Width := imgIcon.Width;

    Height := imgIcon.Height;

    imgRect := Rect( 0, 0, Width, Height );

    Canvas.CopyRect( imgRect, imgIcon.Canvas, imgRect );

  end;




BMP rotation

Question


I want to rotate BMPs (rotate to any arbitrary angle around its center of mass)

on form with Delphi code.

Answer


A:

I can think of a brute force method, but its efficiency might be

questionable, don't try it without a co-processor!



Do a pixel-by-pixel mapping from a source bitmap to a target bitmap (using

the Canvas.Pixels property). For each pixel do a rectangular-polar

coordinate conversion, add the angle offset to the polar coordinate, then

convert back to rectangular and place the pixel at these new coordinates in

the target bitmap. You may also have to dither in a few missing pixels

depending on the accuracy / rounding of your arithmatic.



The X, Y transformation you would need would be as follows:





X,Y    = old pixel coordinates

X1,Y1  = new pixel coordinates

T      = rotation angle (in radians)



R, A   - intermediate values representing the polar coordinates



R = Sqrt(Sqr(X) + Sqr(Y));



A = Arctan(Y/X);



X1 = R * Cos(A+T);



Y1 = R * Sin(A+T);





I really hope there is a better way of doing it, but if you can't find

anything else, this may be worth a try. I'm happy it will work, but may be

rather slow.



A:

>Do a pixel-by-pixel mapping from a source bitmap to a target bitmap (using

>the Canvas.Pixels property).



This is a good start -- but try thinking of it the other way around.  Do a

pixel-by-pixel mapping from the target bitmap to the source bitmap, so

you're thinking about where the pixels are coming from, rather than where

they are going.



Here is a formula for rotation about the origin:



x, y = coordinates in the target bitmap

t = angle

u, v = coordinates in the source bitmap



x = u * cos(t) - v * sin(t)

y = v * cos(t) + u * sin(t)



Now, if I've solved these equations right for u and v, here's what they

would be (no guarantees, that's why I've included the originals!):



      x * cos(t) + y

u = --------------------

    sqr(cos(t)) + sin(t)



v =   y * cos(t) - x

    --------------------

    sqr(cos(t)) + sin(t)



So, assuming you know the angle of rotation, you might calculate the

constants cos(t) and 1/sqr(cos(t))+sin(t) just before your loop; it might

look something like this (some adjustment and clipping needed):



ct := cos(t);

ccst := 1/sqr(cos(t))+sin(t);

for x := 0 to width do

  for y := 0 to height do

    dest.pixels[x,y] := source.pixels[Round((x * ct + y) * ccst),

                                      Round((y * ct - x) * ccst)];



If you wanted to speed it up, and didn't care about accumulated round-off

error, you could realize that since you're moving a pixel at a time, the

distance between pixels in the u,v map is constant as you move across the

row, and again as you move down the column. I'll use the calculated

variables above as shorthand. Just plug in (x,y) = (1,0) and (x,y) = (0,1)

in the equation above to get:



duCol := ct * ccst;

dvCol := -ccst;



duRow := ccst;

dvRow := ct * ccst;



uStart := 0;

vStart := 0;



for x := 0 to width do

  begin

    u := uStart;

    v := vStart;

    for y := 0 to height do

      begin

        dest.pixels[x,y] := source.pixels[Round(u), Round(v)];

        u := u + rowdu;

        v := v + rowdv;

      end;

    uStart := uStart + duCol;

    vStart := vStart + dvCol;

  end;



All code provided as-is and without warranty!



If you're adventurous and want to try rotation around an arbitrary point,

try solving these for u and v:



Xp, Yp (X-sub-p, Y-sub-p) is the pivot point

others defined as above



x = Xp + (u - Xp) * cos(t) - (y - Yp) * sin(t)

y = Yp + (y - Yp) * cos(t) - (x - Xp) * sin(t)



A:

The original equations:



  x = u * cos(t) - v * sin(t)

  y = v * cos(t) + u * sin(t)



are correct but when I solve for u and v, I get this:



      x * cos(t) + y * sin(t)

  u = -----------------------

     sqr(cos(t)) + sqr(sin(t))





      y * cos(t) - x * sin(t)

  v = ------------------------

      sqr(cos(t)) + sqr(sin(t))


Lasso control

Question


Does anybody know how to implement a lasso (selecting many controls by 

dragging the mouse over them) in Delphi?

Answer


A:

Here's a possible approach...



1.  In the OnMouseDown event for the form that you are 'lasso-ing' controls on:



	bMarquee :=  True;		{ set a boolean so that you can

                                          differentiate between decisions that

					  might have to be made during other

					  mouse events }

	ptOrigin := Point( X, Y );	{ get the starting point of the marquee }

	ptMove  := Point( X, Y );	{ initialize the stopping point }



	set the pen and brush attributes here or by calling a common procedure

	that can be reused elsewhere in the Unit.



	Pen.Color := clBlack;

	Pen.Width := 1;

	Pen.Style := psDash;

	Brush.Style := bsClear;



	then draw the marquee rect



	DrawMarquee(ptOrigin, ptMove, pmNotXor );





2.  In the OnMouseMove event for the form...



	if bMarquee = True then begin

	   DrawMarquee(ptOrigin, ptMove, pmNotXor );

	   DrawMarquee(ptOrigin, Point( X, Y ), pmNotXor );

	   ptMove := Point( X, Y );

	   Canvas.Pen.Mode := pmCopy;

	end;





3.  In the OnMouseUp event for the form...



	if bMarquee = True then begin

	   bMarquee := False;

	   DrawMarquee(ptOrigin, Point( X, Y ), pmNotXor );

	   ptMove := Point( X, Y );

	

	   { check for any intersections between the marquee frame and controls }



	   - call the procedure that will highlight ( focus ) the desired controls



	end;





The DrawMarquee procedure...



procedure myForm.DrawMarquee( mStart, mStop : TPoint; AMode : TPenMode);

begin

   Canvas.Pen.Mode := AMode;

   Canvas.Rectangle( mStart.X, mStart.Y, mStop.X, mStop.Y );

end;


TOutline icons

Question


Is it possible to individually specify the icons displayed in a TOutline

component?

Answer


A:

It is possible, but its not necessarily easy. To do it you need to use an

"Owner Draw" outline. In the Outline's OnDrawItem event you'll need to

paint your bitmap and then the text. That parts pretty easy, but you have

to deal with indention, drawing the tree, etc. Plus there are a couple of

bugs/unexpected behaviors that get in the way.



Here's a snippet of code from an OnDrawItem handler that draws a bitmap

followed by the outline item text. The code for handling the bitmap could

probably be improved because I haven't had much experience with Windows

graphics.  In case its not obvious olnOutline is my outline and bmpBitMap is

the bitmap.





  {Get outline index.  The DrawItem Index param is simply the number of the row

   being dran and does not take into account collapsed nodes                   }

  lIndex := GetItem(Rect.Left, Rect.Top);



  Offset := 2;  {Determines spacing between bitmap and text}



  with olnOutline do

  begin

    with Canvas do

    begin

      {Indent the bitmap based on the Level of the OutlineNode}

      Inc(Rect.Left, Offset + (ItemHeight * (Items[lIndex].Level -1)));



      {Copy the bitmap }

      BrushCopy(Bounds(Rect.Left, Rect.Top, bmpBitMap.Width, bmpBitMap.Height),

        bmpBitMap, Bounds(0, 0, bmpBitMap.Height, bmpBitMap.Width),

        bmpBitMap.TransparentColor);



      {Draw the text to the right of the bitmap}

      Inc(Rect.Left,bmpBitMap.Width + Offset);

      TextOut(Rect.Left, Rect.Top, Items[lIndex].Text);

    end; {with Canvas}

  end; {with Outline}





Notes:

This snippet is from a larger block of code and I tried to trim out the

uneccesary junk, but it won't work without a little modification.

There is a problem with Outline's redrawing if you change the width of the

Outline at runtime.  I think it only happens when the horizontal scrollbar

is disabled. Anyway, the problem is that the Rect passed to the OnDrawItem

event is the width before you resized the Outline.  You could get around

this by using the Outline's width to set the right side of the Rect rather

than using the value supplied by Delphi.

This code DOES NOT draw the tree.  I kept thinking I'd steal the code from

the VCL source, but it wasn't needed for this application so I never go to

it. Really wish the tree drawing routine was accessible, but it's not.


Drawing Graphs

Question


I tryed to use ChartFX to plot a function but I have not found

a lot of documentation on it. Does anybody know where I can get

more information? Do you have an example where you plot a trigo

function between 0 and 2*Pi?

Answer


A:

You could use a TCanvas object to draw the function yourself.

A TImage component would be good to use, as it's bitmap contains

a canvas that you can draw on.

eg: (Create a new form, add an Image and a Button. Attach this code

     to the button)



var

  x,l: Integer;

  y,a: Double;

begin

  Image1.Picture.Bitmap := TBitmap.Create;

  Image1.Picture.Bitmap.Width := Image1.Width;

  Image1.Picture.Bitmap.Height := Image1.Height; {These three lines could

                                                  go in Form1.Create instead}

  l := Image1.Picture.Bitmap.Width;

  for x := 0 to l do

    begin

     a := (x/l) * 2 * Pi;  {Convert position on X to angle between 0 & 2Pi}

     y := Sin(a); {Your function would go here}

     y := y * (Image1.Picture.Bitmap.Height / 2); {Scale Y so it fits}

     y := y * -1; {Invert Y, the screen top is 0 !}

     y := y + (Image1.Picture.Bitmap.Height / 2); {Add offset for middle 0}

     Image1.Picture.Bitmap.Canvas.Pixels[Trunc(x), Trunc(y)] := clBlack;

    end;

end;



A:

I've found the best way is to draw directly onto the canvas. Preferably in a

separate procedure taking a TCanvas and a TRect as parameters. That way you

can pass your window's canvas and client rect as parameters for drawing on

screen and the printer's canvas and a rect comprising of the area where

you wan't it to be positioned to print. Look at the canvasses methods to

get the available drawing routines.



A:

You could use a TCanvas object to draw the function yourself.

A TImage component would be good to use, as it's bitmap contains

a canvas that you can draw on.

eg: (Create a new form, add an Image and a Button. Attach this code

     to the button)



var

  x,l: Integer;

  y,a: Double;

begin

  Image1.Picture.Bitmap := TBitmap.Create;

  Image1.Picture.Bitmap.Width := Image1.Width;

  Image1.Picture.Bitmap.Height := Image1.Height; {These three lines could

                                                  go in Form1.Create instead}

  l := Image1.Picture.Bitmap.Width;

  for x := 0 to l do

    begin

     a := (x/l) * 2 * Pi;  {Convert position on X to angle between 0 & 2Pi}

     y := Sin(a); {Your function would go here}

     y := y * (Image1.Picture.Bitmap.Height / 2); {Scale Y so it fits}

     y := y * -1; {Invert Y, the screen top is 0 !}

     y := y + (Image1.Picture.Bitmap.Height / 2); {Add offset for middle 0}

     Image1.Picture.Bitmap.Canvas.Pixels[Trunc(x), Trunc(y)] := clBlack;

    end;

end;


TGraphicComponent child

Question


But, as you may already know, my question is: How can i manage to  get the

MouseDown event occur *only* when my routine - that checks for  this (the

point being into the shape)  - returns TRUE to the points given?

Answer


A:

You can't. However, you can restrict any event handlers attached to it, and

you can make sure that click doesn't get called. I take it you want an

OnClick event that takes into account your triangular shape? Not a problem.

Oh, and just to address one of your other replies, it's not neccesary to

trap the windows messages, as TGraphicControl already does trap most (or all,

not sure) of them.

Now, I'm sure there's a couple of ways to do this, and this is the way I'd

do do it, and it will work, but keep in mind I have no VCL source so this is

probably a bit awkward.



procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer)

; override;



procedure TThing.MouseDown...

begin

	{Not the mouse coordinates in some private property}

	inherited MouseDown...

end;



procedure TThing.Click

begin

	if YourHitTest(X,Y) then

	   inherited Click;

end;

I'm a bit dubious about that last procedure, but it will work. I'm sure

there's some better documented people here who can come up with a more

elegant solution.


Converting Icons to Glyphs

Question


I need to convert Icons(.ICO) into Bitmaps(.BMP) for use in Glyphs at

run-time.  I have seen an application to do this but it didn't come with

source code.  Does anyone know an easy way to do this?  I would prefer a

short code segment but a VCL component would also be an option.

Answer


This is a small example with how to load an icon contained in a

file EXE in a Glyph of an SpeedButton and as cleaning the Glyph.



Sorry but the commentaries of the code source are in Spanish.



*****************************************

unit Procs;



interface

uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, StdCtrls, Buttons, ExtCtrls, ShellAPI;



  procedure LlenaBoton(boton: TSpeedButton; Programa: string);

  procedure LimpiaBoton(boton: TSpeedButton);



  var

    {Botones de programas}

    Pic: TPicture;

    Fname : String;

    TempFile: array[0..255] of Char;

    Icon : TIcon;



implementation

uses ttotro;





procedure LlenaBoton(boton: TSpeedButton; Programa: string);

 var

   NumFiles, NameLength : integer;

   nIconsInFile : word;

   rBoton : TRect;

   oBitmap : TBitmap;

   oBitmap2: TBitmap;

   NombreBitmap: string;



 begin



  try

   screen.cursor := crHourglass;



     {Extrae el Icono}

     Icon := TIcon.Create;

     StrPCopy(TempFile, Programa);

     Icon.Handle := ExtractIcon(HInstance, TempFile, 0);



     {Crea una instancia de TPicture}

     Pic := TPicture.Create;

     {Asigna el icon.handle a la propiedad Pic.icon}



     Pic.Icon := Icon;





     {Configura el tamano del bitmap como el del icono y el del segundo

      bitmap con el tamano del boton}

     oBitmap := TBitMap.create;

     oBitmap2 := TBitMap.create;

     oBitmap2.Width := Icon.Width;

     oBitmap2.Height := Icon.Height;

     oBitmap.Width := boton.Width-4;

     oBitmap.Height := boton.Height-4;



     { Dibuja el icono en el bitmap }

     oBitmap2.Canvas.Draw( 0, 0, Pic.Graphic );

     rBoton.left := 1;

     rBoton.Top := 1;

     rBoton.right:= boton.Width-6;

     rBoton.Bottom := boton.Height-6;

     oBitmap.Canvas.StretchDraw(rBoton, oBitmap2);



     Boton.Hint := Programa;



     NombreBitmap := Copy(programa, 1, Length(programa)-3)+'BMP';

     {Salva el bitmap en un fichero}

     If Not FileExists(NombreBitmap) Then

        begin

         oBitmap.SaveToFile(ExtractFilePath(Application.ExeName)+ExtractFileName(NombreBitmap));

         Boton.Glyph := oBitmap;

        end

     else

        {Carga el BMP en el boton}

        Boton.Glyph.LoadFromFile(ExtractFilePath(Application.ExeName)+ExtractFileName(NombreBitmap));



   finally

     Icon.Free;

     oBitmap.Free;

     oBitmap2.Free;

     screen.cursor := crDefault;



   end; {main begin}

end;  {llenaboton}



procedure LimpiaBoton(boton: TSpeedButton);

 var

   oBitmap : TBitmap;

   rBoton : TRect;

 begin



  try

     {Configuara el tamano del bitmap como el del icono y el del segundo

      bitmap con el tamano del boton}

     oBitmap := TBitMap.create;

     oBitmap.Width := boton.Width-4;

     oBitmap.Height := boton.Height-4;

     Boton.Glyph := oBitmap;



   finally

     oBitmap.Free;

   end; {main begin}

end;  {limpiaboton}



end.


Delphi Graphics

Question


I have a project to develop a small video format....

I've done some tests with Delphi and it takes approx. 4 seconds for it

to fill a 250 x 250 bitmap, one pixel at a time...this is obviously

too slow...there has to be other ways to do it.

Answer


If you are simply trying to display one image in a resonable amount

of time, create a TBitmap object, play around with it, and then when

you are ready to display it to the screen, call

Image.Canvas.Draw(0, 0, Bitmap) to copy it and draw it to the screen.

You see, the main time consumer is the painting of the screen, not in

the setting of the Image's attributes.  As a result, you want to set the

pixel's colors in a non-visible object (the TBitmap you created), and

then display the whole Bitmap at once.  Here is some code for a form

with a single Image component on it:



procedure TForm1.FormPaint(Sender: TObject);

Var

  TmpX, TmpY : Byte;

  MyImage : TBitmap;

begin

  Form1.Width := 260;    Form1.Height := 260;

  Image1.Width := 250;   Image1.Height := 250;

  Image1.top := 5;       Image1.width := 5;

  MyImage := TBitmap.Create;

  MyImage.Width := 250;  MyImage.Height := 250;

  FOR TmpX := 0 TO 249 DO

    FOR TmpY := 0 TO 249 DO

      MyImage.Canvas.Pixels[TmpX,TmpY] :=

            RGB(TmpX, 250 - TmpY, (TmpX + TmpY DIV 2));

  Image1.Canvas.Draw(0, 0, MyImage);

  MyImage.Free;

end;



If you want to do really fast graphics, look into the GDI (API)

functions and/or the WinG functions given out by Microsoft.  These

are a bit tedious to learn and use, and they are outside of Delphi's

domain.


Image resizing and displaying

Question


I've placed a TImage in a ScrollBox, and in my paint routine I have it

adjust the size of the Image component based on a zoom factor, then paint

the Image.

The scroll box reacts correctly to the changes in size, however the TImage

only paints the area corresponding to my 100% size when going to bigger zoom

factors (i.e. 200%).  So my image is chopped off, but like I said, the

scrollbox is doing everything correctly.  I've checked the height and width

properties of the image at run time, and everything is fine there, so I

can't understand what's happening.

Answer


A:

The size of the bitmap you have attached to the picture.graphic property

matters also. If you size the image contorl to say 320x200, but the bitmap

is only sized to 160x100 then all you'll be left with is that gray area

around the picture, unless you have the stretch property set to true.



  Here's a quick way around this.



procedure TForm.ZoomImage;

var Bitmap: TBitmap;

      DstRect: TRect;

begin

   { Here you want to set up a new bitmap with the proper proportions for your

     zoom factor and draw the image you want zoomed into it. }



   Bitmap := TBitmap.Create;

   Bitmap.Width := { insert your zoomed width here }

   Bitmap.Height := { insert your zoomed height here}



   Bitmap.Canvas.StretchDraw(Bitmap.Canvas.ClipRect,{insert the image you



      you want zoomed here});



   { Here you assign the new bitmap to the graphic property of the image box.

    The image box will automatically dispose of the resources used by its

    prior image. }



   Image1.Picture.Graphic := Bitmap;

   Image1.Invalidate;

end;



That should work, or at least give you an idea of how to implement what you

want. I just wrote this OTTOMH so no flames if I forgot something please.

Keep in mind that you don't need to do this in the onPaint event. I also

like the fact that the image box is smart enough to dispose of the old

bitmap when you assign it a new one. Incidently I think if you use the

Assign method instead of implicity assigning the bitmap you'll end up with a

copy of the new bitmap instead of actually having the image box use the one

just created..  You'll have to dispose of the new one then at the end of the

procedure.



A:

The solution to problem was to adjust the TImage.Picture.Bitmap.Width and

the TImage.Picture.Bitmap.Height properties.


How to dim the colors of a glyph in a button

Question


However, for various reasons, I can't create the 2,3,4 glyphs in a bitmap.

I just need to use the 1 glyph in 1 bitmap  and dim the color at run-time

- maybe using some calculations to reduce the color value..... or something.

Answer


A:

The best way is still to create more than one glyph in a bitmap, if

you're stuck on this one, try loading one of the provided sample

button glyphs into image editor, to see how it's done...



I presume though, that you probably have a TBitmap that you

dynamically assign to the bitmap at runtime. To generate a dimmed

glyph, you could draw black pixels on every alternate square, like

those on a chessboard. I think this is the way that 95 generates it's

dimmed screen when asking if a shutdown is needed. Your code to draw

a pixel onto the glyph would probably look something like this:

BitBtn1.Glyph.Canvas.Pixels[0,0] := clBlack;



and in a loop:

for i := 1 to BitBtn1.Height do

  for j := 1 to BitBtn1.Width do

    begin

     if (Trunc(j/2)*2) = j then BitBtn1.Glyph.Canvas.Pixels[j,

          Trunc(Frac(i/2)*2)] := clBlack;

    end;


How Can I Make These Graphics Faster?

Question


How might I only draw to a specific part of the screen and only have that

portion repainted, instead of the entire bitmap repainted?  Just having a

16 x 16 portion of the bitmap would be speed demons quicker than repainting

the entire 416 x 216 bitmap...

Answer


A:

Here is a VCL-only method of doing it;  see if this

helps. The BitBlt is handled by CopyRect.



var

  BitMap : TBitmap;



procedure TForm1.FormCreate(Sender: TObject);

begin

  Bitmap := TBitmap.Create;

  Bitmap.Width := 400;

  Bitmap.Height := 400;

  PaintBox1.Width := 200;

  PaintBox1.Height := 200;

  With Bitmap.Canvas do

    begin

      Pen.Color := clNavy;

      Ellipse(0,0,399,399);

    end;

end;



procedure TForm1.FormDestroy(Sender: TObject);

begin

  Bitmap.Free;

end;



procedure TForm1.Button1Click(Sender: TObject);

var

  Limit : Word;

  I : Word;

  PBBottom, PBRight : Word;

begin

  PBBottom := PaintBox1.Height - 1;

  PBRight := PaintBox1.Width - 1;

  Limit := Bitmap.Width - PaintBox1.Width;

  For I := 0 to Limit do

    PaintBox1.Canvas.CopyRect(Rect(0,0,PBRight,PBBottom),

                              Bitmap.Canvas, Rect(I,0,I+PBRight,PBBottom));

end;


Make mouse snap to grid while drawing

Question


Can anyone tell me where to start....

How do make "snap to grid" -procedure for OnMouseMove -event (or for any

event)(like in programs like Designer, AutoCAD  etc.)

Answer


A:

1.  Declare two variables to hold the user-desired grid sizes:



	nGridWidth : Integer;

	nGridHeight : Integer;



2.  If bSnapToGrid then



	2a.  calculate the closest point in the grid to the current

	x, y in the OnMouseUp event handler.



3.  Place the drawing component (left, top) at this position.



Give the user a method for setting their own grid preferences.


Graph to clipboard

Question


I'm having a problem trying to copy a graph to the clipboard.  I have the

following code:



      TGraph1.refresh;

      TGraph1.CopyBitmap := 0;



The problem is that the graph is distorted with a portion of another window

from a different program.  Is there a way to verify when the bitmap is

copied.  It appears not to do the actual copy until there's some kind of

screen change.

Answer


A:

According to the online help, the CopyBitMap is a method of Chart control. I've

never used it. I have a routine to copy a bitmap to clipboard though. Actually

it copies the whole contents of a Window to the clipboard, memos and all ! 



Var

  Image : TImage;

  BitMap : TBitmap;

Begin

  Image:=TImage.Create(Self);

  BitMap:=TBitMap.Create;

  BitMap.Width:=ClientWidth;

  BitMap.Height:=ClientHeight;

  BitBlt(BitMap.Canvas.Handle, 0, 0, ClientWidth, ClientHeight, GetDC(Handle),

         0, 0, SRCCOPY);

  Image.Picture.Graphic:=BitMap;



  Clipboard.Assign(Image.Picture);

  BitMap.Free;

  Image.Free

End;



No guarantees about efficiency, pictures, graphics, & bitmaps still confuse me,

but it works ! If you only want a bitmap from a window, you change the

GetDC(Handle) to Bitmap.Handle.


Icons loaded and converted for TBitBtn no white

Question


I don't think this is the problem - as I said if I load it into an image, it

works - the transparent parts are - and the white parts are white - when I

put them on a button though, all white becomes transparent!

Answer


A:

If you load an icon into a TImage, it "understands" icons and displays

transparency info accordingly. Icons actually contain two bitmaps, one

containing the normal color info, with white areas to represent where

transparency should go; then a second "mask" bitmap that also has white for

the transparent areas, and black for the colored areas.  When the two are

"xored" together with the background, the white on white areas show the

background through, the color (including white) on black areas show the color

of the icon; (you can also get "inverted background" areas in an icon by

having areas that are black in the colored bitmap but are white on the mask).



When you convert the icon to a bitmap, the transparency info is lost

because bitmaps don't have the built-in capacity for storing this extra

mask bitmap that is used to make transparent parts. I'd guess the icons

you're using are generally "free standing" objects with transparent

backgrounds, that means that the color bitmap is surrounded in white.

So, when you load one into a TBitbutton or TSpeedbutton's glyph

property, the lowerleft corner color (which will be white in these

cases) now gets interpreted as transparent, giving the effect you

describe.



The solution is to convert the icon to a bitmap and save it as a .BMP

file, then edit it with ImageEdit, Resource Workshop, or even PaintBrush

and use an otherwise unused color as the lower left pixel and anywhere

else you WANT to be transparent.  Otherwise, I have some code that

extracts the color and mask bitmaps from an icon, you could then use

these to write out a bitmap that has the appropritate pixels set to an

unused color, though finding that unused color might be a bit tedious

programatically; hmmm, I'm smelling a utility here, I may have to get to

work on this.


Transparent Forms and Bitmaps

Question


Anyone know how to make a form transparent? Also make a bitmap

background transparent in Delphi?

Answer


A:

Here's a nice routine to draw a transparent bitmap onto another.



{This procedure will draw a source bitmap onto a target bitmap,

 leaving information from the taget to shine through where the

 pixels in the source are of the specified transparent color.

 t   = The target canvas to be drawn onto

 x,y = The position on the target where source is drawn

 s   = The source bitmap

 TrCol = The color that will become transparent in the source bmp

 NOTE: Don't forget to repaint the target, eg Image1.Invalidate}



procedure DrawTransparent(t: TCanvas; x,y: Integer; s: TBitmap; TrCol: TColor);

var

  bmpXOR, bmpAND, bmpINVAND, bmpTarget: TBitmap;

  oldcol: Longint;

begin

  try

   bmpAND := TBitmap.Create; bmpAND.Width := s.Width; bmpAND.Height := s.Height; bmpAND.Monochrome := True;

   oldcol := SetBkColor(s.Canvas.Handle, ColorToRGB(TrCol));

   BitBlt(bmpAND.Canvas.Handle, 0,0,s.Width,s.Height, s.Canvas.Handle, 0,0, SRCCOPY);

   SetBkColor(s.Canvas.Handle, oldcol);



   bmpINVAND := TBitmap.Create; bmpINVAND.Width := s.Width; bmpINVAND.Height := s.Height; bmpINVAND.Monochrome := True;

   BitBlt(bmpINVAND.Canvas.Handle, 0,0,s.Width,s.Height, bmpAND.Canvas.Handle, 0,0, NOTSRCCOPY);



   bmpXOR := TBitmap.Create; bmpXOR.Width := s.Width; bmpXOR.Height := s.Height;

   BitBlt(bmpXOR.Canvas.Handle, 0,0,s.Width,s.Height, s.Canvas.Handle, 0,0, SRCCOPY);

   BitBlt(bmpXOR.Canvas.Handle, 0,0,s.Width,s.Height, bmpINVAND.Canvas.Handle, 0,0, SRCAND);



   bmpTarget := TBitmap.Create; bmpTarget.Width := s.Width; bmpTarget.Height := s.Height;

   BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, t.Handle, x,y, SRCCOPY);

   BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, bmpAND.Canvas.Handle, 0,0, SRCAND);

   BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, bmpXOR.Canvas.Handle, 0,0, SRCINVERT);

   BitBlt(t.Handle, x,y,s.Width,s.Height, bmpTarget.Canvas.Handle, 0,0, SRCCOPY);

  finally

   bmpXOR.Free;

   bmpAND.Free;

   bmpINVAND.Free;

   bmpTarget.Free;

  end;{End of TRY section}

end;


From Sizes on different platforms

Question


I am trying to make my app work on screen sizes eg.  640x480 &

1024x768 I have tried changing the pixels per inch property but

it doesn't seem to work.

Answer


A:

The following should help make your forms look correct at different

resolutions:

a.) Set Autoscroll to' FALSE'. True means don't change the form's frame size

at run time.

b.) Set the font to a TrueType like Arial, don't leave it at the default

'SYSTEM''

c.) Set Position to something other than poDesigned, this will leave it where

you left it on your 1280x780 screen which maybe barely visible at 640x480.

d.) Change Pitch property of the font from DEFAULT to VARIABLE

e.) DON'T CHANGE THE PixelsPerInch PROPERTY.

f.) Set the Scaled Property to TRUE. This scales the forms to the value of

the PixelsPerInch property.


Fast way to Clear a TCanvas

Question


Is there a TCanvas.Clear, or, what is the best way to clear a TCanvas?

Answer


A:

InValidateRect(Canvas.handle,NIL,True);



A:

If you are using a Form's canvas try

InValidateRect(form1.handle,NIL,True);

instead.

(or the components handle)



A:

This will clear a canvas:

 canvas.fillrect(canvas.cliprect) ;


Assign a palette to a bitmap

Question


I use a resource file to load (256 colour) bitmaps into my application.

At 65.000 colours this is no problem. When i switch my screen to 256 colours

the palette of the bitmap becomes very weird.

If i place a timage component on the form and do a loadfromfile then the

palette is correct.

So the problem is that the palette won't update when i draw an image

with ' canvas.draw(0,0,bitmap1) ' where bitmap1 is a tbitmap.

Does anybody on the list know a answer to this problem!?

Answer


A:

If you are drawing on a TImage....



First you need to use the Image1.Picture.bitmap not the Image.Canvas.

The reason is the the Image1.Picture.Bitmap has a palette -Timage doesn't.

Then you need to assign the palette.  For example:

	//Set Width and Height before using Image1.Picture Bitmap's Canvas

var

	Bitmap: TBitmap;

begin



	Bitmap:=TBitmap.Create;

	Bitmap.LoadfromFile({'Whatever.bmp'});



	With Image2.Picture.bitmap do

	Begin

		Width:=Bitmap.Width;

		height:=Bitmap.Height;

		Palette:=Bitmap.Palette;

		Canvas.draw(0,0,bitmap);

		Refresh;

	end;

end;



If you are drawing on the Form's Canvas ...



	Canvas.Draw(0,0,Bitmap);

	SelectPalette(Form1.Canvas.handle,Bitmap.Palette,True);

	RealizePalette(Form1.Canvas.Handle);


Transparent bitmap brush

Question




Answer


A:

The following unit draws two bitmaps on a form.  One is used

as the background, and the second one as the foreground.  The

foreground bitmap is displayed as a "transparent" bitmap.



Read the comments for a complete (well sort of) explanation.



{ Purpose:  Display a transparent bitmap loaded from a file

  Author:   Michael Vincze (vincze@ti.com)

  Date:     04/20/95

  Usage:    Create a blank form, named Form1, compile and run.

  Limits:   This unit has been tested for both 16 and 256 color bitmaps.

            It is assumed that the lower left pixel of the bitmap represents

            the transparent color.

  Notes:    If this file is to be used for any purpose please leave

            this header intact and give credit to the author if used for

            any purpose.

            Please contact the author if any improvements are made.

            The author stakes no claim for this programs usefullness

            or purpose.

  Version:  1.00  04/20/95  Initial creation

}

unit Tbmpu;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs, ExtCtrls;



type

  TForm1 = class(TForm)

    procedure FormCreate(Sender: TObject);

    procedure FormClose(Sender: TObject; var Action: TCloseAction);

  private

    { Private declarations }

    ImageForeGround: TImage;

    ImageBackGround: TImage;

  public

    { Public declarations }

  end;



procedure DrawTransparentBitmap (ahdc: HDC;

                                 Image: TImage;

                                 xStart, yStart: Word);



var

  Form1: TForm1;



implementation



{$R *.DFM}



procedure DrawTransparentBitmap (ahdc: HDC;

                                 Image: TImage;

                                 xStart, yStart: Word);

var

  TransparentColor: TColor;

  cColor          : TColorRef;

  bmAndBack,

  bmAndObject,

  bmAndMem,

  bmSave,

  bmBackOld,

  bmObjectOld,

  bmMemOld,

  bmSaveOld       : HBitmap;

  hdcMem,

  hdcBack,

  hdcObject,

  hdcTemp,

  hdcSave         : HDC;

  ptSize          : TPoint;

begin

{ set the transparent color to be the lower left pixel of the bitmap

}

TransparentColor := Image.Picture.Bitmap.Canvas.Pixels[0,

  Image.Height - 1];

TransparentColor := TransparentColor or $02000000;



hdcTemp := CreateCompatibleDC (ahdc);

SelectObject (hdcTemp, Image.Picture.Bitmap.Handle); { select the bitmap }



{ convert bitmap dimensions from device to logical points

}

ptSize.x := Image.Width;

ptSize.y := Image.Height;

DPtoLP (hdcTemp, ptSize, 1);  { convert from device logical points }



{ create some DCs to hold temporary data

}

hdcBack   := CreateCompatibleDC(ahdc);

hdcObject := CreateCompatibleDC(ahdc);

hdcMem    := CreateCompatibleDC(ahdc);

hdcSave   := CreateCompatibleDC(ahdc);



{ create a bitmap for each DC

}



{ monochrome DC

}

bmAndBack   := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);

bmAndObject := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);



bmAndMem    := CreateCompatibleBitmap (ahdc, ptSize.x, ptSize.y);

bmSave      := CreateCompatibleBitmap (ahdc, ptSize.x, ptSize.y);



{ each DC must select a bitmap object to store pixel data

}

bmBackOld   := SelectObject (hdcBack, bmAndBack);

bmObjectOld := SelectObject (hdcObject, bmAndObject);

bmMemOld    := SelectObject (hdcMem, bmAndMem);

bmSaveOld   := SelectObject (hdcSave, bmSave);



{ set proper mapping mode

}

SetMapMode (hdcTemp, GetMapMode (ahdc));



{ save the bitmap sent here, because it will be overwritten

}

BitBlt (hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);



{ set the background color of the source DC to the color.

  contained in the parts of the bitmap that should be transparent

}

cColor := SetBkColor (hdcTemp, TransparentColor);



{ create the object mask for the bitmap by performing a BitBlt()

  from the source bitmap to a monochrome bitmap

}

BitBlt (hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);



{ set the background color of the source DC back to the original color

}

SetBkColor (hdcTemp, cColor);



{ create the inverse of the object mask

}

BitBlt (hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);



{ copy the background of the main DC to the destination

}

BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, ahdc, xStart, yStart, SRCCOPY);



{ mask out the places where the bitmap will be placed

}

BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);



{ mask out the transparent colored pixels on the bitmap

}

BitBlt (hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);



{ XOR the bitmap with the background on the destination DC

}

BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);



{ copy the destination to the screen

}

BitBlt (ahdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);



{ place the original bitmap back into the bitmap sent here

}

BitBlt (hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);



{ delete the memory bitmaps

}

DeleteObject (SelectObject (hdcBack, bmBackOld));

DeleteObject (SelectObject (hdcObject, bmObjectOld));

DeleteObject (SelectObject (hdcMem, bmMemOld));

DeleteObject (SelectObject (hdcSave, bmSaveOld));



{ delete the memory DCs

}

DeleteDC (hdcMem);

DeleteDC (hdcBack);

DeleteDC (hdcObject);

DeleteDC (hdcSave);

DeleteDC (hdcTemp);

end;



procedure TForm1.FormCreate(Sender: TObject);

begin

{ create image controls for two bitmaps and set their parents

}

ImageForeGround := TImage.Create (Form1);

ImageForeGround.Parent := Form1;

ImageBackGround := TImage.Create (Form1);

ImageBackGround.Parent := Form1;



{ load images

}

ImageBackGround.Picture.LoadFromFile ('c:\delphi\images\splash\16color\earth.bmp');

ImageForeGround.Picture.LoadFromFile ('c:\delphi\images\splash\16color\athena.bmp');



{ set background image size to its bitmap dimensions

}

with ImageBackGround do

  begin

  Left := 0;

  Top := 0;

  Width := Picture.Width;

  Height := Picture.Height;

  end;



{ set the foreground image size centered in the background image

}

with ImageForeGround do

  begin

  Left := (ImageBackGround.Picture.Width - Picture.Width) div 2;

  Top := (ImageBackGround.Picture.Height - Picture.Height) div 2;

  Width := Picture.Width;

  Height := Picture.Height;

  end;



{ do not show the transparent bitmap as it will be displayed (BitBlt()ed)

  by the DrawTransparentBitmap() function

}

ImageForeGround.Visible := False;



{ draw the tranparent bitmap

  note how the DC of the foreground is used in the function below

}

DrawTransparentBitmap (ImageBackGround.Picture.Bitmap.Canvas.Handle, {HDC}

                       ImageForeGround, {TImage}

                       ImageForeGround.Left, {X}

                       ImageForeGround.Top {Y} );

end;



procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

{ free images

}

ImageForeGround.Free;

ImageBackGround.Free;

end;



end.


Removing TBitMap from TBitBtn

Question


Is there a way to remove a bitmap from a TBitBtn?

Answer


I would try this:



     Glyph.free;

     Glyph := nil;



At the point where you want to get rid of the bitmap. Not sure it works,

but worth a try.


One draw directly onto the screen (not the form)

Question


Copying the pre-screensaver screen contents to the maximized screensaver-

form, and then slowly changing the contents of the form, creating the

illusion that the screen itself is changing.

The problem then is: how can I read the pixels of the displayed (complete)

screen directly?

Answer


A:

Create a form, drop a TImage control to the form, make it a decent size,

and drop a button on it. DblClick the button and add the following code.



Var

  ScreenDC : HDC;

begin

  ScreenDC:=CreateDC('DISPLAY',nil,nil,nil);

  BitBlt(Image1.Canvas.Handle, 0,0, Image1.Width, Image1.Height,

ScreenDC, 0,0, SRCCOPY);

  Image1.Refresh;

  DeleteDC(ScreenDC);

end;



That will copy the desktop into the Image Control. Play around with the

0,0 near the ScreenDC to move the TopLeft of the image to want to

capture. Move your form around and click the button, Look up BitBlt in

the help file it might explain some things.



You could just as easily create a memory bitmap



Var

   ScreenDC : HDC;

   fBitmap : TBitmap;

begin

   fBitmap := TBitmap.Create;

   fBitmap.Width := 100;

   fBitmap.Height := 100;

   ScreenDC:=CreateDC('DISPLAY',nil,nil,nil);

   BitBlt(FBitmap.Canvas.Handle, 0,0, FBitmap.Width, FBitmap.Height,

ScreenDC, 0,0, SRCCOPY);

   { You now have a copy of the screen from (0,0,100,100) in the

fBitmap, you now can  }

   { do what you want to it, merge it with another bitmap?, or anything

else you want to. }



   { Clean Up }

   DeleteDC(ScreenDC);

   fBitmap.Free

end;


Bitmap Transparency

Question


I was wondering if anyone knows the steps in achieving a transparent bitmap

effect?  Someone told me that I had to deal with 2 bitmaps, a mask and

something else, but I have no clue how that works.

Answer


You do need two copies of the bitmap. The mask and the image. The mask is

nothing more than a bitmap with two colors. Black for the areas you want to

show and white for transparent areas. For Windows 3.1 this can be a

monochrome bitmap to keep the size down. For Win95 a monochrome will not

work under all circumstances so it should have the same depth as the picture

you are going to show. 



The picture you want to display has to have the transparent areas done in

color 0. Putting the picture on the screen is the same method used under

DOS. The mask is ANDed to the screen, then the picture is ORed or XORed to

the same place.



Below is the Delphi code to do this using two TBitmaps.



  Canvas.CopyMode := cmSrcAnd;

  Canvas.CopyRect(TitleRect, BMask.Canvas, TitleRect);

  {fill the hole with the picture}

  Canvas.CopyMode := cmSrcPaint;

  Canvas.CopyRect(TitleRect, BTitle.Canvas, TitleRect);


Close    To Top
  • Prev Article-Programming:
  • Next Article-Programming:
  • Now: Tutorial for Web and Software Design > Programming > delphi > Programming Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction