Internet Explorer 工具列上的「停止」按鈕 (Stop) 在使用者點擊時,會透過 IOleCommandTarget 介面向目前作用中的 ActiveX 控制項發送 OLECMDID_STOP 命令。控制項實作此介面即可接收通知,進而停止播放影音、中斷下載、取消動畫等長時間作業。
#include <ocidl.h> // IOleCommandTarget, OLECMDID_STOP
class CMyOleControl : public COleControl // 或 CComControl, IUnknown 實作
{
// ... 既有成員 ...
protected:
// 宣告巢狀類別實作 IOleCommandTarget
class CmdTargetObj : public IOleCommandTarget
{
public:
STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup, ULONG cCmds,
OLECMD rgCmds[], OLECMDTEXT* pcmdtext);
STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
VARIANTARG* pvaIn, VARIANTARG* pvaOut);
};
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(CmdTarget, IOleCommandTarget)
STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup, ULONG cCmds,
OLECMD rgCmds[], OLECMDTEXT* pcmdtext);
STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
VARIANTARG* pvaIn, VARIANTARG* pvaOut);
END_INTERFACE_PART(CmdTarget)
};
BEGIN_INTERFACE_MAP(CMyOleControl, COleControl)
INTERFACE_PART(CMyOleControl, IID_IOleCommandTarget, CmdTarget)
END_INTERFACE_MAP()
// IUnknown 轉發 (MFC 巨集自動處理,ATL 需手寫)
ULONG FAR EXPORT CMyOleControl::XCmdTarget::AddRef()
{
METHOD_PROLOGUE(CMyOleControl, CmdTarget)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CMyOleControl::XCmdTarget::Release()
{
METHOD_PROLOGUE(CMyOleControl, CmdTarget)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CMyOleControl::XCmdTarget::QueryInterface(REFIID iid, void** ppv)
{
METHOD_PROLOGUE(CMyOleControl, CmdTarget)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppv);
}
//---------------------------------------------------------------------------
// QueryStatus: 瀏覽器詢問命令是否支援/啟用
//---------------------------------------------------------------------------
STDMETHODIMP CMyOleControl::XCmdTarget::QueryStatus(
const GUID* pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT* pcmdtext)
{
METHOD_PROLOGUE(CMyOleControl, CmdTarget)
// 僅處理標準命令群組 (NULL 或 CGID_ShellDocView)
if (pguidCmdGroup == NULL || IsEqualGUID(*pguidCmdGroup, CGID_ShellDocView)) {
for (ULONG i = 0; i < cCmds; ++i) {
if (rgCmds[i].cmdID == OLECMDID_STOP) {
rgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
return S_OK;
}
}
}
return OLECMDERR_E_UNKNOWNGROUP;
}
//---------------------------------------------------------------------------
// Exec: 執行命令 - 核心處理停止按鈕
//---------------------------------------------------------------------------
STDMETHODIMP CMyOleControl::XCmdTarget::Exec(
const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
VARIANTARG* pvaIn, VARIANTARG* pvaOut)
{
METHOD_PROLOGUE(CMyOleControl, CmdTarget)
if (nCmdID == OLECMDID_STOP) {
// ========== 使用者點擊 IE 停止按鈕 ==========
// 在此處理:停止影音播放、取消非同步下載、終止動畫計時器等
pThis->OnStopCommand(); // 自訂處理函式
return S_OK;
}
return OLECMDERR_E_NOTSUPPORTED;
}
//---------------------------------------------------------------------------
// 控制項自訂停止處理
//---------------------------------------------------------------------------
void CMyOleControl::OnStopCommand()
{
// 範例:停止背景音樂
if (m_pMediaPlayer) m_pMediaPlayer->Stop();
// 範例:取消非同步下載
if (m_hDownloadThread) {
m_bCancelDownload = TRUE;
WaitForSingleObject(m_hDownloadThread, 2000);
}
// 範例:停止動畫 Timer
KillTimer(ANIM_TIMER_ID);
}
| 常數 | 值 | 說明 |
|---|---|---|
OLECMDID_STOP | 23 (0x17) | 停止命令 ID (定義於 mshtmhst.h / ocidl.h) |
CGID_ShellDocView | {...} | IE 文檔視圖命令群組 GUID |
OLECMDF_SUPPORTED | 1 | 命令受支援 |
OLECMDF_ENABLED | 2 | 命令目前可用 |
OLECMDID_REFRESH (重新整理)OLECMDID_PRINT (列印)OLECMDID_PROPERTIES (屬性)OLECMDID_SAVEAS (另存新檔)OLECMDID_ZOOM (縮放)QueryStatus 必須正確回報 SUPPORTED | ENABLED,否則 IE 不會發送 Exec。