C# 使用ctrl+;CrystalDecisions.Windows.Forms.CrystalReportViewer中的鼠标滚轮

C# 使用ctrl+;CrystalDecisions.Windows.Forms.CrystalReportViewer中的鼠标滚轮,c#,vb.net,winforms,crystal-reports,windows-forms-designer,C#,Vb.net,Winforms,Crystal Reports,Windows Forms Designer,是否可以在CrystalDecisions.Windows.Forms.CrystalReportViewer上使用ctrl+鼠标滚轮组合启用或实现放大/缩小功能 鼠标滚轮用于滚动。一个建议是处理mouseevent,中止滚动并使用delta调整缩放。。。但我无法处理鼠标滚轮事件 我试过处理CrystalReportViewer.mouseweel,它可以编译,但从未启动过。我还尝试继承控件CrystalDecisions.Windows.Forms.CrystalReportViewer并重写

是否可以在CrystalDecisions.Windows.Forms.CrystalReportViewer上使用ctrl+鼠标滚轮组合启用或实现放大/缩小功能

鼠标滚轮用于滚动。一个建议是处理mouseevent,中止滚动并使用delta调整缩放。。。但我无法处理鼠标滚轮事件


我试过处理CrystalReportViewer.mouseweel,它可以编译,但从未启动过。我还尝试继承控件CrystalDecisions.Windows.Forms.CrystalReportViewer并重写OnMouseWheel方法,但它从未被调用。有什么想法吗?

我发现了一个类似的问题。然后我解决了在按下Ctrl键时实现IMessageFilter接口拦截鼠标滚轮消息的问题。我在CrystalReportViewer控件之前处理了消息,并根据增量调整了缩放级别。 我发布了我的解决方案,希望能对其他人有所帮助。 如果您找到更好的解决方案或bug,请告诉我

Imports System.Drawing
'Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports CrystalDecisions.CrystalReports.Engine
Imports CrystalDecisions.Windows.Forms

Public Class CrystalReportViewerMouseWheelZoom
    Implements IMessageFilter

    Private WithEvents _viewer As CrystalDecisions.Windows.Forms.CrystalReportViewer
    Private _viewerForm As Form = Nothing
    Private _ZoomLevel As Integer
    Public Sub New(viewer As CrystalDecisions.Windows.Forms.CrystalReportViewer)
        Me._viewer = viewer
        Application.AddMessageFilter(Me)
    End Sub

    Private Sub _viewer_Disposed(sender As Object, e As EventArgs) Handles _viewer.Disposed
        Application.RemoveMessageFilter(Me)
        _viewer = Nothing
    End Sub

    Private Sub _viewer_ViewZoom(source As Object, e As ZoomEventArgs) Handles _viewer.ViewZoom
        _ZoomLevel = e.NewZoomFactor
    End Sub

    '<DllImport("user32.dll")>
    'Private Shared Function WindowFromPoint(ByVal p As Point) As IntPtr
    'End Function

    Private Const ZOOM_LEVEL_DELTA_PERC As Double = 5D
    Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
        If (m.Msg <> &H20A) Then Return False

        If Not My.Computer.Keyboard.CtrlKeyDown Then Return False

        Dim mouseAbsolutePosition = New Point(m.LParam.ToInt32())
        Dim mouseRelativePosition = _viewer.PointToClient(mouseAbsolutePosition)


        'DOEW NOT WORK, Control.FromHandle return always null
        'Dim hControlUnderMouse As IntPtr = WindowFromPoint(mouseAbsolutePosition)
        'Dim controlUnderMouse = Control.FromHandle(hControlUnderMouse)
        'If Not Equals(controlUnderMouse, _viewer) Then Return False
        If Not IsViewerFormActive() Then Return False

        Dim _documentControl = FindFirstDocumentControl(_viewer)
        If _documentControl Is Nothing Then Return False
        Dim screenRectangle = _documentControl.RectangleToScreen(_documentControl.ClientRectangle)
        If Not screenRectangle.Contains(mouseAbsolutePosition) Then Return False

        Dim delta = m.WParam.ToInt32() >> 16
        Dim newZoomLevel As Integer = CalcNewZoomLevel(_documentControl, delta)
        If (newZoomLevel < 3) Then Return False

        _viewer.Zoom(newZoomLevel)
        Return True
    End Function

    Private Function IsViewerFormActive() As Boolean
        Dim active As Boolean = False
        If _viewerForm Is Nothing Then _viewerForm = _viewer.FindForm
        Dim activeForm = Form.ActiveForm
        If activeForm IsNot Nothing AndAlso activeForm.IsMdiContainer AndAlso _viewerForm.IsMdiChild Then
            active = Equals(activeForm.ActiveMdiChild, _viewerForm)
        Else
            active = Equals(activeForm, _viewerForm)
        End If
        Return active
    End Function

    Private Function CalcNewZoomLevel(_documentControl As DocumentControl, delta As Integer) As Integer
        Dim newZoomLevel = _ZoomLevel

        If newZoomLevel < 3 Then
            Dim rpt = TryCast(_viewer.ReportSource, ReportDocument)
            If rpt Is Nothing Then Return -1

            Using g = _viewer.CreateGraphics()
                If _ZoomLevel = 1 Then
                    newZoomLevel = CInt((_documentControl.ClientSize.Width / GetPageWith(rpt, g)) * 100)
                ElseIf _ZoomLevel = 2 Then
                    newZoomLevel = CInt((_documentControl.ClientSize.Height / GetPageHeight(rpt, g)) * 100)
                End If
            End Using

        End If


        newZoomLevel += (If(delta < 0, -1, 1) * CInt(newZoomLevel * ZOOM_LEVEL_DELTA_PERC / 100))
        Return newZoomLevel
    End Function

    Private Function GetPageHeight(rpt As ReportDocument, g As Graphics) As Integer
        Dim twips = rpt.PrintOptions.PageContentHeight + rpt.PrintOptions.PageMargins.topMargin + rpt.PrintOptions.PageMargins.bottomMargin
        Return CInt(CDbl(twips) * (1.0 / 1440.0) * g.DpiY)
    End Function

    Private Function GetPageWith(rpt As ReportDocument, g As Graphics) As Integer
        Dim twips = rpt.PrintOptions.PageContentWidth + rpt.PrintOptions.PageMargins.leftMargin + rpt.PrintOptions.PageMargins.rightMargin
        Return CInt(CDbl(twips) * (1.0 / 1440.0) * g.DpiX)
    End Function

    Private Function FindFirstDocumentControl(parent As Control) As DocumentControl
        Dim docCrtl As DocumentControl = Nothing
        For Each c As Control In parent.Controls
            If TypeOf c Is DocumentControl Then
                docCrtl = DirectCast(c, DocumentControl)
                Exit For
            Else
                docCrtl = FindFirstDocumentControl(c)
            End If
            If docCrtl IsNot Nothing Then Exit For
        Next
        Return docCrtl
    End Function
End Class
导入系统图形
'导入System.Runtime.InteropServices
导入System.Windows.Forms
导入CrystalDecisions.CrystalReports.Engine
导入CrystalDecisions.Windows.Forms
公共类CrystalReportViewerMouseheelZoom
实现IMessageFilter
Private WithEvents\u viewer作为CrystalDecisions.Windows.Forms.CrystalReportViewer
Private _viewPerformas Form=无
Private _ZoomLevel为整数
Public Sub New(查看器为CrystalDecisions.Windows.Forms.CrystalReportViewer)
我。_viewer=viewer
Application.AddMessageFilter(Me)
端接头
Private Sub_viewer_Disposed(发送方作为对象,e作为事件参数)处理_viewer.Disposed
Application.RemoveMessageFilter(Me)
_查看器=无
端接头
私有子_viewer _ViewZoom(源作为对象,e作为ZoomEventArgs)处理_viewer.ViewZoom
_ZoomLevel=e.NewZoomFactor
端接头
'
'专用共享函数WindowFromPoint(ByVal p作为Point)作为IntPtr
'结束函数
专用常量缩放\u级别\u增量\u PERC为双精度=5D
作为布尔值的公共函数PreFilterMessage(ByRef m作为消息)实现IMessageFilter.PreFilterMessage
如果(m.Msg&H20A),则返回False
如果不是My.Computer.Keyboard.CtrlKeyDown,则返回False
Dim MouseAbSolutionPosition=新点(m.LParam.ToInt32())
Dim mouseRelativePosition=\u viewer.PointToClient(MouseAbSolutionPosition)
'不工作,Control.FromHandle返回始终为空
'Dim hControlUnderMouse As IntPtr=WindowFromPoint(MouseAbSolutionPosition)
'Dim controlUnderMouse=Control.FromHandle(hControlUnderMouse)
'如果不等于(controlUnderMouse,_viewer),则返回False
如果不是IsViewPerformActive(),则返回False
Dim\u documentControl=FindFirstDocumentControl(\u查看器)
如果_documentControl为Nothing,则返回False
Dim Screen Rectangle=\u documentControl.RectangleToScreen(\u documentControl.ClientRectangle)
如果不是screenRectangle.Contains(MouseAbSolutionPosition),则返回False
尺寸增量=m.WParam.ToInt32()>>16
Dim newZoomLevel As Integer=CalcNewZoomLevel(_documentControl,delta)
如果(newZoomLevel<3),则返回False
_viewer.Zoom(新ZoomLevel)
返回真值
端函数
私有函数IsViewPerformActive()为布尔值
变暗激活为布尔值=False
如果_viewPerform为空,则_viewPerform=_viewer.FindForm
Dim activeForm=Form.activeForm
如果activeForm不是Nothing,也不是activeForm.IsMdiContainer和Also\u ViewPerform.IsMdiChild,那么
active=Equals(activeForm.ActiveMdiChild,_viewPerform)
其他的
active=Equals(activeForm,_viewperform)
如果结束
返回活动
端函数
私有函数CalcNewZoomLevel(_documentControl作为documentControl,delta作为整数)作为整数
Dim newZoomLevel=_ZoomLevel
如果newZoomLevel<3,则
Dim rpt=TryCast(_viewer.ReportSource,ReportDocument)
如果rpt为Nothing,则返回-1
使用g=_viewer.CreateGraphics()
如果_ZoomLevel=1,则
newZoomLevel=CInt(_documentControl.ClientSize.Width/GetPageWith(rpt,g))*100)
ElseIf_ZoomLevel=2那么
newZoomLevel=CInt(_documentControl.ClientSize.Height/GetPageHeight(rpt,g))*100)
如果结束
终端使用
如果结束
newZoomLevel+=(如果(delta<0,-1,1)*CInt(newZoomLevel*ZOOM\u LEVEL\u delta\u PERC/100))
返回新ZoomLevel
端函数
私有函数GetPageHeight(rpt作为ReportDocument,g作为Graphics)作为整数
Dim twips=rpt.PrintOptions.PageContentHeight+rpt.PrintOptions.PageMargins.topMargin+rpt.PrintOptions.PageMargins.bottomMargin
返回CInt(CDbl(twips)*(1.0/1440.0)*g.DpiY)
端函数
私有函数GetPageWith(rpt作为ReportDocument,g作为Graphics)作为整数
Dim twips=rpt.PrintOptions.PageContentWidth+rpt.PrintOptions.PageMargins.leftMargin+rpt.PrintOptions.PageMargins.rightMargin
返回CInt(CDbl(twips)*(1.0/1440.0)*g.DpiX)
端函数
私有函数FindFirstDocumentControl(父控件)作为DocumentControl
Dim docCrtl As DocumentControl=无
对于父控件中的每个c作为控件
如果c的类型为DocumentControl,则
docCrtl=DirectCast(c,DocumentControl)
退出
其他的
docCrtl=FindFirstDocumentControl(c)
如果结束
如果docCrtl不是空的,则退出
下一个
返回文件
端函数
末级

您可以使用鼠标滚轮事件的增量来调整CrystalReportViewer的缩放因子,给它一个tryI无法处理鼠标滚轮事件。我试过处理CrystalReportViewer.Mous