Search code examples
c++imageerror-handlingc++buildervcl

How to handle an error when loading a picture into a TImage component?


I am using a VCL TImage component to load a picture from a file in Embarcadero C++Builder 11.3.

"pic.bmp" is a valid picture:

Image1->Picture->LoadFromFile("C:\\SomePath\\pic.bmp");

This fully works as intended.

However, "pic2.bmp" is a corrupted file:

Image1->Picture->LoadFromFile("C:\\SomePath\\pic2.bmp");

This displays a message box informing of an error and terminates the rest of the procedure.

What I really want to happen is that the error is caught and a "broken picture" is loaded and displayed in its place.

Code I have tried:

Ustr="C:\\SomePath\\pic2.bmp";

try
{
  Image1->Picture->LoadFromFile(Ustr);
}
catch (const exception& e)
{ 
  Ustr="C:\\SomePath\\ErrorPicture.png";
  Image1->Picture->LoadFromFile(Ustr); 
}

Image1 seems to ignore the handling and displays the error message box anyway.

I have tried:

Image1->NoErrMsg = true;

..in conjunction with the try/catch. On compiling for a test run, I received a compiler error:

no member named 'NoErrMsg' in 'Vcl::Extctrls::TImage'

I have also tried:

#include <SysUtils.hpp>
...
NoErrMsg = true;

But that didn't work.

I am obviously missing something and it is probably simple, but all of my Google-fu returns results on resolving images, not loading. I need to know how to handle a bad image quietly and behind the scenes, without bothering the user with a message box.


Solution

  • exception (lowercase e) usually refers to the std::exception base class (assuming you have a using statement somewhere that is pulling exception into the calling namespace). However, that is a C++-specific class, whereas the RTL/VCL is written in Delphi Pascal instead, which uses the System::Sysutils::Exception (uppercase E) base class for its exceptions.

    Remember, C++ is a case-sensitive language!

    Since you are not actually catching what LoadFromFile() is throwing, that is why you are still seeing the message box.

    Try this instead:

    try
    {
      Image1->Picture->LoadFromFile(Ustr);
    }
    catch (const Exception&) // <-- use Exception, not exception!
    { 
      Ustr="C:\\SomePath\\ErrorPicture.png";
      Image1->Picture->LoadFromFile(Ustr); 
    }
    

    Alternatively, fully qualify the class namespace so there is no confusion:

    catch (const System::Sysutils::Exception&)
    

    Alternatively, use a catch-all instead, since you are not doing anything with the Exception object (such as logging it, etc):

    catch (...)
    

    As for NoErrMsg, the compiler is correct, it is not a member of the TImage class, it is a global variable in System.hpp instead. But even so, the VCL doesn't actually use it, which is why setting it has no effect in your case. It is used only by System::WriteErrorMessage(), which is called only when a runtime error occurs during app startup or when calling System::Halt().