首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

ActiveX 控制項偵測 IE 工具列「停止」按鈕 (IOleCommandTarget::Exec)

     編輯:關於C++

背景

Internet Explorer 工具列上的「停止」按鈕 (Stop) 在使用者點擊時,會透過 IOleCommandTarget 介面向目前作用中的 ActiveX 控制項發送 OLECMDID_STOP 命令。控制項實作此介面即可接收通知,進而停止播放影音、中斷下載、取消動畫等長時間作業。

實作步驟 (MFC / ATL / 純 COM)

1. 標頭檔宣告


#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)
};

2. 實作檔


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_STOP23 (0x17)停止命令 ID (定義於 mshtmhst.h / ocidl.h)
CGID_ShellDocView{...}IE 文檔視圖命令群組 GUID
OLECMDF_SUPPORTED1命令受支援
OLECMDF_ENABLED2命令目前可用

其他常見 IE 命令 (同樣透過 IOleCommandTarget)

  • OLECMDID_REFRESH (重新整理)
  • OLECMDID_PRINT (列印)
  • OLECMDID_PROPERTIES (屬性)
  • OLECMDID_SAVEAS (另存新檔)
  • OLECMDID_ZOOM (縮放)

注意事項

  1. 僅在 IE/Edge IE 模式/使用 WebBrowser 控制項的宿主 中生效。Chrome、Firefox、Edge (Chromium) 不支援此機制。
  2. 控制項必須為 UI Active 狀態 (已啟用、取得焦點) 才會收到命令。
  3. QueryStatus 必須正確回報 SUPPORTED | ENABLED,否則 IE 不會發送 Exec。
  4. 現代 Web 開發建議改用 JavaScript API (MediaElement.pause(), fetch().abort(), AbortController),ActiveX 已淘汰。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved