我們?cè)赪indows98環(huán)境下執(zhí)行拷貝文件、查找文件等計(jì)算機(jī)耗時(shí)較長(zhǎng)的操作時(shí),Windows會(huì)顯示一個(gè)小 的動(dòng)畫,指示正在進(jìn)行的操作,與死板的靜止圖像相比增色不少。那么我們自己開發(fā)軟件時(shí),能否也 顯示一個(gè)這樣的動(dòng)畫提示呢?筆者開發(fā)了一個(gè)能夠在PB下調(diào)用的動(dòng)畫DLL,由于采用多線程編程,PB調(diào)用的DLL函數(shù)能夠及時(shí)將控制權(quán)交還給PB,不影響應(yīng)用系統(tǒng)的運(yùn)轉(zhuǎn)。
一、代碼與編譯選項(xiàng)
在C++Builder中創(chuàng)建一個(gè)空白的DLL項(xiàng)目。
創(chuàng)建一個(gè)空白的Form,修改它的屬性為:
BorderStyle=bsDialog
BorderIcons 的 子 屬 性 均 為False
FormStyle=fsStayOnTop
Position= poScreenCenter
Name=StatusForm
在Form上添加一個(gè)Win32下的Animate控件Animate1,修改它的屬性為Align=alTop
在Form上添加一個(gè)Standard 下的Button 控件Button_Cancel,再添加System下的Timer控件Timer1, 設(shè)置定時(shí)Interval時(shí)間位250,較快響應(yīng)用戶的取消請(qǐng)求。
因?yàn)镻B應(yīng)用系統(tǒng)與動(dòng)畫窗體代碼分別屬于兩個(gè)線程,不能采用PB線程直接關(guān)閉動(dòng)畫窗體線程的窗口, 否則會(huì)引起系統(tǒng)運(yùn)行不正常,因此采用PB線程設(shè)置關(guān)閉標(biāo)志,而動(dòng)畫線程采用Timer控件定時(shí)檢查標(biāo) 志,一旦檢測(cè)到關(guān)閉標(biāo)志,就關(guān)閉窗口,清除線程標(biāo)志,結(jié)束動(dòng)畫線程。
下面給出編碼及編碼原理:
(1)DLL主體代碼:
/ *DLL 主 體 代 碼
* 定 義DLL 公 用 變 量
*g_CommonAVI 對(duì)Animate 控 件
動(dòng) 畫 類 型 索 引
*gi_Canceled Button_Cancel
按 鈕 是 否 被 選 擇 過
*gi_AVIType 要 顯 示 的 動(dòng) 畫 類 型,
由DLL 輸 出 函 數(shù) 做 為 參 數(shù) 輸 入
*gi_RequestClose 請(qǐng) 求 動(dòng) 畫 線 程 關(guān) 閉 標(biāo) 志
*gi_WindowActive 動(dòng) 畫 窗 口 所 處 的 狀 態(tài)
*lpsWinTitle 動(dòng) 畫 窗 體 的 標(biāo) 題,
由DLL 輸 出 函 數(shù) 做 為 參 數(shù) 輸 入
*/
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 輸 出 函 數(shù) */
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){
}
/ * 動(dòng) 畫 線 程 執(zhí) 行 代 碼,
動(dòng) 畫 窗 體 的 定 時(shí) 器 控 件 會(huì) 關(guān) 閉 它,
清 除 窗 體 存 在 標(biāo) 志 后 結(jié) 束 線 程 的 運(yùn) 行
*/
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;
}
/ * 定 義 一 個(gè) 線 程 實(shí) 例 指 針 */
TFormThread *FormThread;
/ * 輸 出 函 數(shù) 代 碼 實(shí) 現(xiàn) 部 分
* DllEntryPoint 32 位DLL 入 口
* ShowStatusWindow 顯 示 動(dòng) 畫 窗 口,
它 通 過 創(chuàng) 建 一 個(gè) 線 程 來 創(chuàng) 建 窗 口,
避 免 由 于 窗 口 的MODAL 屬 性 而 使
控 制 權(quán) 不 能 及 時(shí) 的 返 還 給 調(diào) 用 者
* GetStatus 取 得“ 取 消” 狀 態(tài),
即 用 戶 有 沒 有 選 擇“ 取 消” 按 鈕
* CloseStatusWindow 關(guān) 閉 動(dòng) 畫 窗 口,
*/
__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;
}
一、代碼與編譯選項(xiàng)
在C++Builder中創(chuàng)建一個(gè)空白的DLL項(xiàng)目。
創(chuàng)建一個(gè)空白的Form,修改它的屬性為:
BorderStyle=bsDialog
BorderIcons 的 子 屬 性 均 為False
FormStyle=fsStayOnTop
Position= poScreenCenter
Name=StatusForm
在Form上添加一個(gè)Win32下的Animate控件Animate1,修改它的屬性為Align=alTop
在Form上添加一個(gè)Standard 下的Button 控件Button_Cancel,再添加System下的Timer控件Timer1, 設(shè)置定時(shí)Interval時(shí)間位250,較快響應(yīng)用戶的取消請(qǐng)求。
因?yàn)镻B應(yīng)用系統(tǒng)與動(dòng)畫窗體代碼分別屬于兩個(gè)線程,不能采用PB線程直接關(guān)閉動(dòng)畫窗體線程的窗口, 否則會(huì)引起系統(tǒng)運(yùn)行不正常,因此采用PB線程設(shè)置關(guān)閉標(biāo)志,而動(dòng)畫線程采用Timer控件定時(shí)檢查標(biāo) 志,一旦檢測(cè)到關(guān)閉標(biāo)志,就關(guān)閉窗口,清除線程標(biāo)志,結(jié)束動(dòng)畫線程。
下面給出編碼及編碼原理:
(1)DLL主體代碼:
/ *DLL 主 體 代 碼
* 定 義DLL 公 用 變 量
*g_CommonAVI 對(duì)Animate 控 件
動(dòng) 畫 類 型 索 引
*gi_Canceled Button_Cancel
按 鈕 是 否 被 選 擇 過
*gi_AVIType 要 顯 示 的 動(dòng) 畫 類 型,
由DLL 輸 出 函 數(shù) 做 為 參 數(shù) 輸 入
*gi_RequestClose 請(qǐng) 求 動(dòng) 畫 線 程 關(guān) 閉 標(biāo) 志
*gi_WindowActive 動(dòng) 畫 窗 口 所 處 的 狀 態(tài)
*lpsWinTitle 動(dòng) 畫 窗 體 的 標(biāo) 題,
由DLL 輸 出 函 數(shù) 做 為 參 數(shù) 輸 入
*/
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 輸 出 函 數(shù) */
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){
}
/ * 動(dòng) 畫 線 程 執(zhí) 行 代 碼,
動(dòng) 畫 窗 體 的 定 時(shí) 器 控 件 會(huì) 關(guān) 閉 它,
清 除 窗 體 存 在 標(biāo) 志 后 結(jié) 束 線 程 的 運(yùn) 行
*/
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;
}
/ * 定 義 一 個(gè) 線 程 實(shí) 例 指 針 */
TFormThread *FormThread;
/ * 輸 出 函 數(shù) 代 碼 實(shí) 現(xiàn) 部 分
* DllEntryPoint 32 位DLL 入 口
* ShowStatusWindow 顯 示 動(dòng) 畫 窗 口,
它 通 過 創(chuàng) 建 一 個(gè) 線 程 來 創(chuàng) 建 窗 口,
避 免 由 于 窗 口 的MODAL 屬 性 而 使
控 制 權(quán) 不 能 及 時(shí) 的 返 還 給 調(diào) 用 者
* GetStatus 取 得“ 取 消” 狀 態(tài),
即 用 戶 有 沒 有 選 擇“ 取 消” 按 鈕
* CloseStatusWindow 關(guān) 閉 動(dòng) 畫 窗 口,
*/
__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;
}

