Forum > Graphics

Trapping non-available resource

(1/2) > >>

J-G:
I've successfully fathomed how to dynamically determine the name of a resouce and load the bitmap into a TImage, including re-dimentioning that. However, I now need to trap the fact that the image wanted doesn't exist  ---  ie. I have images of Gears, but not every tooth-count, so if the tooth count is calculated at 66 then the file name will be 66T.png but that image doesn't exist as an RCDATA in the [Resourse] list.

I could of course manually create a list of available images in an array and check that before calling 'LoadFromResource' but I suspect that there should be a means by which I can [Read] the resource list, or at least check the existance in a similar way that I can check whether a file exists using {$I-} {$I+} and IOResult   -- which I have tried :

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$I-} tmp := tmp.LoadFromResource(Name); {$I+}  if IOResult <> 0 then    begin      Form1.MissingImage.Caption := Copy(Name,1,Length(name)-4)+' Image not available';    end  else... but does not trap it.

I've also tried at the point of creation ...

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  {$I-} tmp := TBGRAbitmap.create(Name); {$I+}  ... though I didn't think this would be successful even though it does use the 'Name'.

Am I simply barking up the wrong tree?  or is there a method I'm missing?

Handoko:
You can use exception.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.Button1Click(Sender: TObject);const  ImageName = 'IMG1';var  Image: TImage;begin  Image := TImage.Create(nil);  try    Image.Picture.LoadFromResourceName(HInstance, ImageName);  except    ShowMessage('Cannot find image named ' + ImageName + '.');  end;  Image.Free;end;
Read more:
https://www.freepascal.org/docs-html/ref/refch17.html
https://wiki.freepascal.org/Exceptions

J-G:
Thank Handoko, I've tried (and failed) to use [Try][Except] - probably because I don't (yet) fully understand the concept  :-[

This is my interpreation of your suggestion :

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---begin  Form1.MissingImage.Hide;  tmp := TBGRAbitmap.create(Name);  Try    tmp.LoadFromResource(Name);  except    begin      Form1.MissingImage.Caption := Copy(Name,1,Length(name)-4)+' Image not available';      Form1.MissingImage.Show;      Exit;    end  end;      dest := TBGRAbitmap.create;      BGRAReplace(dest, tmp.FilterRotate(PointF(X,Y),angle,true));     ... 
When the image IS available then it works perfectly, testing and then moving on to the 'dest:=' part but if the image doesn't exist it doesn't get into the [except] section.

This may well be because I'm not using the same "Image.Picture.LoadFromResourceName(HInstance, ImageName);"
method that you site.


Handoko:
Don't give up easily, friend.

Here is a working demo:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, Forms, Controls, Graphics, StdCtrls, ExtCtrls, BGRABitmap, uniError; type   { TForm1 }   TForm1 = class(TForm)    btn1: TButton;    btn2: TButton;    btn3: TButton;    Image1: TImage;    procedure btn1Click(Sender: TObject);    procedure btn2Click(Sender: TObject);    procedure btn3Click(Sender: TObject);  private    procedure LoadImage(const ResName: string);  end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.btn1Click(Sender: TObject);begin  LoadImage('IMG1');end; procedure TForm1.btn2Click(Sender: TObject);begin  LoadImage('IMG2');end; procedure TForm1.btn3Click(Sender: TObject);begin  LoadImage('IMG3');end; procedure TForm1.LoadImage(const ResName: string);var  tmpBitmap: TBGRABitmap;begin  tmpBitmap := TBGRABitmap.Create;  try    try      tmpBitmap.LoadFromResource(ResName);      Image1.Picture.Bitmap.Assign(tmpBitmap);    except      frmError.SetMessage(ResName + ' cannot be found.');      frmError.ShowModal;    end;  finally    tmpBitmap.Free;  end;end; end.
I personally rarely use exception. But for your case, because you create something in memory, you can't simply exit when exception happens. You should put a try-finally block (see line #64).

Download the file and run it. To better understand what will really show on user screen, you should run it directly from the binary, don't run it from your Lazarus IDE.

This demo will cause an exception if you click the third button 'IMG3' because the image doesn't exist in the resources.

J-G:

--- Quote from: Handoko on June 10, 2022, 07:19:41 pm ---Don't give up easily, friend.
--- End quote ---
:D :D  That I very seldom do!  - I'm known for my stubborn determination to get my way  ::)

--- Quote from: Handoko ---Here is a working demo:
--- End quote ---
Works perfectly (of course)

--- Quote from: Handoko ---I personally rarely use exception. But for your case, because you create something in memory, you can't simply exit when exception happens. You should put a try-finally block (see line #64).
--- End quote ---
As you can tell, I've also avoided the [Try][Except][Finally]  -  I did consider that a [Finally] might be needed but didn't know not to use [Exit].

I have solved the problem by using a referenced list (array) as a 'look-up'  but it's not a perfect solution since that list can be modified by the user without necessarily adding to the resource.

My latest 'trial' code - based again upon your excellent suggestion - though naturally including the extra code needed to complete the task in hand - is:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure Rotate(Pic:TImage;Name:string;Angle:single;X,Y:word;T:byte);Var  tmp, dest : TBGRABitmap;begin  tmp := TBGRAbitmap.create(Name);  try    try      tmp.LoadFromResource(Name);    except      Form1.MissingImage.Caption := Copy(Name,1,Length(name)-4)+' Image not available';      Form1.MissingImage.Show;    end;  finally    dest := TBGRAbitmap.create;    BGRAReplace(dest, tmp.FilterRotate(PointF(X,Y),angle,true));     dest.ReplaceTransparent(clRed);    Pic.Picture.Clear;    Pic.Picture.Bitmap.SetSize(tmp.Width,tmp.Height);    Pic.Picture.Bitmap.TransparentColor:=clRed;    Pic.Transparent:=true;     dest.Draw(Pic.Picture.Bitmap.Canvas,0,0);     application.ProcessMessages;    dest.free;    tmp.free;  end;end; 
It doesn't trap the missing image  - - -  well it throws an error when run under the IDE in Debug mode, so I assume that would mean the same directly from the .exe (your comment to run your program from the binary).

I'm obviously missing a 'key' to jumping out of the routine after line 11 : (Form1.MissingImage.Show;)   since even though the [Try] may have failed it will continue into the [Finally] section which I only want to happen if the [Try] is successful but I can't (yet) fathom how to accomplish that  :( :-[ :-[   

I can understand [If][Then][Else] but the [Try]..... is currently defeating my aging grey matter!

. . . . . . . .    Just 'thinking' . . . . . . .  If I put a boolean [True] in the [Finally] - or somewhere where [Try] has been successful - and use that to determine whether the rest of the code should be executed, would that work ??  . . . . . .   more testing needed :)


Navigation

[0] Message Index

[#] Next page

Go to full version