編程實用篇—C++Builder開發動畫DLL

火星人 @ 2014-03-26 , reply:0



我們在Windows98環境下執行拷貝文件、查找文件等計算機耗時較長的操作時, Windows會顯示一個小 的動畫,指示正在進行的操作,與死板的靜止圖像相比增色不少。那麼我們自己開發軟體時,能否也顯示一個這樣的動畫提示呢?筆者開發了一個能夠在PB下調用的動畫DLL,由於採用多線程編程,PB調用的DLL函數能夠及時將控制權交還給PB,不影響應用系統的運轉。

一、代碼與編譯選項

在C++Builder中創建一個空白的DLL項目。

創建一個空白的Form,修改它的屬性為:

BorderStyle=bsDialog
BorderIcons 的 子 屬 性 均 為False
FormStyle=fsStayOnTop
Position= poScreenCenter
Name=StatusForm

在Form上添加一個Win32下的Animate控制項Animate1,修改它的屬性為Align=alTop

在Form上添加一個Standard 下的Button 控制項Button_Cancel,再添加System下的Timer控制項Timer1, 設置定時Interval時間位250,較快響應用戶的取消請求。

因為PB應用系統與動畫窗體代碼分別屬於兩個線程,不能採用PB線程直接關閉動畫窗體線程的窗口, 否則會引起系統運行不正常,因此採用PB線程設置關閉標誌,而動畫線程採用Timer控制項定時檢查標 志,一旦檢測到關閉標誌,就關閉窗口,清除線程標誌,結束動畫線程。

下面給出編碼及編碼原理:

(1)DLL主體代碼:

/ *DLL 主 體 代 碼
  * 定 義DLL 公 用 變 量
*g_CommonAVI 對Animate 控 件
動 畫 類 型 索 引
 *gi_Canceled Button_Cancel
按 鈕 是 否 被 選 擇 過
 *gi_AVIType 要 顯 示 的 動 畫 類 型,
由DLL 輸 出 函 數 做 為 參 數 輸 入
 *gi_RequestClose 請 求 動 畫 線 程 關 閉 標 志
 *gi_WindowActive 動 畫 窗 口 所 處 的 狀 態
 *lpsWinTitle 動 畫 窗 體 的 標 題,
由DLL 輸 出 函 數 做 為 參 數 輸 入
 */

   TCommonAVI g_CommonAVI[]={
    aviNone, aviFindFolder,
    aviFindFile, aviFindComputer,
   aviCopyFiles, aviCopyFile,
    aviRecycleFile, aviEmptyRecycle,
   aviDeleteFile
   };
   int gi_Canceled=0,gi_AVIType=0;
   int gi_RequestClose=0,gi_WindowActive=0;
   char lpsWinTitle[256];
   HWND hWndParent=NULL;

   / * 定 義DLL 輸 出 函 數 */
   extern 「C" __declspec(dllexport) int pascal Dll
? EntryPoint(HINSTANCE hinst, unsigned
long reason, void *);
   extern 「C" __declspec(dllexport) int pascal
ShowStatus Window
(int AVIType,LPSTR WinTitle,long hWnd);
extern 「C" __declspec(dllexport)
int pascal GetStatus(int ai_CloseWin);
extern 「C" __declspec(dllexport)
int pascal CloseStatusWindow();

    / * 定 義 線 程TformThread: */
   class TFormThread : public TThread{
   public: // User declarations
   __fastcall TFormThread(bool CreateSuspended);
   void __fastcall Execute(void);
   };
   __fastcall TFormThread::
TFormThread(bool CreateSuspended):
TThread(CreateSuspended){
   }
/ * 動 畫 線 程 執 行 代 碼,
動 畫 窗 體 的 定 時 器 控 件 會 關 閉 它,
清 除 窗 體 存 在 標 志 后 結 束 線 程 的 運 行
*/
   void __fastcall TFormThread::Execute(void){
   gi_WindowActive=1;
    StatusForm=new TStatusForm(NULL);

    StatusForm ->Caption=lpsWinTitle;
    StatusForm ->ShowModal();
    gi_WindowActive=0;
    delete StatusForm;
    gi_RequestClose=0;
   }
   / * 定 義 一 個 線 程 實 例 指 針 */
   TFormThread *FormThread;
    / * 輸 出 函 數 代 碼 實 現 部 分
    * DllEntryPoint 32 位DLL 入 口
    * ShowStatusWindow 顯 示 動 畫 窗 口,
它 通 過 創 建 一 個 線 程 來 創 建 窗 口,
避 免 由 於 窗 口 的MODAL 屬 性 而 使
控 制 權 不 能 及 時 的 返 還 給 調 用 者
    * GetStatus 取 得「 取 消」 狀 態,
即 用 戶 有 沒 有 選 擇「 取 消」 按 鈕
    * CloseStatusWindow 關 閉 動 畫 窗 口,
    */
   __declspec(dllexport) int WINAPI DllEntryPoint
(HINSTANCE hinst, unsigned long reason, void *)
   {
   return 1;
   }

 __declspec(dllexport) int pascal ShowStatusWindow
(int AVIType,LPSTR WinTitle,long hWnd){
 hWndParent=(HWND)hWnd;
memset(lpsWinTitle,0,sizeof(lpsWinTitle));
 strncpy(lpsWinTitle,WinTitle,sizeof(lpsWin Title) -1);
if (AVIType>0 & & AVIType<=8) gi_AVIType="AVIType;"    
FormThread="new" TFormThread(true);      
FormThread ->Priority = tpNormal;
    FormThread ->Resume();
   }

 __declspec(dllexport) int pascal GetStatus
(int ai_CloseWin){
   if (gi_Canceled)
   if (gi_WindowActive){
   gi_RequestClose=1;
    while(gi_RequestClose);
    }

    return gi_Canceled;
   }

   __declspec(dllexport) int pascal CloseStatusWindow(){
    if (gi_WindowActive){
   gi_RequestClose=1;
    while(gi_RequestClose);
   }

    return gi_Canceled;
   }

(2)窗體StatusForm 的代碼:

   TStatusForm *StatusForm;
   extern int gi_Canceled;
   extern int gi_AVIType;
   extern TCommonAVI g_CommonAVI[];
   __fastcall TStatusForm::TStatusForm
(HWND ParentWindow)
    : TForm(ParentWindow)
   {
    gi_Canceled=0;
   }
   // 取 消 按 鈕 並 不 直 接 關 閉 窗 體,
而 指 示 設 置 取 消 標 志, 供 調 用 者 查 看
   void __fastcall TStatusForm::Button_CancelClick
(TObject *Sender)
   {
   gi_Canceled=1;
   // ModalResult=mrCancel;
   }
     // 激 活 動 畫, 在FORMCREATE 事 件 中
   void __fastcall TStatusForm::FormCreate
(TObject *Sender)
   {
    Animate1 ->CommonAVI=g_CommonAVI[gi_AVI
Type];
    Animate1 ->Active = true;
   }
 
 extern int gi_RequestClose;
 // 定 時 器 事 件 檢 測 到 結 束 標 志 關 閉 窗 體
 void __fastcall TStatusForm::Timer1Timer
(TObject *Sender)
   {
    if (gi_RequestClose){
    ModalResult=mrOk;
    }
   }

設置編譯選項:打開Project Options 對話框,清除Linker屬性頁中的Use Dynamic RTL標誌,清除Packages屬性頁中的Build with runtime packages。 這樣只要單個DLL就可以運行了,而不必安裝 一些動態連接運行時間庫。

二、使用動畫DLL

1.定義:

   //Declare -> Global External Functions
   FUNCTION Long ShowStatusWindow
(Long AVIType,String WinTitle,long hWnd)
&LIBRARY 「STATWIN.DLL" ALIAS FOR
「Show StatusWindow"

   FUNCTION Long GetCancelStatus
(Long CloseWindow) &LIBRARY
「STATWIN.DLL" ALIAS FOR 「GetStatus"

   FUNCTION Long CloseStatusWindow() &
 LIBRARY 「STATWIN.DLL" ALIAS FOR
「CloseStatusWindow"

2.調用:

   long ll_EndTime
   // 顯 示 查 找 文 件 夾 動 畫
   ShowStatusWindow(2)
   setpointer(HourGlass!)

   ll_EndTime = Cpu() + 10 * 1000
   DO
    if GetCancelStatus(0)=1 then
    exit
   end if
    // 做 想 做 的 事 情
   LOOP UNTIL cpu() > ll_EndTime

   CloseStatusWindow()




[火星人 via ] 編程實用篇—C++Builder開發動畫DLL已經有145次圍觀

http://www.coctec.com/docs/linux/show-post-190245.html