我們在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()
[火星人
]
編程實用篇—C++Builder開發動畫DLL 已經有632 次圍觀
本文地址: http://coctec.com/docs/linux/show-post-190245.html