青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

Internet Explorer編程簡述(六)

1、概述
Internet Explorer提供了非常開發的接口,使開發人員不僅可以把其瀏覽器核心嵌入應用程序,還可以通過各種接口以實現更深層的控制。本文就將介紹對瀏覽器進行高級控制的話題之一——自定義上下文菜單。

2、最簡單的情況
自定義的IE及WebBrowser的上下文菜單,最簡單的方式就是在注冊表的HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt下添加自定義的鍵值,步驟如下:
1) 添加一個新的鍵,其名稱即為將來顯示在上下文菜單中的菜單項名稱,如:
 HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\&Google Search
2) 將新增的鍵的默認值設置為一個包含腳本的網頁的URL(或文件路徑全名),該網頁中的腳本將在用戶點擊上下文菜單中的“Google Search”后被瀏覽器執行。

3)在新增的鍵下還可以新建一個二進制值Contexts,用以指定我們新增的菜單項針對特定的網頁對象是否出現,其取值可以是如下值的組合(邏輯或)

Context     Value
Default     0x1
Images     0x2
Controls    0x4
Tables     0x8
Text selection 0x10
Anchor     0x20

4) 還可以建立一個DWORD類型的Flags項并將其值設置為0x01,這將使得前述腳本在一個模態窗口中執行,就好像是通過window.showModalDialog調用的,但不同的是在腳本中仍然可以訪問window對象。
5) 實例腳本如下:

通過修改注冊表自定義菜單的方法適用于Internet Explorer和WebBrowser,也具有良好的擴展性。但我們如果希望執行的是不僅僅是腳本,二是自己的程序中代碼,這種方法就不適用了。

3、使用完全自定義的菜單
1)
IDocHostUIhandler接口提供了一個ShowContextMenu方法,在需要顯示上下文菜單之前,MSHTML引擎就會調用實現了IDocHostUIHandler接口的
宿主程序的ShowContextMenu方法。

HRESULTIDocHostUIHandler::ShowContextMenu(
  DWORD dwID,
  POINT *ppt,
  IUnknown *pcmdtReserved,
  IDispatch *pdispReserved
);

dwID參數的意義與Contexts的組合類似;ppt為菜單的彈出點屏幕坐標;pcmdtReserved接口指向 IOleCommandTarget接口,可用于檢測網頁對象的狀態和執行命令等操作。pdispReserved在IE5以上版本中指向的是網頁對象的 IDispatch接口,用以區分不同對象,比如我們可以這樣來獲得網頁對象的指針:

IHTMLElement *pElem;
HRESULT hr;
hr = pdispReserved->QueryInterface(IID_IHTMLElement, (void**)pElem);
if(SUCCEEDED (hr)) {
  BSTR bstr;
  pElem->get_tagName(bstr);
  USES_CONVERSION;
  ATLTRACE("TagName:%s\n", OLE2T(bstr));
  SysFreeString(bstr);
  pElem->Release();
}

如果我們在該方法中返回S_OK,則告訴MSHTML我們將使用自己的菜單(界面),如果是S_FALSE,則彈出默認的菜單。

2) 實現
原理清楚之后,實現起來非常簡單,和彈出一般的菜單沒什么兩樣,舉例如下,顯示主框架的“文件菜單”:

HRESULT CMyHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt, IUnknown * pcmdtReserved, IDispatch *)
{
 // 載入主菜單
 HMENU hMenuParent = ::LoadMenu( ::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME) );
 if (hMenuParent)
 {
  HMENU hMenu = ::GetSubMenu( hMenuParent, 0 ); // 取得“文件”子菜單
  if (hMenu)
  {
   // 顯示菜單
   TrackPopupMenuEx( hMenu,
    TPM_LEFTALIGN | TPM_TOPALIGN,
    ppt->x,
    ppt->y,
    ::AfxGetMainWnd()->m_hWnd,
    NULL );
  }
  ::DestroyMenu( hMenuParent );
 }
 return S_OK;
}

4、自定義標準上下文菜單
1)
原理
更多的時候我們希望能在瀏覽器原來菜單的基礎上作一些修改,如刪掉“查看源文件”,添加自己的菜單項,等等,而不是完全不要原始的菜單,怎么辦呢?借助MSDN提供的例子,我們來看看:

HRESULT CBrowserHost::ShowContextMenu(DWORD dwID, POINT *ppt,IUnknown *pcmdTarget,IDispatch *pdispObject)
{
 #define IDR_BROWSE_CONTEXT_MENU 24641
 #define IDR_FORM_CONTEXT_MENU 24640
 #define SHDVID_GETMIMECSETMENU 27
 #define SHDVID_ADDMENUEXTENSIONS 53

 HRESULT hr;
 HINSTANCE hinstSHDOCLC;
 HWND hwnd;
 HMENU hMenu;

 CComPtr spCT;
 CComPtr spWnd;

 MENUITEMINFO mii = {0};
 CComVariant var, var1, var2;
 hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
 hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
 hr = spWnd->GetWindow(&hwnd);//取得瀏覽器窗口句柄
 hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));
 if (hinstSHDOCLC == NULL)
 {
  // Error loading module -- fail as securely as possible
  return;
 }
 hMenu = LoadMenu(hinstSHDOCLC, MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
 hMenu = GetSubMenu(hMenu, dwID);
 // Get the language submenu
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
 mii.cbSize = sizeof(mii);
 mii.fMask = MIIM_SUBMENU;
 mii.hSubMenu = (HMENU) var.byref;
 // Add language submenu to Encoding context item
 SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
 // Insert Shortcut Menu Extensions from registry
 V_VT(&var1) = VT_INT_PTR;
 V_BYREF(&var1) = hMenu;
 V_VT(&var2) = VT_I4;
 V_I4(&var2) = dwID;
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
 // Remove View Source
 DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);//刪除“查看源文件”菜單項
 // Show shortcut menu
 int iSelection = ::TrackPopupMenu(hMenu,
  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD ,//返回用戶選擇的菜單命令ID
  ppt->x,
  ppt->y,
  0,
  hwnd,
  (RECT*)NULL);
 // Send selected shortcut menu item command to shell
 LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);//發送到Internet Explorer_Server進行內部處理。
 FreeLibrary(hinstSHDOCLC);
 return S_OK;
}

從 上面的例子我們看出,基本的方法就是根據“shdoclc.dll”文件中的菜單資源建立菜單,再通過來自pcmdTarget的 IOlcCommandTarget接口獲得“編碼”菜單以及HKEY_CURRENT_USER\Software\Microsoft\ Internet Explorer\MenuExt下的定義擴展菜單,然后以TPM_RETURNCMD標志調用TrackPopupMenu或 TrackPopupMenuEx彈出菜單,并將返回的菜單命令ID教給瀏覽器窗口進行處理。這種方法可以調用許多通過瀏覽器無法直接調用的命令和對話框 (參閱:《Internet Explorer 編程簡述(五)調用IE隱藏的命令》)。

所以,我們只需要在彈出菜單之前做一些自定義操作即可達到修改默認菜單的目的,如上面代碼中就用刪除了“查看源文件”菜單項。

2) 問題
如果我們不僅僅是刪除默認的菜單項或是修改了默認的菜單項,還添加了自己的菜單項,會出現什么情況呢?由于使用了類似于MFC中UpdateUI的機制,遇到不認識的CommandID,瀏覽器就會將其狀態設置為Disabled,所以我們自己添加的菜單是無法被選擇的。
可 以想到,如果把菜單狀態設置為Enabled,并通過TPM_RETURNCMD標志調用TrackPopupMenu或 TrackPopupMenuEx,再把返回的命令ID教給合適的窗口(如主框架窗口)去處理不就行了。關鍵點就在于如何把菜單狀態設置為 Enabled。

3) 實現
解決的辦法是截獲 WM_INITMENUPOPUP 消息,在菜單創建以后,尚未顯示之前修改菜單項狀態,那瀏覽器就沒有辦法了。截獲WM_INITMENUPOPUP消息則可使用子類化(subclass)的技術,前面通過IOleWindow接口我們得到了瀏覽器窗口的句柄hwnd,則可以這樣做:

HMENU g_hPubMenu = NULL;
WNDPROC g_lpPrevWndProc = NULL;

LRESULT CALLBACK CustomMenuWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 if (uMsg == WM_INITMENUPOPUP)
 {
  if (wParam == (WPARAM) g_hPubMenu)
  {
   ::EnableMenuItem( 自定義的菜單命令ID, MF_ENABLED | MF_BYCOMMAND );
   ::CheckMenuItem( 自定義的菜單命令ID, MF_BYCOMMAND);
   return 0;
  }
 }
 return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}

HRESULT CMyHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
//瀏覽器菜單句柄保存在g_hPubMenu中
......
// subclass瀏覽器窗口
g_lpPrevWndProc = (WNDPROC)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CustomMenuWndProc);
//m_SubclassWnd.SubclassWindow( hwnd );//MFC中用此方法更簡便

// Show shortcut menu
int iSelection = ::TrackPopupMenu(hSubMenu,
 TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
 ppt->x,
 ppt->y,
 0,
 hwnd,
 (RECT*)NULL);
// Unsubclass瀏覽器窗口
::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);
g_lpPrevWndProc = NULL;
//m_SubclassWnd.UnsubclassWindow();

if (iSelection == 自定義的菜單命令ID )
{
 ::SendMessage( ::AfxGetMainWnd()->m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lResult), 0x0), 0 );
}
else
{
 LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
......
}

在MFC 中則更為方便,從CWnd繼承一個窗口類,假設為CWebBrowserSubclassWnd,為CMyHtmlView添加一個 CWebBrowserSubclassWnd類型的成員變量m_SubclassWnd,在子類化和去除子類化時調用 m_SubclassWnd.SubclassWindow( hwnd )和m_SubclassWnd.UnsubclassWindow()即可。相應的WM_INITMENUPOPUP消息處理函數如下所示:

void CWebBrowserSubclassWnd::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
 CWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

 pPopupMenu->EnableMenuItem( 自定義的菜單命令ID, MF_ENABLED | MF_BYCOMMAND );
 pPopupMenu->CheckMenuItem( 自定義的菜單命令ID, MF_BYCOMMAND);
}

下面的圖片顯示了將“文字大小”菜單項添加到“編碼”菜單項的下面的效果。

5、新的問題
看完上面的代碼,我們又自然地想到瀏覽器編程中的另一個問題,那就是“編碼”菜單。我們指定,手動建立一個“編碼”菜單是比較麻煩的事,而且很難做到與瀏覽器上下文菜單上的“編碼”菜單一樣的效果。何不使用上述的方法讓瀏覽器自己建立“編碼”菜單和處理相應的命令呢?

具體實現請看下一篇文章《Internet Explorer 編程簡述(七)完美的“編碼”菜單》


參考資料
MSDN:Adding Entries to the Standard Context Menu
MSDN:How To Adding to the Standard Context Menus of the WebBrowser Control
MSDN:IDocHostUIHandler::ShowContextMenu Method
BeginThread.com:Custom WebBrowser Context Menus


posted on 2007-07-29 15:17 旅途 閱讀(988) 評論(0)  編輯 收藏 引用 所屬分類: BHO

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            米奇777超碰欧美日韩亚洲| 亚洲欧美国产精品桃花| 91久久精品久久国产性色也91 | 亚洲国产高清视频| 免费黄网站欧美| 性欧美精品高清| 宅男66日本亚洲欧美视频| 国产精品久久久久久av下载红粉| 亚洲一区二区三区精品视频| 久久久五月婷婷| 亚洲高清在线播放| 日韩视频不卡| 国产伦精品一区二区三区视频黑人 | 亚洲欧美日韩另类| 亚洲精品1区2区| 久久av资源网| 欧美亚洲视频| 久久精品国产精品亚洲精品| 久久精品国产一区二区电影| 国产一区二区三区在线观看视频 | 国内视频精品| 免费看av成人| 欧美天天在线| 99在线精品视频| 亚洲激情视频在线| 亚洲福利视频网| 国产亚洲欧美激情| 欧美亚洲日本网站| 日韩视频一区二区在线观看| 免费观看欧美在线视频的网站| 亚洲二区在线| 国产毛片久久| 午夜精品久久久久久99热软件| 亚洲国产激情| 亚洲综合日韩在线| 一区二区日韩精品| 国产伦精品一区二区| 久久久久久穴| 欧美成人一区二区在线| 日韩午夜在线电影| 国产精品一香蕉国产线看观看 | 久久嫩草精品久久久精品| 欧美福利一区二区| 久久婷婷久久| 日韩一级片网址| 久久久久久噜噜噜久久久精品| 亚洲国产精品久久久久秋霞影院| 中文国产一区| 狠狠爱成人网| 欧美绝品在线观看成人午夜影视 | 一区二区三区欧美日韩| **性色生活片久久毛片| 久久国产欧美精品| 久久艳片www.17c.com| 亚洲精品国精品久久99热| 国产精品国产| 久久久一二三| 亚洲视频在线一区观看| 免播放器亚洲一区| 玉米视频成人免费看| 久久久国产一区二区| 99riav国产精品| 一本色道久久88综合日韩精品| 国产一区二区三区在线观看视频| 午夜精品视频| 亚洲精品资源美女情侣酒店| 久久色在线观看| 亚洲免费视频在线观看| 亚洲欧洲一区二区三区| 狠狠色伊人亚洲综合网站色| 国产精品区二区三区日本| 欧美精品一区二| 久久免费视频一区| 午夜日韩在线| 一本大道久久精品懂色aⅴ| 亚洲福利免费| 一区二区电影免费观看| 国产精品视频999| 欧美日韩在线高清| 西西人体一区二区| 欧美国产日韩视频| 欧美成人资源| 一本色道久久88综合日韩精品| 国产精品网站一区| 国产精品久久久久久久久久免费看 | 正在播放亚洲一区| 精品99一区二区三区| 久久野战av| 先锋影音网一区二区| 在线综合亚洲欧美在线视频| 久久久久久尹人网香蕉| 欧美中文字幕在线视频| 亚洲激情一区二区| 亚洲人午夜精品免费| 亚洲国产一二三| 国产精品久久久久毛片大屁完整版| 欧美日一区二区在线观看| 欧美日韩精品一本二本三本| 欧美一进一出视频| 一区二区高清视频| 欧美大胆成人| 亚洲黄网站黄| 日韩小视频在线观看| 亚洲男人av电影| 性久久久久久| 99re66热这里只有精品4| 免费成人美女女| 欧美黑人国产人伦爽爽爽| 亚洲精品美女在线观看播放| 久久久久久伊人| 亚洲高清网站| 亚洲淫片在线视频| 久久九九免费| 欧美成人日韩| 久久国产精品久久w女人spa| 乱人伦精品视频在线观看| 午夜精品免费| 久久久久国色av免费观看性色| 欧美一区二区三区在线视频| 久久久久青草大香线综合精品| 一区二区三区**美女毛片| 欧美一级精品大片| 午夜欧美电影在线观看| 久久综合狠狠综合久久综青草| 欧美国产精品va在线观看| 久久久另类综合| 欧美日本一区二区高清播放视频| 国产免费观看久久黄| 91久久久精品| 亚洲第一在线视频| 欧美中在线观看| 久久aⅴ乱码一区二区三区| 亚洲人成网站精品片在线观看| 亚洲欧美日韩在线不卡| 欧美一区二区在线免费播放| 欧美日韩国产小视频| 黄色成人在线网址| 亚洲啪啪91| 亚洲私人黄色宅男| 亚洲一区二区精品在线观看| 一本色道久久综合狠狠躁的推荐| 亚洲精品美女91| 99国产精品久久久久老师| 日韩一级在线| 免费观看久久久4p| 西西人体一区二区| 国产精品高潮视频| 亚洲视频碰碰| 亚洲欧洲一区| 美女诱惑一区| 另类人畜视频在线| 国产精品美女一区二区| 91久久在线| 另类激情亚洲| 欧美一区二区免费| 久久婷婷影院| 国产亚洲欧美日韩一区二区| 国产精品久久久久免费a∨大胸| 国产精品欧美久久| 亚洲国产一区二区三区高清| 欧美一二区视频| 91久久午夜| 看欧美日韩国产| 国产人成精品一区二区三| 曰韩精品一区二区| 亚洲视频电影在线| 欧美成人精品激情在线观看| 久久婷婷国产综合国色天香| 欧美三级黄美女| 99re视频这里只有精品| 欧美一区网站| 亚洲经典三级| 性欧美8khd高清极品| 黄色在线成人| 亚洲午夜高清视频| 亚洲国产aⅴ天堂久久| 欧美激情四色 | 亚洲精品久久久一区二区三区| 亚洲午夜在线观看| 午夜国产不卡在线观看视频| 亚洲国产婷婷| 欧美精品少妇一区二区三区| 99pao成人国产永久免费视频| 久久三级视频| 亚洲一区日韩在线| 黄色日韩精品| 欧美 日韩 国产在线| 亚洲欧美国内爽妇网| 欧美日韩一级黄| 亚洲国产aⅴ天堂久久| 亚洲精品网站在线播放gif| 国产精品美女| 在线视频精品一区| 久久国产主播精品| 99在线|亚洲一区二区| 亚洲欧美视频在线| 亚洲国产va精品久久久不卡综合| 久久精品免费看| 欧美大尺度在线| 亚洲国产专区|