Loading Resources

Introduction

Loading resources such as images is asynchronous, proceeding in the background, so you need to be careful not to use one that has not yet been loaded. This demonstration is based on Primož Gabrijelčič's splash screen on his Smart Programmer website, with added code to load and display a single image as an example.

Following the clear instructions, we added a panel and a label to SplashForm. We added a PaintBox control and two buttons (btnPart and btnWhole) to Form1 then created the Image control in code. We added to Resources the image sms_ide.png:

SMS IDE

SMS IDE

You can see the code assigned to btnPart.OnClick to display part of an image. Parameters 2 to 5 of DrawImageF define the rectangle to be copied from the image; the x and y coordinates of the top left corner then its width and height. The remaining four parameters are the x and y coordinated of the destination rectangle followed by its width and height. To display the whole image at its original size DrawImageF takes as parameters the image handle followed by the x and y coordinates of the destination rectangle.

Code of Project File for Version 3.0 of Smart Mobile Studio

See below a trimmed-down project file for Version 3.0 of Smart Mobile Studio. We have syntax-highlighted the Smart Pascal code of both forms. Interestingly, changing the line <object type="TW3Form"> to <object Type="TW3Form"> is enough to cause the project file to be rejected (with the message "Exception Exception Class type mismatch! Should be TW3Form, but was ".

<SMART>
  <Project version="3" subversion="0">
    <Name>Splash</Name> 
    <Options>
      <Compiler />
      <Codegen>
        <Obfuscation>1</Obfuscation>
        <Devirtualize>1</Devirtualize>
        <MainBody>1</MainBody>
        <CodePacking>1</CodePacking>
        <SmartLinking>1</SmartLinking>
      </Codegen>
      <ConditionalDefines />
      <Linker>
        <CompressCSS>1</CompressCSS>
        <ExternalCSS>0</ExternalCSS>
        <Theme>default.css</Theme>
        <EmbedJavaScript>1</EmbedJavaScript>
      </Linker>
      <Output>
        <JavaScriptFileName>main.js</JavaScriptFileName>
        <HtmlFileName>Splash.html</HtmlFileName>
        <OutputFilePath>www\</OutputFilePath>
      </Output>
      <Import />
      <Execute />
    </Options>
    <Files>
      <File type="main">
        <Name>Splash</Name>
        <Source>
          <![CDATA[uses SmartCL.System, uSplash, Form1, SplashForm;

  var Application := TApplication.Create;
  Application.RunApp;
]]>
        </Source>
      </File>
      <File type="unit">
        <Name>uSplash</Name>
        <Source>
          <![CDATA[unit uSplash;

interface

uses 
  Pseudo.CreateForms, SmartCL.System, SmartCL.Components, SmartCL.Forms, SmartCL.Application, Form1, SplashForm;

type
  TApplication  = class(TW3CustomApplication)
  end;

implementation

end.]]>
        </Source>
      </File>      
      <File type="form">
        <Name>Form1</Name>
        <Source>
          <![CDATA[
unit Form1;        

interface

uses 
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms, SmartCL.Fonts, SmartCL.Borders, SmartCL.application, SmartCL.Controls.PaintBox, SmartCL.Controls.Image, SmartCL.Controls.Button;

type
  TForm1=class(TW3Form)
  private
    {$I 'Form1:intf'}
    FFirst : boolean;
    FImage : TW3Image;
  public
    procedure FormActivated; override;
  protected
    procedure InitializeObject; override;
    procedure FinalizeObject; override;
  end;

implementation

procedure TForm1.FormActivated;
begin
  inherited;
  if FFirst then
    begin
      FFirst := False;
      Application.ShowModal('SplashForm', 'SplashPanel', '');
    end;
end;

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  FImage := TW3Image.Create(nil);
  FImage.LoadFromURL('res/sms_ide.png');
  FFirst := true;   
  btnPart.OnClick := procedure(Sender : TObject)
    begin
      pb.Canvas.FillStyle := 'rgb(0, 0, 0)'; // Clear
      pb.Canvas.FillRectF(0, 0, pb.Width, pb.Height);
      pb.Canvas.DrawImageF(FImage.Handle, 5, 150, 250, 310, 20, 0, 250, 310);
    end;

  btnWhole.OnClick := procedure(Sender : TObject)
    begin
      pb.Canvas.DrawImageF(FImage.Handle, 0, 0);
    end;
end;
 
procedure TForm1.FinalizeObject;
begin
  inherited;
  FImage.Free;
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.
]]>
        </Source>
        <Design>
          <![CDATA[<?xml version="1.0" encoding="utf-16"?>
<Form version="3" subversion="0">
  <object type="TW3Form">
    <Caption>Main Form</Caption>
    <Name>Form1</Name> 
    <object type="TW3PaintBox">
      <Name>pb</Name>
      <Left>0</Left>
      <Top>48</Top>
      <Width>1000</Width>
      <Height>552</Height>       
    </object>
    <object type="TW3Button">
      <Name>btnPart</Name>
      <Left>21</Left>
      <Top>8</Top>
      <Width>200</Width>
      <Height>24</Height>       
      <Caption>Part Of Image</Caption>
    </object>
    <object type="TW3Button">
      <Name>Btnwhole</Name>
      <Left>240</Left>
      <Top>8</Top>
      <Width>200</Width>
      <Height>24</Height>
      <caption>Whole Image</caption>
    </object>
  </object>
</Form>]]>
        </Design>
        <AutoCreate>
          <IsAutoCreate>1</IsAutoCreate>
          <IsMainForm>1</IsMainForm>
          <Order>1</Order>
        </AutoCreate> 
      </File>
      <File type="form">
        <Name>SplashForm</Name>
        <Source>
          <![CDATA[
unit SplashForm;

interface

uses 
  SmartCL.system, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms, SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Panel, System.Time, SmartCL.Controls.Label, SmartCL.Controls.Image;

type
  TSplashForm=class(TW3Form)
  private
    {$I 'SplashForm:intf'}
  public
    procedure FormActivated; override;
  protected
    procedure InitializeObject; override;
    procedure Resize; override;
  end;

implementation

procedure TSplashForm.FormActivated;
begin
  var Timer := TW3Timer.Create(Self);
  Timer.Delay := 3000;
  Timer.OnTime := lambda Application.HideModal(mrOK); end;
  Timer.Enabled := True;
end;

procedure TSplashForm.InitializeObject;
begin
  inherited;
  {$I 'SplashForm:impl'}
  W3Label1.Font.Size := 24;
  Height := ClientHeight;
  Width := ClientWidth;
end;

procedure TSplashForm.Resize;
begin
  inherited;
  SplashPanel.Height := Height;
  SplashPanel.Width := Width;
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TSplashForm); 
end.
]]>
        </Source>
        <Design>
          <![CDATA[<?xml version="1.0" encoding="utf-16"?>
<Form version="3" subversion="0">          
  <object type="TW3Form">
    <name>SplashForm</name>
    <Caption>Splash Form</Caption>
    <object type="TW3Panel">
      <name>SplashPanel</name>
      <Left>8</Left>
      <Top>0</Top>
      <Width>800</Width>
      <Height>600</Height>
      <object type="TW3Label">
        <Name>W3label1</Name>
        <Left>88</Left>
        <Top>112</Top>
        <Width>640</Width>
        <Height>64</Height>
        <Caption>Splash Screen (Image Loading)</Caption>
      </object>
    </object>
  </object>  
</Form>]]>
        </Design>        
        <AutoCreate>
          <IsAutoCreate>1</IsAutoCreate>
          <IsMainForm>0</IsMainForm>
          <Order>2</Order>
        </AutoCreate>  
      </File>
    </Files>
    <Target>Browser</Target>
    <Generator>Visual Components Project</Generator>
  </Project>
</SMART>
Programming - a skill for life!

Useful for games, with drawing routines (including transforms and text fonts), images, sprites and WebGL 3D graphics. Now includes Box2D physics and rendering by Pixi.js.