明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

軟件打開畫面中打開狀態(tài)的顯示

[摘要]我們平時(shí)看到的很多軟件(PhotoShop,3DMax)都會在啟動畫面中顯示當(dāng)前正在啟動哪個(gè)模塊,并在模塊加載失敗時(shí)給予提示,這樣的好處是,可以讓比較專業(yè)的軟件使用者知道當(dāng)前軟件加載了哪些模塊,或者在軟件發(fā)生啟動錯(cuò)誤時(shí),讓用戶得以反饋是啟動的哪個(gè)模塊時(shí)發(fā)生了,以及在長時(shí)間的軟件啟動過程中,讓用戶知...
我們平時(shí)看到的很多軟件(PhotoShop,3DMax)都會在啟動畫面中顯示當(dāng)前正在啟動哪個(gè)模塊,并在模塊加載失敗時(shí)給予提示,這樣的好處是,可以讓比較專業(yè)的軟件使用者知道當(dāng)前軟件加載了哪些模塊,或者在軟件發(fā)生啟動錯(cuò)誤時(shí),讓用戶得以反饋是啟動的哪個(gè)模塊時(shí)發(fā)生了,以及在長時(shí)間的軟件啟動過程中,讓用戶知道軟件還在工作,避免用戶對其失去信息。。。

好了,說了那么多廢話,就來看看我是怎么制作這樣一個(gè)程序的,由于本人平時(shí)基本上都用Delphi來開發(fā),所以以下代碼也都是Delphi的,但是基本框架有了,相信要用其它語言實(shí)現(xiàn)也不會很難。另外,以下這些代碼是我在過去的歷次開發(fā)過程中組部提煉出來的,雖然還無法達(dá)到不修改即使用的地步,但是要修改的內(nèi)容也不會很多。。

我的這個(gè)類叫做TAppLoader,首先要做的是,讓它接管部分程序的初始化工作。
將工程dpr文件中的啟動代碼寫成這樣:
var
  GAppLoader:TAppLoader;

begin
  Application.Initialize;
  GAppLoader:=TAppLoader.Create();
  try
    if GAppLoader.DoLoad() then begin
      Application.Run;
    end;
  finally
    GAppLoader.Free;
  end;
end.
可以看到,所有的啟動代碼都在TAppLoader.DoLoad()函數(shù)中了,如果這個(gè)函數(shù)失敗,則會返回false,此時(shí)就跳過Application.Run();過程,直接跳出程序。
接下來,來看一下這個(gè)類的定義:
  TAppLoader = class (TObject)
  private
    FSplashForm: TfrmSplash;
    FManagerList:TList;
  protected
    procedure InitializeManager(var AManager;AManagerClass:TCustomManagerClass);
    procedure OnAppLoading(ASender:TObject;AEvent:String;ADelay:Integer=5);
  public
    constructor Create();
    destructor Destroy(); override;
    function DoLoad: Boolean;
  end;

除了剛才說到的DoLoad()函數(shù)外,還可以看到這么兩個(gè)函數(shù):InitializeManager()和OnAppLoading()。
在說明InitializeManager()函數(shù)前,需要先介紹這么一個(gè)類:
  TCustomManagerClass = class of TCustomManager;

  TCustomManager = class(TObject)
  private
    FOnAppLoading:TAppLoadingEvent;
  protected
    procedure Initialize();virtual;abstract;
    procedure Finalize();virtual;abstract;
    procedure DoAppLoading(AEvent:String);
    property OnAppLoading:TAppLoadingEvent read FOnAppLoading write FOnAppLoading;
  public
    constructor Create();virtual;
  end;
在我的程序中,將所有的全局的資源管理類都叫做TxxxManager,而TCustomManager就定義了這些類的一些基本行為。說道這里,可能還有必要解釋一下什么是資源管理類,說白了,也就是將整個(gè)軟件運(yùn)行期需要經(jīng)常訪問的資源、使用的功能都集中起來管理,比如我將數(shù)據(jù)庫連接叫做:TDataManager,將串口通訊功能類叫做:TCommManager,等等。。。

這個(gè)基類定義了Initialize()和Finalize()兩個(gè)虛方法,是用來讓TAppLoader啟動或關(guān)閉服務(wù)用的,這兩個(gè)方法不同與構(gòu)造與析構(gòu)函數(shù),它們初始化的不是類本身的資源,而是一些外部連接資源,(比如網(wǎng)絡(luò)連接,文件句柄,串口端口等等),它們可以允許在不銷毀對象的前提下,進(jìn)行重新連接,也就是說,除了在TAppLoader中會調(diào)用Initialize()和Finalize()方法,你也可以在軟件的使用過程中調(diào)用這兩個(gè)方法,(比如用戶選擇了新的串口端口號)。

接著,可以看到TCustomManager中有一個(gè)OnAppLoading事件,在Initialize()的過程中,實(shí)際的Manager類就可以調(diào)用該方法,在啟動畫面上顯示文字了。該事件實(shí)際會調(diào)用TAppLoader.OnAppLoading()方法,它的代碼如下:
procedure TAppLoader.OnAppLoading(ASender:TObject;AEvent:String;
        ADelay:Integer);
begin
  if Assigned(FSplashForm) then begin
    if Assigned(ASender) then begin
      FSplashForm.lbl1.Caption:=ASender.ClassName+': '+AEvent;
    end
    else begin
      FSplashForm.lbl1.Caption:=AEvent;
    end;
    FSplashForm.Update;
    if ADelay>0 then
      Sleep(ADelay);
  end;
end;
其中FSplashForm就是啟動畫面了,在TAppLoader.DoLoad()中調(diào)用各個(gè)Manager的Initialize()方法時(shí),這些Manager會根據(jù)自身當(dāng)前初始化的內(nèi)容,回調(diào)這個(gè)OnAppLoading()函數(shù),此時(shí)就可以在啟動畫面上顯示文字了。

實(shí)際的Manager類中只要調(diào)用DoAppLoading()方法,就可以將文字顯示到啟動畫面上了,如:
procedure TFileImageManager.Initialize();
var
  Directory:String;
  FindHandle:THandle;
  FindFileData:TWin32FindData;
begin
  Directory:=ExtractFilePath(ParamStr(0))+'decoders\';
  FindHandle:=FindFirstFile(PChar(Directory+'*.dcd'),FindFileData);
  if FindHandle = INVALID_HANDLE_VALUE then
    exit;
  repeat
    if (FindFileData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)<>FILE_ATTRIBUTE_DIRECTORY then begin
      DoAppLoading('Loading ' + FindFileData.cFileName);
      AddDecoder(Directory+FindFileData.cFileName);
    end;
  until not FindNextFile(FindHandle,FindFileData);
  Windows.FindClose(FindHandle);
end;

TAppLoader中還有這么一個(gè)函數(shù):
procedure TAppLoader.InitializeManager(var AManager;AManagerClass:TCustomManagerClass);
var
  Instance: TCustomManager;
begin
  Instance := TCustomManager(AManagerClass.NewInstance);
  TCustomManager(AManager) := Instance;
  try
    Instance.Create();
    FManagerList.Add(@AManager);
    Instance.OnAppLoading:=OnAppLoading;
    Instance.Initialize();
    Instance.OnAppLoading:=nil;
  except
    TCustomManager(AManager):= nil;
    raise;
  end;
end;
它用來啟動一個(gè)Manager,并將其加入TAppLoader的一個(gè)FManagerList列表中,在TAppLoader析構(gòu)時(shí),它會自動按照這個(gè)列表,來釋放所有的Manager。
在Manager的Initialize()結(jié)束后,比較保險(xiǎn)的是將它的OnAppLoading重新設(shè)為空,這樣如果在程序運(yùn)行過程中,由其它功能來調(diào)用Manager的Initialize()時(shí),就不會再回調(diào)到顯示啟動文字的部分了。

最后,看一下DoLoad()函數(shù):
function TAppLoader.DoLoad: Boolean;
begin
  Result:=false;
  Application.Title:='Ultra Album';
  FSplashForm:=TfrmSplash.Create(nil);
  try
    try
      FSplashForm.Show;
      OnAppLoading(nil,'Starting...');
      Sleep(100);

      InitializeManager(GOptionManager,TOptionManager);
      InitializeManager(GRdItemClassManager,TRdItemClassManager);
      InitializeManager(GImageManager,TFileImageManager);
      InitializeManager(GThemeManager,TFileThemeManager2);
      InitializeManager(GMaskManager,TFileMaskManager);

      OnAppLoading(nil,'Ending...',0);

      Application.CreateForm(TfrmMain, frmMain);
      if ParamCount>=1 then begin   //deal with the filename in the parameter
        FSplashForm.Hide;
        frmMain.Show;
        frmMain.DoOpenFile(ParamStr(1));
      end;

      Result:=true;
    except
      on E:Exception do begin
        MessageBox(Application.Handle,PChar(E.ClassName+':'+#13+#10+E.Message),
            PChar(Application.Title),MB_ICONERROR);
      end;
    end;
  finally
    FreeAndNil(FSplashForm);
  end;
end;
這個(gè)函數(shù)是我的一個(gè)軟件中的代碼,它首先構(gòu)造并顯示一個(gè)啟動畫面,然后使用InitializeManager()分別初始化了5個(gè)Manager類,其中的GOptionManager,GRdItemClassManager。。。都是全局對象,在今后需要訪問時(shí),都使用這個(gè)全局對象來進(jìn)行訪問,這里我沒有使用Singleton模式,因?yàn)槲矣X得這幾個(gè)對象都必須在程序主窗體創(chuàng)建前完全初始化,而Singleton的設(shè)計(jì)思路是在對象第一次使用時(shí)才創(chuàng)建它的實(shí)例,在我的這個(gè)使用中不需要這樣的功能。當(dāng)然,你也可以自己改造這些Manager類成為Singleton的,改動代碼不會很多。
最后,再將程序的主界面創(chuàng)建出來,可以看到這個(gè)主界面的創(chuàng)建代碼就是我們從dpr文件中刪除的那行。