获取一个列表框的滚动事件

 

介绍 此示例演示如何

  

 

访问从System.Windows.Forms派生的自定义控件中的滚动条事件。列表框控件,在c# . net。问题回答: 如何获得滚动事件? 如何获得滚动条的位置? 开始 创建一个新的项目(文件,新建,项目…),类型为“Windows应用程序”。Visual Studio将在解决方案资源管理器和'Form1 '中显示该项目。设计模式下的cs。右键单击项目节点并选择‘Add, Add User Control…’。命名为“ScrollingListBox.cs”。现在可以在解决方案资源管理器中看到它,并且在设计器中看起来像一个灰色的正方形。 按F7进入代码并将基本的'UserControl'替换为'ListBox'。保存,编译,转到设计器。如您所见,解决方案资源管理器中的图标发生了变化,设计器没有显示列表框。这是您此时的代码:收缩,复制Code

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace WebsiteSamples
{
    /// <summary>
    /// Summary description for ScrollingListBox.
    /// </summary>
    public class ScrollingListBox : System.Windows.Forms.ListBox
    {
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public ScrollingListBox()
        {
            // This call is required by the Windows.Forms Form Designer.
            InitializeComponent();

            // TODO: Add any initialization after the InitForm call

        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Component Designer generated code
        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }
        #endregion
    }
}

Win32的东西 我们将重写WndProc并处理滚动条事件。这是常数的名称相同的C:\Program Files\Microsoft Visual Studio . net \ Vc7 \ PlatformSDK \ \ WinUser.h包括包含文件。隐藏,复制Code

private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;

private const int SB_LINELEFT = 0;
private const int SB_LINERIGHT = 1;
private const int SB_PAGELEFT = 2;
private const int SB_PAGERIGHT = 3;
private const int SB_THUMBPOSITION = 4;
private const int SB_THUMBTRACK = 5;
private const int SB_LEFT = 6;
private const int SB_RIGHT = 7;
private const int SB_ENDSCROLL = 8;

private const int SIF_TRACKPOS = 0x10;
private const int SIF_RANGE = 0x1;
private const int SIF_POS = 0x4;
private const int SIF_PAGE = 0x2;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;

当我们在WndProc中识别滚动消息时,我们需要调用user32.dll中的GetScrollInfo来查找位置。(微软文档说,当类型是SB_THUMBPOSITION或SB_THUMBTRACK时,这个位置在滚动消息的wparam中发送,但这根本不是真的。)因此,首先从DLL中导入GetScrollInfo。隐藏,复制Code

[DllImport("user32.dll", SetLastError=true) ]
private static extern int GetScrollInfo(
    IntPtr hWnd, int n, ref ScrollInfoStruct lpScrollInfo );

在Win32中,ScrollInfoStruct被称为SCROLLINFO,这是您在Microsoft api中看到的典型查询构造:信息结构被装载有自己的大小和问题代码(以及问题的可选参数)。在这种情况下,问题是‘你的立场是什么?”,或“SIF_ALL”。隐藏,复制Code

private struct ScrollInfoStruct
{
    public int cbSize;
    public int fMask;
    public int nMin;
    public int nMax;
    public int nPage;
    public int nPos;
    public int nTrackPos;
}

最后,检测消息并触发事件 好的,现在让我们在收到滚动消息时启动标准ScrollEvent。为此,我们需要事件,我将其称为“滚动”,因为这是微软对事件(如“Clicked”)的命名:复制Code

[Category("Action")]
public event ScrollEventHandler Scrolled = null;

在WndProc中,获取滚动消息并触发滚动事件。在这个例子中,我只响应WM_HSCROLL消息,因为这是一个所有者绘制列表框控件所需要的消息。然而,WM_VSCROLL的代码完全相同。在本例中,我只对滚动结束消息感兴趣,它是在每个滚动动作之后触发的。隐藏,复制Code

protected override void WndProc(ref System.Windows.Forms.Message msg)
{
    if( msg.Msg == WM_HSCROLL )
    {
        if( Scrolled != null )
        {
            ScrollInfoStruct si = new ScrollInfoStruct();
            si.fMask = SIF_ALL;
            si.cbSize = Marshal.SizeOf(si);
            GetScrollInfo(msg.HWnd, 0, ref si);

            if( msg.WParam.ToInt32() == SB_ENDSCROLL )
            {
                ScrollEventArgs sargs = new ScrollEventArgs(
                    ScrollEventType.EndScroll,
                    si.nPos);
                Scrolled(this, sargs);
            }
        }
    }
    base.WndProc(ref msg);
}

为了能够使用Marshal类,您必须引用互操作名称空间:Hide复制Code

using System.Runtime.InteropServices;

应该做的。您可以通过捕获垂直滚动条或捕获更多滚动事件来扩展它。如果您想知道滚动条在其他任何时候的位置,请使用GetScrollInfo函数。 另外,我还没有尝试过,但它可能适用于任何带有滚动条的控件。 如果你想知道,我需要这段代码有其他控件'滚动'与列表框。 本文转载于:http://www.diyabc.com/frontweb/news273.html

posted @ 2020-08-05 02:11  Dincat  阅读(323)  评论(0编辑  收藏  举报