我正在用C#开发一个Windows窗体应用程序,其中嵌入了WebBrowser
控件以“虚拟证明”(即禁用上下文菜单,后退按钮,自由导航等)访问第三方Web应用。
现在我正在尝试将缩放功能添加到我的自定义浏览器中。我有键盘组合工作(CTRL +和CTRL - 对底层ActiveX WebBrowser对象进行正确的OLE调用),但在其他令人沮丧的事情WebBrowser
我必须处理,我可以'似乎弄清楚如何捕捉CTRL鼠标滚轮来模拟像IE一样的缩放功能。我到处寻找解决方案,但无济于事。
为了弄清楚,我创建了一个只有WebBrowser控件的空表单,并找到了以下内容:
MouseWheel
事件在WebBrowser
控件上,即使父窗体具有焦点,它似乎没有焦点。MouseWheel
控件上且WebBrowser
具有焦点时,CTRL-MouseWheel永远不会触发WebBrowser
事件,并且似乎没有效果。WebBrowser
的窗口内容,但不会触发MouseWheel
事件,直到垂直滚动条完全到达顶部或底部。
Message
和WM_MOUSEWHEEL
两者来截取WndProc
的{{1}},以获取从DefWndProc
继承的样本类和父表单仅适用于上述条件(WebBrowser
正确表示wParam
)。MK_CONTROL
事件会按预期触发,但仍然与鼠标滚轮无关。
所以我想PreviewKeyDown
正在父窗体和托管控制级别下面进行处理,并且没有冒泡到我可以截取甚至处理它的位置。有没有办法做到这一点,或者使用CTRL-MouseWheel模拟放大和缩小的其他方法?
感谢阅读!
答案 0 :(得分:4)
首先将WebBrowser.Document.DomDocument
强制转换为mshtml命名空间中的右侧接口,如mshtml.HTMLDocumentEvents2_Event
,然后您可以处理(和取消)mousewheel事件。我不确定,但我认为您需要在文档更改时随时连接事件处理程序,因此我在WebBrowser.DocumentCompleted
事件上执行此操作。我也不确定你是否需要释放任何COM对象。
这令人沮丧,我让它开始工作并停止了关怀......
以下是至少一份解释基础知识的文件:How to handle document events in a Visual C# .NET application
对于您的具体情况,只需根据是否按下onmousewheel
键,有条件地压缩CTRL
事件。
private void webBrowser_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser.Url.ToString() == "about:blank")
return;
var docEvents = (mshtml.HTMLDocumentEvents2_Event)webBrowser.Document.DomDocument;
docEvents.onmousewheel -= docEvents_onmousewheel; //may not be necessary?
docEvents.onmousewheel += docEvents_onmousewheel;
}
bool docEvents_onmousewheel(mshtml.IHTMLEventObj pEvtObj)
{
if (pEvtObj.ctrlKey)
{
pEvtObj.cancelBubble = true; //not sure what this does really
pEvtObj.returnValue = false; //this cancels the event
return false; //not sure what this does really
}
else
return true; //again not sure what this does
}
现在,如果您需要知道Wheel Delta(滚动量),您需要将events对象转换为另一个界面。
bool docEvents_onmousewheel(mshtml.IHTMLEventObj pEvtObj)
{
var wheelEventObj = (mshtml.IHTMLEventObj4)pEvtObj;
var delta = wheelEventObj.wheelDelta;
[...]
}
答案 1 :(得分:0)
使用SetWindowsHookEx查找这些事件可能对您有用。这就是我用来在ActiveX MapPoint控件上获取滚轮事件的方法。
请注意,在Windows 7上存在一些可能需要一些修改的怪癖。有关详细信息,请在MSDN论坛上搜索Windows 7上的SetWindowsHookEx。
答案 2 :(得分:0)
要解决此问题,您必须侦听并处理这些消息:
他们是由Internet Explorer调度的。请参阅remarks on MSDN。
答案 3 :(得分:0)
这是我用来禁用ctrl + shift的代码:
你需要在最深的控件“Internet Explorer_Server”中更改WndProc的行为,
在您的Web浏览器准备就绪后执行此操作:
IntPtr wbHandle = Win32.FindWindowEx(this.wbMain.Handle, IntPtr.Zero, "Shell Embedding", String.Empty);
wbHandle = Win32.FindWindowEx(wbHandle, IntPtr.Zero, "Shell DocObject View", String.Empty);
wbHandle = Win32.FindWindowEx(wbHandle, IntPtr.Zero, "Internet Explorer_Server", String.Empty);
WbInternal wb = new WbInternal(wbHandle);
class WbInternal : NativeWindow
{
public WbInternal(IntPtr handle)
{
this.AssignHandle(handle);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
{
if (((int)m.WParam & 0x00FF) == MK_SHIFT)
{
return;
}
}
base.WndProc(ref m);
}
}
您可以从MSDN找到有关WM_MOUSEWHEEL的更多消息 我在MSDN上找到了这个。但是我忘记了链接,一旦发现,就会把它添加到这里。
答案 4 :(得分:0)
我无法使这些中的任何一个可靠地工作,所以经过一些(令人沮丧的)实验后,我想出了TCC发布的答案的衍生物。我的webbrowser控件托管在usercontrol中。主要区别是我使用HTMLDocumentEvents2_Event的类级变量,所以我可以成功取消订阅,并将mshtml.IHTMLEventObj pEvtObj.Returnvalue设置为true ..现在似乎运行良好..
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_wbData = (WebBrowser)FindElement("DataBrowser");
_horzScroll = (ScrollBar)FindElement("HorizontalScroll");
_vertScroll = (ScrollBar)FindElement("VerticalScroll");
_wbData.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(OnLoadCompleted);
_horzScroll.Scroll += new ScrollEventHandler(OnHorizontalScroll);
_vertScroll.Scroll += new ScrollEventHandler(OnVerticalScroll);
LoadDefault();
EnableSoundEffects(SoundEffects);
}
private void OnHorizontalScroll(object sender, ScrollEventArgs e)
{
// _wbData.Handle
mshtml.HTMLDocument htmlDoc = _wbData.Document as mshtml.HTMLDocument;
_horzPosition = (int)e.NewValue;
if (htmlDoc != null && htmlDoc.body != null)
htmlDoc.parentWindow.scroll(_horzPosition, _vertPosition);
}
private void OnVerticalScroll(object sender, ScrollEventArgs e)
{
mshtml.HTMLDocument htmlDoc = _wbData.Document as mshtml.HTMLDocument;
_vertPosition = (int)e.NewValue;
if (htmlDoc != null && htmlDoc.body != null)
htmlDoc.parentWindow.scroll(_horzPosition, _vertPosition);
}
private void OnLoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
mshtml.HTMLDocument htmlDoc = _wbData.Document as mshtml.HTMLDocument;
if (htmlDoc != null && htmlDoc.body != null)
{
mshtml.IHTMLElement2 body = (mshtml.IHTMLElement2)htmlDoc.body;
_horzScroll.Visibility = Visibility.Collapsed;
if (body.scrollHeight > _wbData.ActualHeight)
_vertScroll.Visibility = Visibility.Visible;
else
_vertScroll.Visibility = Visibility.Collapsed;
_vertScroll.ViewportSize = _wbData.ActualHeight;
_vertScroll.Maximum = body.scrollHeight - (_wbData.ActualHeight - 8);
_eventHelper = (HTMLDocumentEvents2_Event)_wbData.Document;
_eventHelper.onmousewheel -= OnMouseWheel;
_eventHelper.onmousewheel += new HTMLDocumentEvents2_onmousewheelEventHandler(OnMouseWheel);
}
}
private bool OnMouseWheel(mshtml.IHTMLEventObj pEvtObj)
{
mshtml.HTMLDocument htmlDoc = _wbData.Document as mshtml.HTMLDocument;
var wheelEventObj = (mshtml.IHTMLEventObj4)pEvtObj;
var delta = wheelEventObj.wheelDelta;
if (htmlDoc != null && htmlDoc.body != null && wheelEventObj != null)
{
_vertPosition += (int)wheelEventObj.wheelDelta;
htmlDoc.parentWindow.scroll(_horzPosition, _vertPosition);
}
pEvtObj.returnValue = true;
return true;
}