0

In Delphi 10.4, in a COM Server DLL ShellExtension project, I have added a DataModule to the project and placed a TImageList on the DataModule. The ImageList contains several images added at design-time. Now, from the main unit of the DLL project, I try to access an image in the ImageList:

procedure TMyShellExtension2.MyGetBitmap(ABitmap: Vcl.Graphics.TBitmap);
begin
  ABitmap.PixelFormat := pf24bit;
  ABitmap.Width := 128;
  ABitmap.Height := 128;
  DataModule.DataModule3.ilUrlPics.GetBitmap(0, ABitmap);
  CodeSite.Send('test');    
end;

The GetBitmap line seems to cause an error, as the following CodeSite.Send line is not being executed and the image is not assigned.

Obviously, my way of accessing the image from a TImageList on a DataModule inside a DLL is not correct.

On the other hand, when assigning a "self-made" BitMap, it does work:

ABitmap.PixelFormat := pf24bit;
ABitmap.Width := 128;
ABitmap.Height := 128;
ABitmap.Canvas.Brush.Color := clBlue;
ABitmap.Canvas.FillRect(Rect(0, 0, 127, 127));

Is there another working way of accessing an image inside a DLL? What am I doing wrong?

user1580348
  • 5,721
  • 4
  • 43
  • 105
  • Did you try catching exceptions (in case one is thrown by `GetBitmap`)? – Olivier Aug 08 '20 at 16:50
  • When trying to include `GetBitmap` inside `try except` with a `ShowMessage` statement, at runtime (windows File Explorer in this case is the host) I get an `Access Violation`. – user1580348 Aug 08 '20 at 17:18
  • You just need to debug it. Find out which memory access leads to the AV. You can do that using code site. – David Heffernan Aug 08 '20 at 17:27
  • Exactly. After having replaced `ShowMessage` by `CodeSite.Send` I got this exception: "...: Exception = EAccessViolation error raised, with message : Access Violation..." – user1580348 Aug 08 '20 at 17:29
  • I'll try this BEFORE `GetBitmap`: `CodeSite.Send('MyGetBitmap: IL Assigned?', Assigned(DataModule.DataModule3.ilUrlPics));` – user1580348 Aug 08 '20 at 17:37
  • `CodeSite` tells me that `DataModule.DataModule3` does not exist (Assigned = False)!!! So why a `DataModule` created at design-time does not exist at run-time in a `DLL`? – user1580348 Aug 08 '20 at 17:59
  • @user1580348: Perhaps its constructor raises an exception? – Andreas Rejbrand Aug 08 '20 at 18:09
  • 1
    @user1580348 because a DLL project doesn't have startup code in its EntryPoint to create design-time objects at runtime, like a Form GUI project does. So you will have to explicitly create the `TDataModule` object yourself. – Remy Lebeau Aug 08 '20 at 19:03
  • @AndreasRejbrand I don't think so. Maybe `DataModule` isn't supposed to be used in a DLL. But meanwhile, I have solved the problem by storing the Bitmaps with `Project → Resources and Images` and loading the Bitmap at run-time with `ABitmap.LoadFromResourceName`. This works! – user1580348 Aug 08 '20 at 19:05
  • 1
    That's might actually be a better approach; otherwise, probably Remy's remark is spot on. – Andreas Rejbrand Aug 08 '20 at 19:14
  • @RemyLebeau In the `OnCreate` event-handler of the `DataModule` unit? – user1580348 Aug 08 '20 at 19:17
  • 1
    @user1580348 no, I mean in the DLL's **entry point** (the `begin..end.` block of the project's main source file, or in a `DllProc` callback). And besides, *units* don't have events, *classes* do. However, in a DLL, using resources is a better solution than using a `TImageList` on a `TDataModule`. – Remy Lebeau Aug 08 '20 at 20:16
  • I want to say THANK YOU to ALL commentators who contributed their valuable knowledge to the community! This is a great community! – user1580348 Aug 09 '20 at 13:52
  • @AndreasRejbrand Regarding my answer for the question "From the IDE's Structure Panel, how to copy a TCard to the clipboard?" (https://stackoverflow.com/questions/63336038/from-the-ides-structure-panel-how-to-copy-a-tcard-to-the-clipboard/63338826), where you have edited my answer: Why is my answer no more accepted since you edited it? What did you edit in that answer? – user1580348 Aug 10 '20 at 17:37
  • @user1580348: You can always see the difference an edit made by clicking the ["edited N hours ago" text](https://stackoverflow.com/posts/63338826/revisions). In this case, you can see my edit comment "for users of screen readers, search engines, etc." and the actual edit: "enter image description here" was replaced by "MainForm". Every time you include an image on a web page, you should give it an alternative text for visually impaired people who use screen readers. And also to aid Google and other computer programs. If you put a picture of a black carrot on the web and someone searches... – Andreas Rejbrand Aug 10 '20 at 17:43
  • ...on Google for "black carrot", they won't find it without the alt text. So IMHO you should always provide a nice alt text. I often include alt texts several sentences long describing screenshots and other more complex images. So that's the edit I made. I am really surprised the edit affected the "accepted" status of the answer. I had no idea it would. Can you not tick it again? – Andreas Rejbrand Aug 10 '20 at 17:45
  • 1
    I gave you a +1 as "compensation". :) – Andreas Rejbrand Aug 10 '20 at 17:47
  • 1
    @AndreasRejbrand Thank you for your edit of my answer and for the explanation of the Alt text. I will use it in the future. And also thank you for your help in general! I have learned a lot from you. And you are a very friendly and constructive person! – user1580348 Aug 10 '20 at 20:23
  • @AndreasRejbrand Something must have gone wrong, there is no image description there: `[1]: https://i.stack.imgur.com/pqlfe.png` – user1580348 Aug 10 '20 at 20:34
  • @user1580348: Thank you for your kind words. Regarding the alt text: The alt text is stored at the point of reference (in the main part of the text): `[![MainForm][1]][1]`. The generated HTML of the page reveals that it is present: `MainForm` – Andreas Rejbrand Aug 10 '20 at 20:37

1 Answers1

0

As several commentators in this question have pointed out and as I have experienced myself, using resources as image-source in DLLs is a better methodology than "using a TImageList on a TDataModule" which would have to be explicitly instantiated in the DLL's entry point (as @RemyLebeau has pointed out).

So in this specific case I:

• Store the needed images as Bitmaps in Project → Resources and Images.

• Make sure to load the created resource e.g. with {$R MyShellExtensionDLL.res}.

• Load the Bitmaps at run-time with e.g.:

procedure MyGetBitmap(ABitmap: Vcl.Graphics.TBitmap);  
begin  
  ABitmap.PixelFormat := pf24bit;  
  ABitmap.Width := 128;  
  ABitmap.Height := 128;  
  ABitmap.LoadFromResourceName(HInstance,'BITMAP1');  
end;  
user1580348
  • 5,721
  • 4
  • 43
  • 105