C# 在internet explorer BHO中添加浏览器操作按钮
所以。我正在IE中处理一个BHO,我想添加这样一个:C# 在internet explorer BHO中添加浏览器操作按钮,c#,internet-explorer,winapi,bho,browser-action,C#,Internet Explorer,Winapi,Bho,Browser Action,所以。我正在IE中处理一个BHO,我想添加这样一个: BOOL FindFavoritesAndToolsBar(HWND mainWnd, HWND* addressBarWnd, HWND* cmdTargetWnd) { mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "WorkerW" ), NULL ); mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "ReBarWindow32" )
BOOL FindFavoritesAndToolsBar(HWND mainWnd, HWND* addressBarWnd, HWND* cmdTargetWnd)
{
mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "WorkerW" ), NULL );
mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "ReBarWindow32" ), NULL );
*cmdTargetWnd = ::FindWindowEx
mainWnd, NULL, TEXT( "ControlBandClass" ), NULL );
if( *cmdTargetWnd )
*addressBarWnd = ::FindWindowEx(
*cmdTargetWnd, NULL, TEXT( "ToolbarWindow32" ), L"Favorites and Tools Bar" );
return cmdTargetWnd != NULL;
}
在InternetExplorer中,它看起来像
我找到的唯一教程和文档是关于创建工具栏项目的。没有人提到这一选择。我知道这是可能的,因为crossrider让你做这件事。我只是不知道怎么做
我找不到任何关于如何在BHO中实现这一点的文档。欢迎任何指点
我用C来标记这个问题,因为C的解可能更简单,但是C++的解决方案,或者任何其他的解决方案也很受欢迎。
< P>在进一步的回顾之后,我意识到“收藏夹和动作工具栏”只是一个普通的普通的控制工具条(我以前假设它是某种自定义控件)。 我还不能调整我的代码,看看它会把我带到哪里,但这种方法应该与我下面概述的略有不同 据我所知,如果您希望工具栏按钮具有图像,则必须首先将该图像插入工具栏图像列表(检索列表,添加图像) 现在,我们可以创建实例并将其发送到工具栏中,同时显示或消息 那应该是吧台上的按钮。但是如何将它连接到您的代码 单击按钮时,工具栏将生成一条消息(可能是wParam
低位单词中TBBUTTON
结构的iCommand
成员)。所以我们只需要使用WH_CALLWNDPROC
并等待消息
当我让它开始工作时,将要实现;)
原始答案 正如我们之前在chat上讨论的,我怀疑是否有官方支持的方式在Internet Explorer UI的该位置添加额外按钮(或任何UI元素) 然而,仍然有一种“蛮力”方式,可以简单地在InternetExplorer窗口中创建一个新的子窗口 到目前为止,我还无法创建一个完整的示例,主要是因为我尝试调整工具栏的大小(3个操作按钮位于工具栏上)失败了 不管怎样,到目前为止,我能想到以下几点:
internal class MyButtonFactory
{
public void Install()
{
IntPtr ieFrame = WinApi.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "IEFrame", null);
IntPtr navigationBar = WinApi.FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", "Navigation Bar");
IntPtr reBar = WinApi.FindWindowEx(navigationBar, IntPtr.Zero, "ReBarWindow32", null);
IntPtr controlBar = WinApi.FindWindowEx(reBar, IntPtr.Zero, "ControlBandClass", null);
IntPtr toolsBar = WinApi.FindWindowEx(controlBar, IntPtr.Zero, "ToolbarWindow32", "Favorites and Tools Bar");
IntPtr myButton = WinApi.CreateWindowEx(0, "Button", "MySpecialButtonName",
WinApi.WindowStyles.WS_CHILD | WinApi.WindowStyles.WS_VISIBLE, 0, 0, 16,
16,
toolsBar, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (IntPtr.Zero == myButton)
{
Debug.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).Message);
}
IntPtr buttonWndProc = Marshal.GetFunctionPointerForDelegate(new WinApi.WndProc(WndProc));
WinApi.SetWindowLongPtr(new HandleRef(this, myButton), -4, buttonWndProc); // -4 = GWLP_WNDPROC
}
[AllowReversePInvokeCalls]
public IntPtr WndProc(IntPtr hWnd, WinApi.WM msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case WinApi.WM.LBUTTONUP:
MessageBox.Show("Hello World");
break;
default:
return WinApi.DefWindowProc(hWnd, msg, wParam, lParam);
}
return IntPtr.Zero;
}
}
这需要几个Windows API调用,这导致了一个1600行的beast从中复制到一起,所以我将在本文中省略它
除此之外,我无法将按钮很好地安装到工具栏中,一旦我设置了自己的窗口消息处理程序,按钮就不再绘制
因此,显然,要使这种方法发挥作用,还需要做很多工作,但我想我还是要与大家分享这一点
我想到的另一个想法是忽略整个工具栏,只把按钮放在它旁边。也许这更容易处理
在网上搜索与Windows API相关的术语时,我还看到了CodeProject文章,这篇文章似乎与本文非常相关。Dll注入就是答案,伙计 编辑: 当然。看起来你不必做DLL注入,BHO可以从IE进程内部访问。这样就容易多了 基本上,你需要先找到窗户。因此,通过修改函数以满足您的需要,它将如下所示:
BOOL FindFavoritesAndToolsBar(HWND mainWnd, HWND* addressBarWnd, HWND* cmdTargetWnd)
{
mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "WorkerW" ), NULL );
mainWnd = ::FindWindowEx( mainWnd, NULL, TEXT( "ReBarWindow32" ), NULL );
*cmdTargetWnd = ::FindWindowEx
mainWnd, NULL, TEXT( "ControlBandClass" ), NULL );
if( *cmdTargetWnd )
*addressBarWnd = ::FindWindowEx(
*cmdTargetWnd, NULL, TEXT( "ToolbarWindow32" ), L"Favorites and Tools Bar" );
return cmdTargetWnd != NULL;
}
其余逻辑与我链接的文章相同。您可以使用子类来拦截消息循环,并为自己的按钮添加自己的事件处理程序
另一种方法是只创建一个按钮作为弹出窗口,将IE窗口设置为父窗口,找到“偏好和工具栏”的位置,并将按钮放置在它旁边。更容易,但当然不那么优雅
编辑2:
对不起,我刚才看到我重复了奥利弗的一些回答。但是,如果您按照我在BHO中所写的操作,该按钮将与IE自己的任何按钮一样,您可以完全控制它。编辑:
这是我正在进行的工作的屏幕截图 我所做的事情: 1。从保护模式退出 BHO注册必须更新
HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy
密钥
我之所以选择流程方式,是因为它被称为“最佳实践”,并且更易于调试,但是rundll32策略也可以做到这一点
找到包含BHO注册表设置的rgs
文件。它包含注册表项的upadte“浏览器帮助对象”
。将以下内容添加到该文件:
HKLM {
NoRemove SOFTWARE {
NoRemove Microsoft {
NoRemove 'Internet Explorer' {
NoRemove 'Low Rights' {
NoRemove ElevationPolicy {
ForceRemove '{AE6E5BFE-B965-41B5-AC70-D7069E555C76}' {
val AppName = s 'SoBrowserActionInjector.exe'
val AppPath = s '%MODULEPATH%'
val Policy = d '3'
}
}
}
}
}
}
}
GUID必须是新的,不要使用我的,请使用GUID生成器。
策略的3
值确保代理进程将作为中等完整性进程启动。%MODULEPATH%
宏不是预定义的宏
为什么要使用宏?
如果MSI包含对注册表的更新,您可以避免在RGS文件中使用该新代码。由于与MSI打交道可能会很痛苦,所以提供“完整的自我注册”软件包通常更容易。但是如果不使用宏,则不能允许用户选择安装目录。使用宏可以使用正确的安装目录动态更新注册表
如何使宏工作?
找到BHO类标题中的DECLARE\u REGISTRY\u RESOURCEID
宏,并将其注释掉。在该标题中添加以下函数定义:
static HRESULT WINAPI UpdateRegistry( BOOL bRegister ) throw() {
ATL::_ATL_REGMAP_ENTRY regMapEntries[2];
memset( ®MapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY));
regMapEntries[0].szKey = L"MODULEPATH";
regMapEntries[0].szData = sm_szModulePath;
return ATL::_pAtlModule->UpdateRegistryFromResource(IDR_CSOBABHO, bRegister,
regMapEntries);
}
该代码是从ATL实现中借来的,用于DECLARE\u REGISTRY\u RESOURCEID
(在我的例子中,它是VS2010附带的代码,请检查您的ATL版本,并在必要时更新代码)。IDR_CSOBABHO
宏是在RC文件中添加RGS的注册表
资源的资源ID
sm_szModulePath
变量必须包含代理进程EXE的安装路径。我选择让它成为一个公共场所
STDMETHODIMP CCSoBABHO::SetSite( IUnknown* pUnkSite ) {
if ( pUnkSite ) {
HRESULT hr = pUnkSite->QueryInterface( IID_IWebBrowser2, (void**)&m_spIWebBrowser2 );
if ( SUCCEEDED( hr ) && m_spIWebBrowser2 ) {
SHANDLE_PTR hWndIEFrame;
hr = m_spIWebBrowser2->get_HWND( &hWndIEFrame );
if ( SUCCEEDED( hr ) ) {
wchar_t szExeName[] = L"SoBrowserActionInjector.exe";
wchar_t szFullPath[ MAX_PATH ];
wcscpy_s( szFullPath, sm_szModulePath );
wcscat_s( szFullPath, L"\\" );
wcscat_s( szFullPath, szExeName );
STARTUPINFO si;
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
PROCESS_INFORMATION pi;
wchar_t szCommandLine[ 64 ];
swprintf_s( szCommandLine, L"%.48s %d", szExeName, (int)hWndIEFrame );
BOOL bWin32Success = CreateProcess( szFullPath, szCommandLine, NULL,
NULL, FALSE, 0, NULL, NULL, &si, &pi );
if ( bWin32Success ) {
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
}
}
[...]
#include <Windows.h>
#include <stdlib.h>
typedef LRESULT (CALLBACK *PHOOKCALLWNDPROCRET)( int nCode, WPARAM wParam, LPARAM lParam );
PHOOKCALLWNDPROCRET g_pHookCallWndProcRet;
HMODULE g_hDll;
UINT g_uiRegisteredMsg;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, char * pszCommandLine, int ) {
HWND hWndIEFrame = (HWND)atoi( pszCommandLine );
wchar_t szFullPath[ MAX_PATH ];
DWORD dwCopied = GetModuleFileName( NULL, szFullPath,
sizeof( szFullPath ) / sizeof( wchar_t ) );
if ( dwCopied ) {
wchar_t * pLastAntiSlash = wcsrchr( szFullPath, L'\\' );
if ( pLastAntiSlash ) *( pLastAntiSlash + 1 ) = 0;
wcscat_s( szFullPath, L"SoBrowserActionBHO.dll" );
g_hDll = LoadLibrary( szFullPath );
if ( g_hDll ) {
g_pHookCallWndProcRet = (PHOOKCALLWNDPROCRET)GetProcAddress( g_hDll,
"HookCallWndProcRet" );
if ( g_pHookCallWndProcRet ) {
g_uiRegisteredMsg = RegisterWindowMessage( L"SOBA_MSG" );
if ( g_uiRegisteredMsg ) {
DWORD dwTID = GetWindowThreadProcessId( hWndIEFrame, NULL );
if ( dwTID ) {
HHOOK hHook = SetWindowsHookEx( WH_CALLWNDPROCRET,
g_pHookCallWndProcRet,
g_hDll, dwTID );
if ( hHook ) {
SendMessage( hWndIEFrame, g_uiRegisteredMsg, 0, 0 );
UnhookWindowsHookEx( hHook );
}
}
}
}
}
}
if ( g_hDll ) FreeLibrary( g_hDll );
return 0;
}
// DllMain
// -------
if ( dwReason == DLL_PROCESS_ATTACH ) {
CCSoBABHO::sm_dwTlsIndex = TlsAlloc();
[...]
} else if ( dwReason == DLL_THREAD_DETACH ) {
CCSoBABHO::UnhookIfHooked();
} else if ( dwReason == DLL_PROCESS_DETACH ) {
CCSoBABHO::UnhookIfHooked();
if ( CCSoBABHO::sm_dwTlsIndex != TLS_OUT_OF_INDEXES )
TlsFree( CCSoBABHO::sm_dwTlsIndex );
}
// BHO Class Static functions
// --------------------------
void CCSoBABHO::HookIfNotHooked( void ) {
if ( sm_dwTlsIndex == TLS_OUT_OF_INDEXES ) return;
HHOOK hHook = reinterpret_cast<HHOOK>( TlsGetValue( sm_dwTlsIndex ) );
if ( hHook ) return;
hHook = SetWindowsHookEx( WH_CALLWNDPROCRET, HookCallWndProcRet,
sm_hModule, GetCurrentThreadId() );
TlsSetValue( sm_dwTlsIndex, hHook );
return;
}
void CCSoBABHO::UnhookIfHooked( void ) {
if ( sm_dwTlsIndex == TLS_OUT_OF_INDEXES ) return;
HHOOK hHook = reinterpret_cast<HHOOK>( TlsGetValue( sm_dwTlsIndex ) );
if ( UnhookWindowsHookEx( hHook ) ) TlsSetValue( sm_dwTlsIndex, 0 );
}
LRESULT CALLBACK CCSoBABHO::HookCallWndProcRet( int nCode, WPARAM wParam,
LPARAM lParam ) {
if ( nCode == HC_ACTION ) {
if ( sm_uiRegisteredMsg == 0 )
sm_uiRegisteredMsg = RegisterWindowMessage( L"SOBA_MSG" );
if ( sm_uiRegisteredMsg ) {
PCWPRETSTRUCT pcwprets = reinterpret_cast<PCWPRETSTRUCT>( lParam );
if ( pcwprets && ( pcwprets->message == sm_uiRegisteredMsg ) ) {
HookIfNotHooked();
HWND hWndTB = FindThreadToolBarForIE9( pcwprets->hwnd );
if ( hWndTB ) {
AddBrowserActionForIE9( pcwprets->hwnd, hWndTB );
}
}
}
}
return CallNextHookEx( 0, nCode, wParam, lParam);
}
HWND FindThreadToolBarForIE9( HWND hWndIEFrame ) {
HWND hWndWorker = FindWindowEx( hWndIEFrame, NULL,
L"WorkerW", NULL );
if ( hWndWorker ) {
HWND hWndRebar= FindWindowEx( hWndWorker, NULL,
L"ReBarWindow32", NULL );
if ( hWndRebar ) {
HWND hWndBand = FindWindowEx( hWndRebar, NULL,
L"ControlBandClass", NULL );
if ( hWndBand ) {
return FindWindowEx( hWndBand, NULL,
L"ToolbarWindow32", NULL );
}
}
}
return 0;
}
void AddBrowserActionForIE9( HWND hWndIEFrame, HWND hWndToolBar ) {
// do nothing if already done
LRESULT lr = SendMessage( hWndToolBar, TB_BUTTONCOUNT, 0, 0 );
UINT ButtonCount = (UINT)lr;
for ( WPARAM index = 0; index < ButtonCount; ++index ) {
TBBUTTON tbb;
LRESULT lr = SendMessage( hWndToolBar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>( &tbb ) );
if ( lr == TRUE ) {
if ( tbb.idCommand == 4242 ) return;
}
}
HIMAGELIST hImgList = (HIMAGELIST)SendMessage( hWndToolBar, TB_GETIMAGELIST, 0, 0 );
HIMAGELIST hImgListHot = (HIMAGELIST)SendMessage( hWndToolBar, TB_GETHOTIMAGELIST, 0, 0 );
HIMAGELIST hImgListPressed = (HIMAGELIST)SendMessage( hWndToolBar, TB_GETPRESSEDIMAGELIST, 0, 0 );
// load little or big bitmap
int cx, cy;
BOOL bRetVal = ImageList_GetIconSize( hImgList, &cx, &cy );
HBITMAP hBitMap = LoadBitmap( CCSoBABHO::sm_hModule,
MAKEINTRESOURCE( cx <= 17 ? IDB_BITMAP_SO_LITTLE : IDB_BITMAP_SO_BIG ) );
int iImage = -1;
if ( hImgList ) {
iImage = ImageList_Add( hImgList, hBitMap, NULL );
}
if ( hImgListHot ) {
ImageList_Add( hImgListHot, hBitMap, NULL );
}
if ( hImgListPressed ) {
ImageList_Add( hImgListPressed, hBitMap, NULL );
}
TBBUTTON tbb;
memset( &tbb, 0, sizeof( TBBUTTON ) );
tbb.idCommand = 4242;
tbb.iBitmap = iImage;
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = BTNS_BUTTON;
lr = SendMessage( hWndToolBar, TB_INSERTBUTTON, 0, reinterpret_cast<LPARAM>( &tbb ) );
if ( lr == TRUE ) {
// force TB container to expand
HWND hWndBand = GetParent( hWndToolBar );
RECT rectBand;
GetWindowRect( hWndBand, &rectBand );
HWND hWndReBar = GetParent( hWndBand );
POINT ptNew = { rectBand.left - cx, rectBand.top };
ScreenToClient( hWndReBar, &ptNew );
MoveWindow( hWndBand, ptNew.x, ptNew.y, rectBand.right - rectBand.left + cx,
rectBand.bottom - rectBand.top, FALSE );
// force IE to resize address bar
RECT rect;
GetWindowRect( hWndIEFrame, &rect );
SetWindowPos( hWndIEFrame, NULL, rect.left, rect.top, rect.right - rect.left + 1,
rect.bottom - rect.top, SWP_NOZORDER );
SetWindowPos( hWndIEFrame, NULL, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOZORDER );
}
if ( hBitMap ) DeleteObject( hBitMap );
return;
}
if ( pcwprets && ( pcwprets->message == WM_COMMAND ) ) {
if ( LOWORD( pcwprets->wParam ) == 4242 ) {
NotifyActiveBhoIE9( pcwprets->hwnd );
}
}
// New Members in CCSoBABHO
static wchar_t * sm_pszPrivateClassName
static void RegisterPrivateClass( void );
static void UnregisterPrivateClass( void );
HWND m_hWndPrivate;
static LRESULT CALLBACK wpPrivate( HWND hWnd, UINT uiMsg,
WPARAM wParam, LPARAM lParam );
static wchar_t * MakeWindowText( wchar_t * pszBuffer, size_t cbBuffer,
DWORD dwTID );
bool CreatePrivateWindow( void );
bool DestroyPrivateWindow( void ) {
if ( m_hWndPrivate ) DestroyWindow( m_hWndPrivate );
};
// implementation
wchar_t * CCSoBABHO::sm_pszPrivateClassName = L"SoBrowserActionClassName";
void CCSoBABHO::RegisterPrivateClass( void ) {
WNDCLASS wndclass;
memset( &wndclass, 0, sizeof( wndclass ) );
wndclass.hInstance = sm_hInstance;
wndclass.lpszClassName = sm_pszPrivateClassName;
wndclass.lpfnWndProc = wpPrivate;
RegisterClass( &wndclass );
return;
}
void CCSoBABHO::UnregisterPrivateClass( void ) {
UnregisterClass( sm_pszPrivateClassName, sm_hInstance );
return;
}
wchar_t * CCSoBABHO::MakeWindowText( wchar_t * pszBuffer, size_t cbBuffer,
DWORD dwTID ) {
swprintf( pszBuffer, cbBuffer / sizeof( wchar_t ),
L"TID_%.04I32x", dwTID );
return pszBuffer;
}
bool CCSoBABHO::CreatePrivateWindow( void ) {
wchar_t szWindowText[ 64 ];
m_hWndPrivate = CreateWindow( sm_pszPrivateClassName,
MakeWindowText( szWindowText,
sizeof( szWindowText ),
GetCurrentThreadId() ),
0, 0, 0,0 ,0 ,NULL, 0, sm_hInstance, this );
return m_hWndPrivate ? true : false;
}
void CCSoBABHO::NotifyActiveBhoIE9( HWND hWndFromIEMainProcess ) {
// Up to Main Frame
HWND hWndChild = hWndFromIEMainProcess;
while ( HWND hWndParent = GetParent( hWndChild ) ) {
hWndChild = hWndParent;
}
HWND hwndIEFrame = hWndChild;
// down to first "visible" FrameTab"
struct ew {
static BOOL CALLBACK ewp( HWND hWnd, LPARAM lParam ) {
if ( ( GetWindowLongPtr( hWnd, GWL_STYLE ) & WS_VISIBLE ) == 0 ) return TRUE;
wchar_t szClassName[ 32 ];
if ( GetClassName( hWnd, szClassName, _countof( szClassName ) ) ) {
if ( wcscmp( szClassName, L"Frame Tab" ) == 0 ) {
*reinterpret_cast<HWND*>( lParam ) = hWnd;
return FALSE;
}
}
return TRUE;
}
};
HWND hWndFirstVisibleTab = 0;
EnumChildWindows( hwndIEFrame, ew::ewp,
reinterpret_cast<LPARAM>( &hWndFirstVisibleTab ) );
if ( hWndFirstVisibleTab == 0 ) return;
// down to first child, (in another process)
HWND hWndThreaded = GetWindow( hWndFirstVisibleTab, GW_CHILD );
if ( hWndThreaded == 0 ) return;
DWORD dwTID = GetWindowThreadProcessId( hWndThreaded, NULL );
wchar_t szWindowText[ 64 ];
HWND hWndPrivate = FindWindow( sm_pszPrivateClassName,
MakeWindowText( szWindowText,
sizeof( szWindowText ), dwTID ) );
if ( hWndPrivate ) SendMessage( hWndPrivate, WM_USER, 0, 0 );
}
LRESULT CALLBACK CCSoBABHO::wpPrivate( HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam ) {
switch( uMsg ) {
case WM_CREATE: {
CREATESTRUCT * pCS = reinterpret_cast<CREATESTRUCT*>( lParam );
SetWindowLongPtr( hWnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>( pCS->lpCreateParams ) );
return 0;
}
case WM_USER: {
CCSoBABHO * pThis =
reinterpret_cast<CCSoBABHO*>( GetWindowLongPtr( hWnd, GWLP_USERDATA ) );
if ( pThis ) pThis->OnActionClick( wParam, lParam );
break;
}
default: return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
return 0;
}
case DISPID_WINDOWSTATECHANGED: {
LONG lFlags = pDispParams->rgvarg[ 1 ].lVal;
LONG lValidFlagsMask = pDispParams->rgvarg[ 0 ].lVal;
LONG lEnabledUserVisible = OLECMDIDF_WINDOWSTATE_USERVISIBLE |
OLECMDIDF_WINDOWSTATE_ENABLED;
if ( ( lValidFlagsMask & lEnabledUserVisible ) == lEnabledUserVisible ) {
SHANDLE_PTR hWndIEFrame = 0;
HRESULT hr = m_spIWebBrowser2->get_HWND( &hWndIEFrame );
if ( SUCCEEDED( hr ) && hWndIEFrame ) {
if ( reinterpret_cast<HWND>( hWndIEFrame ) != m_hWndIEFrame ) {
m_hWndIEFrame = reinterpret_cast<HWND>( hWndIEFrame );
LaunchMediumProcess();
}
}
}
break;
}