Fill background by tiling with bitmap - delphi

In my FMX Application I have to fill the entire background area of my form using a Bitmap pattern.
The reason why I'm thinking to use this pattern is because the form is freely resizable by the user and whether I set a fixed image the stretch causes the loss of quality of the background.
Is there a way to use a small Bitmap pattern I can repeat (X and Y) to fill the whole form area according to the resizing?

The effect you are looking for is a Tile.
See TTilerEffect and FireMonkey_Image_Effects for documentation.
The properties HorizontalTileCount and VerticalTileCount controls how many times a bitmap will be replicated. Since these values are floats, you need to adapt their values when the form is rescaled.

Add a TImage to the form
Make all the other controls children of it (so they appear on top).
Set the image's Align to alClient.
Load the Bitmap.
Set the WrapMode to imTile.

Related

What does the CapInsets property of a FireMonkey TBitmapLink do for a FireMonkey style?

When creating a custom FireMonkey style, you often run into style objects, such as TButtonStyleObject, that include one or more properties (such as TButtonStyleObject.NormalLink) that are collections of TBitmapLinks. Each individual TBitmapLink defines three properties, CapInsets, Scale, and SourceRect. SourceRect contains the coordinates of a segment of a bitmap that will be used to draw some aspect of the control (see Using TBitmapLinks with the FireMonkey Style Designer for more detail).
My question is, what does CapInsets do?
I think it is something related how to paint a resizable component using a single bitmap. The CapInsets should represent the stretchable portion of the bitmap leaving apart, in example, the borders so they do not get too thin or too large when you resize the component.
Think about a button and a 25x50 px bitmap to be the backround. Think it is a single color rectangle with a little border. What if you resize the button to be 25x500 px? The left and right border will become too large (and no more proportional to the top and bottom border).
I found no documentation except this article in russian (translation to italian is very bad, the english one isn't so clear to me as well), look for the "Background" section http://habrahabr.ru/post/137851/
HTH

How to get a control that is underneath another control?

I am trying to create a basic map editor for fun which consists of a scrollbox and paintbox (to draw the grid).
In the OnMouseDown event for the paintbox I create images at runtime and add them inside the scrollbox, the grid paintbox is painted above the images ( because if the grid was at the back it just would not look good ).
Here is a sample screen:
My question would solve two of my problems in one.
I need to be able to drag and drop (to move) the images around at runtime.
I also need to be able to get the X and Y position of the image to display as information.
Here is where my problem lies, to solve the problems above I first need to get the Image under the mouse cursor. But because I paint my grid (paintbox) above the images, the cursor will only ever 'see' the paintbox grid, and not the underlying images.
I did experiment with copying the paintbox grid to a TImage but it came out all wrong and I was getting out of memory errors. The size of the maps could be quite large and so putting the grid onto a bitmap is not ideal due the memory and limitations etc.
The grid must go on the top, otherwise it would look something like this:
Which hides the grid, and I don't want that to happen.
So, how can I see past the paintbox and get to the images underneath, using FindVCLWindow or something similar?
Set the Enabled property of the PaintBox to False. That will let the mouse messages go through.
Further:
In the OnMouseDown event for the PaintBox I create images at runtime and add them inside the scrollbox
Change that to the OnMouseDown event on the ScrollBox. Adjust the coordinates by ScrollBox.[Horz/Vert]Scrollbar.Position.

Animated GIF in Firemonkey

I'm trying to display an animated GIF in a Firemonkey HD form using TImage but I do not see any methods for animation.
Using Vcl.Imaging.gifImg is not an option because types differ.
Can someone suggest a way to solve this problem or probably component to animate GIF images under Firemonkey?
The only way I find for now is:
create TGIFImage instance and load the GIF image
loop through gif.images:
a. save current image to stream
b. Image1.bitmap.loadFromStream [Image1 is FMX:TImage]
Is there any smarter solution?
You can use TBitmapListAnimation with a single image which has each frame of the animation inside a long strip. eg, if your animation has 4 frames and is 32px by 32px then you need to create an image 128px wide by 32px high and add each frame side by side...
Then add a TImage to the form (you don't have to load a bitmap into this)
Add a TBitmapListAnimation with the TImage as it's parent
Double click AnimationBitmap and load your animation image strip
Drop down PropertyName and pick Bitmap
Set AnimationCount to 4 and AnimationRowCount 1 for this example
Set enabled to true
TBitmapListAnimation has good control over animation frame rates, reversing, looping and interpolation. I couldn't find a way to get a .gif to animate in FireMonkey2 but if you have the means to convert an animated .gif into a 'cartoon strip' then this is a good way to do animations.
PS This is Delphi XE3...so can't say if these components existed in previous version.

Display secondary underlying image on a Imagelist?

I have a Image list assigned to a listview to display transparent images.
There is a slight issue with this regarding some transparent images that are added, and that is they are sometimes hard to see/find in the listview.
See this example image:
You will notice that the images (noticeably the mouse) is barely viewable, infact if a empty image was added you would not even see it, the number captions come to the rescue here to show there is something actually there.
But I would like to make the images visually easier to see. I thought maybe having another image underneath the transparent images would work - of course though it could not affect the actual image.
So with that in mind, I made a bitmap of a chessboard grid:
I feel this would be the most suitable way of representing transparent areas of the images just like Paint.NET etc does.
To further illustrate this example I have modified the original image to show how it would look, if we had the chessboard bitmap as the underlay image:
Having the chessboard there would indicate there is a list item there in the first place, and the bitmap of the chessboard grid could be darker or an altogether different kind of image. As I said earlier if there was no image you would see nothing at all, so better to show an empty chess grid or other bitmap than nothing.
So, how can I display a second image underneath the original images using a imagelist to give a result similar to the example above? The underneath image could be anything - just another loaded bitmap for example.
If you store the chessboard as the first image (with index 0) and make the overlay image from the current image in the OnGetImageIndex event handler, it will do what you want to. However I'm not sure how efficient is to make the overlay image every time the event is fired.
procedure TForm1.ListView1GetImageIndex(Sender: TObject; Item: TListItem);
begin
// make the overlay (with overlay index 1) from the
// image with index Item.Index + 1
ImageList1.Overlay(Item.Index + 1, 1);
// use the first image from the list as a background
Item.ImageIndex := 0;
// and assign just created overlay index for overlay
Item.OverlayIndex := 1;
end;
I seems that what you need is a TImageList with extra capabilities.
As a starting point, I suggests you to consider TImageListEx described in the book Inside Delphi 2006
Excerpt:
The TImageListEx component is a TImageList descendant that can use the
images from another image list to generate disabled images, which can
be used on toolbars and other user interface elements.
The TImageListEx component is a TImageList descendant that can use the
images from another image list to generate disabled images, which can
be used on toolbars and other user interface elements.
There are several benefits of the TImageListEx component:
It eliminates the need for creating disabled glyphs.
It eliminates the need for adding the disabled glyphs to an additional TImageList component at design time.
It can drastically reduce the size of the .dfm file and of the entire application, especially in large applications that use a lot of
glyphs.
It's extremely fast, taking only milliseconds to disable all images in an image list, even when there are number of images.
It's extremely lightweight. (If you add it to an application that already uses the standard TImageList component, it won't increase the
size of the executable at all, and if you add it to an application
that doesn't use the standard TImageList component, the overhead is
only 2 KB.)
It's far from your requirements but yet detailed enough to show how to extend TImageList.

How do I create nodes with transparent backgrounds in a TVirtualDrawTree?

I am deriving a custom control from TVirtualDrawTree and I am overriding the DoPaintBackground event to draw a background gradient effect for the tree view.
I am also overriding the DoBeforeItemPaint function so I can custom draw the tree view items. However, I can't quite manage to get the items to paint with a transparent background.
Looking into the source for TVirtualDrawTree, it looks as though the item is copied to a TBitmap image and then copied onto the canvas, however, I have tried editing the source and setting the transparency options on the bitmap itself and it still doesn't seem to be working.
I have also tried clearing the canvas before drawing e.g. Canvas.Brush.Style := bsClear and filling the item rect but no joy.
Don't do transparency, cheat!
Drawing the gradient sounds like a lot of work: draw it to a temporary bitmap so you don't need to re-generate it every time DoPaintBackgrdound() is called. Once you have the background in a bitmap you can BitBlt the relevant portion into the Canvas when you handle DoBeforeItemPaint, and you can BitBlt the bitmap to the whole virtual tree when you need the whole background.
This way you don't need to deal with expensive transparency yet for the end user it looks like your items had been painted using transparency. It's a win:win situation.

Resources