How to Assign a PNG image from TPngImageList to TuniImage? - delphi

Delphi XE2 Update 4
I have loaded several PNG files 128x128 on TPngImageList and I was to pick one, or either by index number or name, and assign to the TuniImage.Picture
TUniImage is from UniGUi framework. However it is a TPicture class. I guess should be the same of other TPictures that use it.

If you have a TPicture, as you say, then you assign its Graphic property like this:
Picture.Graphic := SomeGraphic;
So, where does SomeGraphic come from. I'm not clear which TPngImageList you are using. So, the code to extract a TGraphic from the TPngImageList might look like this:
SomeGraphic := PngImageList.PngImages[0].PngImage;

Related

Delphi. Clone an object [duplicate]

This question already has answers here:
How to copy the properties of one class instance to another instance of the same class?
(3 answers)
Closed 5 years ago.
Is it possible to clone an object with another reference?
Here is an example what i'm trying to do: I have a TLabel named Label1. Now I want to create a Label2, equals Label1, able to be changed without reflect each other.
Ps: I'm using TLabel as an example, I want to copy any object in another instance.
In the code below, I've tried changing the name, but the reference still the same, when a change one of them the other changes too.
var
cloneOfLabel1: TLabel;
begin
Label1.Caption := 'label 1';
cloneOfLabel1 := Label1;
cloneOfLabel1.Name := 'label2';
cloneOfLabel1.Caption := 'label 2';
cloneOfLabel1.Left := 0;
cloneOfLabel1.Top := Label1.Top+100;
That's possible to write Clone function for TComponent descendants:
function CloneComponent(aSource: TComponent): TComponent;
var mem: TMemoryStream;
begin
mem := TMemoryStream.Create;
try
mem.WriteComponent(aSource);
mem.Seek(0,soFromBeginning);
Result := mem.ReadComponent(nil);
finally
mem.free;
end;
end;
Note that only published properties gets copied that way and also some data which component saves through DefineProperties. Integers, floats, strings, enumerations and sets are cloned fine, but there could be problems with references: streaming system is designed for saving to file and reading from there, so no memory adresses get transfered, instead rather complicated actions are made to convert them into string paths including component owner and names. Usually you need to stream all the structure and only then some inner relationships would be saved.
If you are designer of classes which should be cloned, then overriding Assign method seems like more robust solution.
Good thing of this TComponent streaming solution is: you're able to clone some arbitrary component without knowing ahead, what class it is. For example, make a list of various components or some more complex structure and then get the full copy of each of them.
In your code, you are doing this:
cloneOfLabel1 := Label1;
However, this is merely acquiring a copy of its pointer, so it will still reference the original. It will not make a copy.
The closest you can get stems from TPersistent.Assign(), which needs to be implemented to actually copy the properties over. TLabel does not implement Assign, and so you cannot use it to create a clone either.
The answer is that you cannot arbitrarily clone objects, unless it inherits from TPersistent and implements Assign. And even then, you are at the mercy of the Assign procedure, so it will only copy those properties it was designed to copy. Name is certainly not one of those, especially since it's impossible to have two components with the same name. In fact, even if you do set a unique name to a cloned copy of a component, you cannot reference it by that, because it was created in run-time. Only design-time components can be referenced directly by their name.
On a side note, records can (by nature) be copied by using a simple :=, because records are value types instead of classes. However, I'm sure based on your example, that records are out of the question.

How to add Exif functionality to TBitmap?

I want to create a general purpose function that loads 'any' type of image (gif, jpg, bmp, png, etc) from disk and returns a bitmap.
function LoadGraph(FileName: string): TBitmap; {pseudocode}
begin
if FileIsJpeg then
jpeg.LoadFromFile;
Bitmap.Exif.Assign(Jpeg.Exif);
end;
The thing is that I need to have access to the Exif data when the input type is Jpeg.
So, I wanted to create a class helper like this:
TYPE
TBitmapHelper = class helper for TBitmap
public
FExifData: TExif;
end;
However, it seems that the Delphi compiler does not have this capability (yet?) as I get this compile error:
E2599 Field definition not allowed in helper type
How to achieve this?
There is quite complex hierarchy of graphic objects in Delphi intended to work with various image formats: TGraphic is abstract class for some image you can load from file, save to file and draw on canvas. TPicture is container for TGraphic which allows you to write just one line of code:
Picture.LoadFromFile(Filename);
and it will look up correct graphic class, create it and load your image.
So one of solutions for you would be to use TPicture instead of TBitmap. For TBitmap and its descendants TPicture will contain Bitmap property, while for the others you can draw on Canvas or assign Picture.Graphic to your TBitmap (works for TJPEGImage, TPNGImage, but still fails with TIcon).
If it's too bulky, for example, you need not just show image on screen but modify it in some way and not think each time how it's actually represented, I'd recommend to create descendant from TBitmap, not just helper, it's quite possible, you can pass such an object everywhere in program where TBitmap is expected, but now you can extend it with new fields. I'm going to do similar thing to add ICC profiles capability (supported in BitmapHeaderV5).

How to get the word under the cursor in a Windows Word editor or in a Pdf editor with using Delphi?

I'm trying to prepare a Delphi Project. In this project I need get the word which was selected by user in Windows Word editor or in Pdf editor. So far I saw some examples about getting the word under the cursor in Memo or in Notbook, but I need to get the word under the cursor in other editor like MsWord or AdobePdf editor.
This works for me using D7 and Word 2007:
procedure TForm1.GetSelectedText;
var
MSWord,
Selection,
SelectedText : OleVariant;
begin
try
MsWord := GetActiveOleObject('Word.Application');
except
try
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;
except
Exception.Create('Error');
end;
end;
Selection := MSWord.Selection;
if not VarIsEmpty(Selection) then begin
SelectedText := Selection.Text;
Caption := SelectedText;
end;
end;
Obviously, it would be trivial to re-write the above as a stand-along function and pass in a reference to an existing MSWord object, if you already have one elsewhere in your code.
Like I said in my comment, doing the equivalent in Acrobat/Pdf is a different technical question, requiring its own q. However, having investigated it, I don't think there's a straightforward method of doing it.
If you import the Acrobat type library into Delphi, giving you a unit Acrobat_Tlb.Pas, you'll see that it contains a COM object interface, CAcroPDDoc.
You can instantiate that object for the document currently active in Acrobat. However, one* of the weird things about Acrobat's COM object model is that it doesn't provide any useful access to the text contents, if any, in the document.
However, from the CAcroPDDoc interface, you can get access to Acrobat's internal JavaScript object for the document by using a call to CAcroPDDoc.GetJSObject.
Once you've got a reference to the JS object, you can do a very limited amount of text processing, in particular there's a method GetPageNthWord(Page, WordNum, StripWhiteSpace) that "does what it says on the tin". That's as far as I've got, implementation-wise (if you want to see the code, post a new question).
From there, if you have the time, know-how and inclination - and I currently don't - you can apparently retrieve another JS object representing the on-screen selection rectangle and by somehow comparing that with the coordinates of the various Nth words from GetPageNthWord, you can identify which of them is/are selected. Not QED, ISTM.
All of which is a sufficient performance that if it were me, I'd just tell the user to copy the selection to the clipboard, where it would be easy to pick up from Delphi code.
* - Sometimes working with the Acrobat automation I get the feeling that Adobe have gone out of their way to not make it easy to get at the text in a .PDF file. Whether that's anything to do with the possibly apocryphal story that originally PDF was conceived as a write-only medium, so that you could guarantee that you could put one in the field and be sure that it couldn't be modified, I don't know.

Delphi: Getting Copy/Paste to work

So I want to add a Copy/Paste function to my Delphi application that draws different shapes and does stuff with them.
Here's the on even handler for the Copy menu item:
procedure TForm1.Copy1Click(Sender: TObject);
begin
Clipboard.Open;
if SelectShape <> nil then
clipboard.SetComponent(SelectShape);
Clipboard.Close;
end;
And I get the error:
Incompatible types: 'TComponent' and 'TBaseShape'
TBaseShape is the ancestor class for all shapes in my application
I have no idea why it doesn't work...
Another approach would be to use a private data format, and serialize your object to XML or another easy-to-debug text-based structure, and put that onto the clipboard. It would also be useful/polite to render your object (assuming it's a graphic of some sort) onto a Bitmap, and place that on the clipboard as well (clipboard can hold multiple/many formats simultaneously) so that the user can paste into paint, word, etc., and get "something".
Here's a question that does something along these lines, using GPX data
How to paste a custom format clipboard data into a TMemo?

How to pass Bitmap into DLL function in C++ and Delphi?

I want to create a DLL plugins to use with Delphi and other languages (mostly C++).
How can I pass bitmaps in a C++ and Delphi-friendly way? Can it just be a handle to the Delphi TBitmap? C++ program should be able to decode it using WinApi, right?
You cannot pass a Delphi TBitmap object since that is only meaningful to Delphi code. What you need to pass is an HBITMAP, a handle to a Windows bitmap.
The Delphi TBitmap class is just a wrapper around the Windows bitmap and can provide HBITMAP handles. The thing you need to watch out for is the ownership of those handles.
If you have a Delphi TBitmap you can get an HBITMAP by calling the ReleaseHandle method of a TBitmap. The handle returned by ReleaseHandle is no longer owned and managed by the TBitmap object which is exactly what you want. You pass that handle to the C++ code and let it become the owner. It is responsible for disposing of that handle.
The documentation for ReleaseHandle says:
Returns the handle to the bitmap so that the TBitmap object no longer
knows about the handle.
Use ReleaseHandle to disassociate the bitmap from the bitmap handle.
Use it when you need to give a bitmap handle to a routine or object
that will assume ownership (or destroy) the bitmap handle.
In the other direction your Delphi code would receive an HBITMAP from the C++ code and take on ownership. Do that by assigning to the Handle property of a TBitmap instance.
The details will vary from language to language, but no matter what, all will be able to deal with an HBITMAP.

Resources