I want to assign the existing TImageList Handle to TImageCollection so that I can use my TImagecollection with TvirtualImageList.
Here FormSet.SmallImageListHandle is a TImageList which is loading images from some other modules but I want copy these images to TvirtualImageList without touching the deeper layer in my codebase for FormSet.SmallImageListHandle.
Below is a sample code I have tried but didn't get success yet. Need to know if somehow I can assign Images to ImCol ?
Images := TImageList.Create(nil); // This is Timagelist
ImCol := TImageCollection.Create(nil);
imgclIte := TImageCollectionItem.Create(nil);
try
Images.Handle := FormSet.SmallImageListHandle;
//this line is existing code used as Timagelist
// need to assign this to Imagecollection
//ImCol.
Images.ShareImages := TRUE;
//FormIconsImageList.Images
// FormIconsImageListOld.AddImages(Images); // Old Approach with TImageList
FormIconsImageList.ImageCollection := ImCol; // Eventually I will set this
//Timagecollection to TvirtualImageList for Icons replacement
Related
I am trying to create a custom icon button with a transparent bitmap image, below the code.
The icon is stored in an ImageList connected to an ActionList.
bitmap := TBitmap.Create;
BmpObj := TMemoryStream.Create;
try
ImageList.GetBitmap(ActionList.Actions[i].ImageIndex, bitmap);
bitmap.Transparent := TRUE;
bitmap.TransparentColor := clWhite;
bitmap.Canvas.Brush.Color := clWhite;
bitmap.SaveToStream(BmpObj);
finally
BmpObj.Free;
bitmap.Free;
end;
I don't know what I am missing.. Anyone has an idea about this problem?
Without better knowledge about the components I asked about, I show the basic way of having transparent image on many Windows controls.
Take a TImageList and fill it with the images you want to use. The lower left pixel determines the transparent color. In my example black numbers are placed on white background.
On the button, set property Images to your ImageList and ImageIndex to a valid image number (0 .. ). The image will appear on the button, with the white colored areas transparent.
In the image below, I include a TImage with the bitmap so you can see the actual colors.
Note no code required.
Hi i have the following code to add an image from a Timage that for now is populated from a blob. My issue is this code does not add the image to the paintbox but rather to the form.
var
RectangleCanvas, RectanglePicture: TRectF;
BlobStream: TStream;
begin
BlobStream := qrypunchsheetitemphoto.CreateBlobStream(qrypunchsheetitemphoto.FieldByName('Photo'),TBlobStreamMode.bmRead);
imgviewimage.Bitmap.LoadFromStream(BlobStream);
fdrawbox:= TMyPaintBox.Create(panel1);
fdrawbox.Canvas.BeginScene;
fdrawbox.BitmapStamp := imgviewimage.Bitmap;
fdrawbox.Height := imgviewimage.Bitmap.Height;
fdrawbox.Width := imgviewimage.Bitmap.Width;
RectangleCanvas := RectF(10, 10, imgviewimage.Bitmap.Width, imgviewimage.Bitmap.Height);
RectanglePicture := RectF(10, 10, imgviewimage.Bitmap.Width, imgviewimage.Bitmap.Height);
fdrawbox.Canvas.DrawBitmap(imgviewimage.Bitmap, RectangleCanvas , RectanglePicture, 1);
fdrawbox.Canvas.EndScene;
fdrawbox.BringToFront;
BlobStream.Free;
TabControl1.ActiveTab := tabViewImage;
end;
end;
The FMX Paintbox is different to older Delphi Paintboxes. Previously you could put a Paintbox anywhere on your form and start drawing. The results would be within the confines of the Paintbox where you placed it.
The FMX Paintbox isn't like that and I don't understand their reasoning. I've been told it has a something to do with cross-platform compatibility and how devices handle canvas operations.
You can verify canvas width for yourself easily enough.
If you have a form width of 640 pixels and place a 50 x 50 Paintbox in the middle you'd expect drawing to occur in the middle.
Check it yourself;
ShowMessage(FloatToStr(Paintbox1.Width)); // Result will be 50
Now check Paintbox1.Canvas.Width and you'll get a different result.
ShowMessage(IntToStr(Paintbox1.Canvas.Width)); // Result is 640
When you pass parameters to drawing functions you need to take this into account and offset accordingly. I have read something about parental clipping having some effect, but I've not seen it work.
Another potential solution is to use a TPanel and draw on it's canvas.
I have some data stored inside my TImage Component. I want to save the image as an bitmap. Executing this code the TImage content gets white and only a bmp file with 0 bytes has been created on the harddisk. What is wrong with my code ?
MainStatusbar.SimpleText := 'save the image .... ';
if SaveDialog.Execute then
begin
Image1.picture.Bitmap.SaveToFile(SaveDialog.filename);
end;
MainStatusbar.SimpleText := 'done ';
TPicture is a container for multiple different types of images. If the current image is not a TBitmap, then Picture.Bitmap will not contain your image. When you refer to Picture.Bitmap your original image will be destroyed, and an empty TBitmap created. So, the obvious explanation in that Picture.Bitmap is empty when SaveToFile() is called.
You should be saving your image by calling SaveToFile on the Picture object instead:
Image1.Picture.SaveToFile(...);
If the original image is not a bitmap then calling Picture.Bitmap will erase the content and create an empty bitmap. Depending on the original picture format an automatic conversion (e.g. from an icon) may be possible, but has to be done outside of TImage.
If the TImage.Picture.Graphic property does not currently hold a TBitmap then accessing the TImage.Picture.Bitmap property will free the current Graphic and replace it with a blank TBitmap. This is documented behavior.
Since you want to save a bitmap, check if the current Graphic is already a TBitmap. If so, save it as-is. Otherwise create a temp TBitmap, assign the current Graphic to it, and then save it.
MainStatusbar.SimpleText := 'save the image .... ';
if SaveDialog.Execute then
begin
if Image1.Picture.Graphic is TBitmap then
Image1.Picture.Bitmap.SaveToFile(SaveDialog.FileName)
else
begin
Tmp := TBitmap.Create;
try
Tmp.Assign(Image1.Picture.Graphic);
Tmp.SaveToFile(SaveDialog.FileName);
finally
Tmp.Free;
end;
end;
end;
MainStatusbar.SimpleText := 'done ';
I want to add a bitmap to a TMenuItem created dynamically. With this code it doesn't work, I don't have the image on my menu. What's wrong?
procedure TForm3.FormCreate(Sender: TObject);
var
item : TmenuItem;
icon : TIcon;
begin
item := TMenuItem.Create(PopupMenu1);
item.Caption := 'coucou';
icon := TIcon.Create;
icon.LoadFromFile('d:\SmallIcon.ico');
icon.Height := 16;
icon.Width := 16;
item.Bitmap.Canvas.Draw(0,0,icon);
PopupMenu1.Items.Add(item);
end;
The Bitmap property on TMenuItem isn't the way to go here. You really should use image lists instead. This will allow you to share images between your UI elements in a manageable fashion.
Add the icon to a TImageList.
Set the Images property on the menu (i.e. PopupMenu1) to refer to the image list.
Set the image index of the menu item to the index of the icon in the list, i.e. 0 if it's the first image.
Of course, you really ought to be using actions too, in which case you simply need to set the ImageIndex for the action and the framework takes care of assigning it to the menu item.
As an aside, I would note that the Delphi implementation of Vista themed menus has a large number of subtle bugs, many related to drawing of images. However, these bugs are relatively minor in visual impact.
Add the line
item.Bitmap.SetSize(16,16);
as third one. Then it works.
So your code would look like this:
var
item : TmenuItem;
icon : TIcon;
begin
item := TMenuItem.Create(PopupMenu1);
item.Caption := 'coucou';
item.Bitmap.SetSize(16,16); // <--- set size of bitmap
icon := TIcon.Create;
icon.LoadFromFile('d:\SmallIcon.ico');
icon.Height := 16;
icon.Width := 16;
item.Bitmap.Canvas.Draw(0,0,icon);
PopupMenu1.Items.Add(item);
end;
Although I agree with David. Better use a TImageList.
a) You can't set TIcon dimensions once they have an image in them -- if your loaded icon isn't already 16x16 you'll get an exception, b) You don't indicate if your parent menu uses a TImageList (if so, you can't set individual images), c) by default, I don't think tmenuitem bitmaps have a particular size/color depth or anything else. You need to properly create a TBitmap to assign to the TMenuItem.Bitmap (assuming your parent menu doesn't use TImageLists).
I've spended hours for this (simple) one and don't find a solution :/
I'm using D7 and the TImageList. The ImageList is assigned to a toolbar.
When I populate the ImageList at designtime, the icons (with partial transparency) are looking fine.
But I need to populate it at runtime, and when I do this the icons are looking pretty shitty - complete loose of the partial transparency.
I just tried to load the icons from a .res file - with the same result.
I've tried third party image lists also without success.
I have no clue what I could do :/
Thanks 2 all ;)
edit:
To be honest I dont know exactly whats going on. Alpha blending is the correkt term...
Here are 2 screenies:
Icon added at designtime:
(source: shs-it.de)
Icon added at runtime:
(source: shs-it.de)
Your comment that alpha blending is not supported just brought the solution:
I've edited the image in an editor and removed the "alpha blended" pixels - and now it looks fine.
But its still strange that the icons look other when added at runtime instead of designtime. If you (or somebody else ;) can explain it, I would be happy ;)
thanks for you support!
To support alpha transparency, you need to create the image list and populate it at runtime:
function AddIconFromResource(ImageList: TImageList; ResID: Integer): Integer;
var
Icon: TIcon;
begin
Icon := TIcon.Create;
try
Icon.LoadFromResourceID(HInstance, ResID);
Result := ImageList.AddIcon(Icon);
finally
Icon.Free;
end;
end;
function AddPngFromResource(ImageList: TImageList; ResID: Integer): Integer;
var
Png: TPngGraphic;
ResStream: TStream;
Bitmap: TBitmap;
begin
ResStream := nil;
Png := nil;
Bitmap := nil;
try
ResStream := TResourceStream.CreateFromID(HInstance, ResID, RT_RCDATA);
Png := TPNGGraphic.Create;
Png.LoadFromStream(ResStream);
FreeAndNil(ResStream);
Bitmap := TBitmap.Create;
Bitmap.Assign(Png);
FreeAndNil(Png);
Result := ImageList.Add(Bitmap, nil);
finally
Bitmap.Free;
ResStream.Free;
Png.Free;
end;
end;
// this could be e.g. in the form's or datamodule's OnCreate event
begin
// create the imagelist
ImageList := TImageList.Create(Self);
ImageList.Name := 'ImageList';
ImageList.DrawingStyle := dsTransparent;
ImageList.Handle := ImageList_Create(ImageList.Width, ImageList.Height, ILC_COLOR32 or ILC_MASK, 0, ImageList.AllocBy);
// populate the imagelist with png images from resources
AddPngFromResource(ImageList, ...);
// or icons
AddIconFromResource(ImageList, ...);
end;
I had the exact same problems a couple of years ago. It's a Delphi problem. I ended up putting the images in the list at design time, even though I really didn't want to. I also had to use a DevExpress image list to get the best results and to use 32 bit color images.
As Jeremy said this is indeed a Delphi limitation.
One work around I've used for images that I was putting onto buttons (PNGs with alpha transparency in my case) is to store the PNGs as resources, and at run time paint them onto a button sized bitmap filled with clBtnFace. The bitmap was then used as the control's glyph.
Delphi's built in support for icons with alpha masks is very limited, however there's an excellent icon library kicon which may help.