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

禁用 HTML 頁面右鍵選單:CHtmlView/CHtmlCtrl 兩種完整解決方案

     編輯:關於VC++

使用 CHtmlView 或 CHtmlCtrl 顯示 HTML 內容時,滑鼠右鍵會彈出 IE 預設選單(檢視原始碼、另存新檔等),存在資訊安全風險。本文提供兩種解決方案:簡單的 HTML 指令法與正規的 C++ 介面實作法。

方案一:HTML 指令法(最簡單、零程式碼)

在 HTML `` 標籤加入屬性:

<body oncontextmenu="return false">

<body oncontextmenu="ShowMyMenu(); return false">

瀏覽器引擎直接攔截右鍵事件,無需任何 C++ 程式碼修改。

方案二:C++ 正規實作法(IDocHostUIHandler 介面)

為何需要子類化 Internet Explorer_Server 視窗?

Spy++ 觀察視窗階層:

Dialog
  AfxFrameOrView42d  // CHtmlCtrl
    Shell Embedding
      Shell DocObject View
        Internet Explorer_Server  ← 真正接收輸入的視窗

標準訊息(WM_CONTEXTMENU、WM_RBUTTONDOWN)送往最底層的 Internet Explorer_Server,CHtmlCtrl 無法攔截。

取得 IE_Server HWND 演算法

static HWND GetLastChild(HWND hwndParent) {
    HWND hwnd = hwndParent;
    while (TRUE) {
        HWND hwndChild = ::GetWindow(hwnd, GW_CHILD);
        if (hwndChild == NULL) return hwnd;
        hwnd = hwndChild;
    }
    return NULL;
}

假設單一子視窗鏈結,取得最深層子視窗即為目標。

子類化實作步驟

  1. 建立 CMyIEWnd : public CWnd 重載 OnContextMenu 為空函數
  2. CHtmlCtrl 衍生類別加入 CMyIEWnd m_myIEWnd 成員
  3. 在 OnNavigateComplete2 中子類化:
    void CMyHtmlCtrl::OnNavigateComplete2(LPCTSTR strURL) {
        if (!m_myIEWnd.m_hWnd) {
            HWND hwnd = GetLastChild(m_hWnd);
            m_myIEWnd.SubclassWindow(hwnd);
        }
    }

重要風險警告

「這是非常規方式,微軟明確禁止。子類化 IE_Server 等於押上所有賭注,不當使用會導致災難性後果。正式專案請實作 IDocHostUIHandler 介面。」

  • 優點:功能強大,可攔截所有訊息
  • 缺點:非支援作法、版本相容性風險、記憶體洩漏風險、除錯困難
  • 必要時務必處理 UnsubclassWindow/ResubclassWindow 避免 HWND 變更導致崩潰

IDocHostUIHandler 正規作法方向

實作 IDocHostUIHandler::ShowContextMenu 回傳 S_OK 並設定 pGuid 為 NULL 即可禁用預設選單,支援自訂選單。需透過 QueryInterface 取得介面指標,複雜度較高但穩定安全。

總結建議

  1. 簡單需求:直接修改 HTML 加入 oncontextmenu="return false"
  2. 正式專案:投入資源實作 IDocHostUIHandler
  3. 原型驗證/學習:可嘗試子類化法,但嚴禁用於生產環境
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved