最近想在IS12製作的安裝包的安裝界面上實現一種定時功能:
當顯示一個界面後,即開始計時,定時10秒到時如果用戶還沒有任何操作則默認是NEXT,進入下一步,10秒之前用戶可做任何選擇。
查了help文檔中和time有關的所有搜索條目都沒有看到IS12與定時有關的任何函數,只有Delay(秒);安裝界面都是一個SD函數實現的,這裏爲了修改界面的動作,使用的是自定義對話框,由於只是希望在原有對話框的基礎上多一個10-0的倒數顯示,只要添加一個Text,所以這裏在use interface的Dialog中,選擇一個已定義的對話框,點擊Edit Dialog layout,添加一個Text Area,再右鍵Clone這個對話框,將複製的dialog rename爲MyDlg,在Installscript中添加自定義對話框MyDlg的腳本mydlg.rul
這裏使用的是EzDefineDialog ( szDialogName, szDLLName, szDialogID, nDialogID ); 定義這個對話框,WaitOnDialog ( szDlgName );顯示這個對話框,我查了很多資料,都是使用這個方式,所以我也採用這種方式。
對於定時功能,我做了大概以下3種探索:
1.使用Delay()函數
在WaitOnDialog 的default的返回值的處理中,使用Delay()來定時,
for nCount = 10 downto 1
Delay(1);//延時一秒
// Convert the number to a string.
nResult = NumToStr (strCount, nCount);
CtrlSetText( DLG_MYDLG, TIMETEXT, strCount);
endfor;
在for循環中,延時一秒則更新一下時間的顯示,存在的問題,Delay這種方式本來就是阻塞了,程序會一直停留在這裏無法響應任何其他的操作,可以正確的顯示窗口,也可以看到時間在倒數,但是就是不能響應其他的操作,即其他的操作必需要在10後才能得到相應,failed
2.Delay(1)+Sendmessage
由於是For循環阻塞了消息循環,所以就想到使用Sendmessage的方式來發送messge,
help中的文檔關於WaitOnDialog的返回值的第一項dialogControlID,是接收界面上的控件的WM_COMMAND message,於是發送
//延遲一秒之後,顯示時間
Delay(1);//延時一秒
// Convert the number to a string.
nCount= nCount-1;
nResult = NumToStr (strCount, nCount);
CtrlSetText( DLG_MYDLG,TIMETEXT, strCount);
hDlg = CmdGetHwndDlg(DLG_MYDLG);
if nCount = 0 then
//當計時結束時,發送NEXT信息
SendMessage (hDlg, WM_COMMAMD, RES_PBUT_NEXT, 0);
else
//倒計時沒有到10秒時,依然send message to the time ctrl
SendMessage (hDlg, WM_COMMAMD, TIMETEXT, 0);
endif;
但是總是不正確,WaitOnDialog沒有響應Sendmessage的任何消息,而只能顯示界面上的點擊等動作,我懷疑是不是IS中的Sendmessage用的不對啊,help中sendmessage的例子SendMessage (nHwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);也有試過都可以成功的。於是就想寫個dll來像這個DLG發送一個message。
3.DLL實現定時器,並向自定義對話框發送定時10秒到的message
DLL實現:
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime)
{
g_nCount--;
SetDlgItemInt(g_hDlg,g_nID,g_nCount,TRUE);
if ( g_nCount == 0 )
{
KillTimer(g_hDlg,1);
SendMessage(g_hDlg,WM_COMMAND,g_nIDBtn,0);
DestroyWindow( g_hDlg );
}
}
// This is export API
COUNTDOWN_API int RegisterCountdown(HWND hDlg,int nIDDlgItem,int nIDBtn)
{
SetDlgItemText(hDlg,nIDDlgItem,"10");
g_hDlg = hDlg;
g_nID = nIDDlgItem;
g_nIDBtn = nIDBtn;
SetTimer(hDlg,1,1000,TimerProc );
return 1;
}
在Installscript中調用這個API
nResult=UseDLL(SUPPORTDIR^"countdown.dll");
if nResult=0 then
MessageBox("動態庫加載成功",INFORMATION);
hDlg = CmdGetHwndDlg(DLG_MYDLG);
nResult=RegisterCountdown(hDlg,TIMETEXT,RES_PBUT_NEXT);
else
MessageBox("動態庫加載失敗",INFORMATION);
abort;
endif;
時間到時,依然不能響應NEXT的動作。
但是在MFC AP中調用這個函數則可以成功,響應button的動作。
於是,我沒轍了~~
看到有人使用:
hProgressBar = CtrlGetDlgItem(DLGNAME,CmdGetHwndDlg(DLGNAME),PROGRESSBAR_ID);
SendMessage(hProgressBar,PBM_SETPOS,20,0);
的方法,獲取到自定義的進度條的句柄,進而給這個進度條控件直接發送一些消息,可以成功,但是用的是2010,在IS12中CtrlGetDlgItem不被識別,也沒有辦法試一下,因爲我們只有IS12,不知道誰有2010可以試一下這個方法。
這次失敗主要是WaitOnDialog 阻塞了這些消息,但不知道大家都還有什麼好的方法,在IS中可以實現這個功能,請給我留言哦~~謝謝~~