Microsoft VSrollBar行为或触摸屏的错误 – 窗体

我在VScrollBar中发现了一个奇怪的行为(Visual Studio工具箱中提供了垂直滚动条)。 问题是“ 如果我向下滑动滚动条,它会向上移动。如果我向上滑动,它会向下移动 ”。

复制Bug或行为的步骤 – 1

1)将VScrollBar作为子项添加到任何用户控件。

2)向上或向下滑动用户控件(不在滚动条上)。 即使内容和VScrollBar之间没有任何程序连接,垂直滚动条也会向相反方向移动

复制Bug或行为的步骤 – 2

1)将VScrollBar作为子项添加到任何用户控件。

2)在滚动条上滑动,在向下滑动时向上和向下滑动(正确行为)

3)在用户控件上向上或向下滑动。 垂直滚动条向相反方向移动

4)现在在垂直滚动条上向上或向下滑动。 垂直滚动条开始向相反方向移动(Buggy行为,仅在错误号:1之后发生)

在此处输入图像描述

使用垂直滚动条进行简单控制即可复制此行为

public class QuickViewer : Control { public QuickViewer() { // Designer generated code // Copy pasted for illustration alone this.vScrollBar1 = new System.Windows.Forms.VScrollBar(); this.SuspendLayout(); // // vScrollBar1 // this.vScrollBar1.Location = new System.Drawing.Point(420, 4); this.vScrollBar1.Name = "vScrollBar1"; this.vScrollBar1.Size = new Size(this.vScrollBar1.Width, 292); // // QuickViewer // this.Controls.Add(this.vScrollBar1); this.Name = "QuickViewer"; this.Size = new System.Drawing.Size(441, 296); this.vScrollBar1.Value = 5; this.ResumeLayout(false); } protected override void OnPaint(PaintEventArgs e) { //My actual control is different. I prepared a simple control to replicate the buggy behavior of VScrollBar //Control border Pen borderPen = new Pen(Color.LawnGreen, 5); e.Graphics.DrawRectangle(borderPen, ClientRectangle); borderPen.Dispose(); //View area Rectangle rect = new Rectangle(ClientRectangle.Location, ClientRectangle.Size); rect.Inflate(-25, -10); e.Graphics.FillRectangle(Brushes.White, rect); e.Graphics.DrawRectangle(Pens.Black, rect); this.Font = new System.Drawing.Font("Segoe UI", 12, FontStyle.Bold); StringFormat format = new StringFormat() { Alignment = StringAlignment.Center }; e.Graphics.DrawString("Quick viewer", this.Font, Brushes.Black, rect, format); string content = "This is a control created to illustrate the bug in VScrollBar." + "\n Control area refers to the area with white background" + "\n Control and Vertical Scrollbar are not programatically connected with each other." + "But still VScrollBar moves if you swipe on control area"; Font font = new System.Drawing.Font("Segoe UI", 12, FontStyle.Italic); rect.Y += 20; e.Graphics.DrawString(content, font, Brushes.Black, rect, format); font.Dispose(); format.Dispose(); base.OnPaint(e); } ///  /// Required designer variable. ///  private System.ComponentModel.IContainer components = null; ///  /// Clean up any resources being used. ///  /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private System.Windows.Forms.VScrollBar vScrollBar1; } 

题:

有没有办法克服这种行为或错误? 我希望滚动条向下滑动,同时向上滑动向上移动。 在内容上滑动时不应该有任何滚动

我希望滚动条向下滑动,同时向上滑动向上移动。

根据Hans Passants评论它只是一个系统设置(以注册表项的forms):

在此处输入图像描述

答案实际上是在SuperUser:

https://superuser.com/questions/310681/inverting-direction-of-mouse-scroll-wheel

在C#中你想要的:

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Microsoft.Win32; using System.Diagnostics; using System.Security.Principal; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Flippable[] flippable; private void Form1_Load(object sender, EventArgs e) { WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator); if (!hasAdministrativeRight) { RunElevated(Application.ExecutablePath); this.Close(); Application.Exit(); } //probably only want to flip mice. flippable = getFlippable("hid.mousedevice"); dgv_flippable.DataSource = flippable; foreach (var col in dgv_flippable.Columns.OfType()) { col.TrueValue = true; col.FalseValue = false; col.IndeterminateValue = null; } } private static bool RunElevated(string fileName) { //MessageBox.Show("Run: " + fileName); ProcessStartInfo processInfo = new ProcessStartInfo(); processInfo.UseShellExecute = true; processInfo.Verb = "runas"; processInfo.FileName = fileName; try { Process.Start(processInfo); return true; } catch (Win32Exception) { //Do nothing. Probably the user canceled the UAC window } return false; } private Flippable[] getFlippable(string filter) { List flips = new List(); using (RegistryKey hid = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\HID\",false)) { foreach (string devicekn in hid.GetSubKeyNames()) { using (RegistryKey device = hid.OpenSubKey(devicekn,false)) { foreach (string devicekn2 in device.GetSubKeyNames()) { using (RegistryKey device2 = device.OpenSubKey(devicekn2,false)) { using (RegistryKey devparam = device2.OpenSubKey("Device Parameters",true)) { if (devparam != null) { flips.Add(new Flippable(new string[] { devicekn, devicekn2 }, device2, devparam, tmr_popup)); } } } } } } } if (filter != null) { return flips.Where(f=>f.name.Contains(filter)).ToArray(); } return flips.ToArray(); } private void dgv_flippable_MouseUp(object sender, MouseEventArgs e) { dgv_flippable.EndEdit(); } private void button1_Click(object sender, EventArgs e) { flippable = getFlippable(null); dgv_flippable.DataSource = flippable; } private void btn_flip_Click(object sender, EventArgs e) { foreach (var f in flippable) { f.vertical = true; f.horizontal = true; } dgv_flippable.DataSource = null; dgv_flippable.DataSource = flippable; } private void btn_normal_Click(object sender, EventArgs e) { foreach (var f in flippable) { f.vertical = false; f.horizontal = false; } dgv_flippable.DataSource = null; dgv_flippable.DataSource = flippable; } private void tmr_popup_Tick(object sender, EventArgs e) { tmr_popup.Enabled = false; notifyIcon1.ShowBalloonTip(99999999); } } public class Flippable { public Flippable(string[] keyPath, RegistryKey deviceKey, RegistryKey devparam, Timer timer) { this._keyPath = keyPath; IEnumerable flipValues = Flippable.valueNames .Select(v => onlyIntBool(devparam.GetValue(v, null))); this.name = (string)deviceKey.GetValue("DeviceDesc"); this._vertical = flipValues.ElementAt(0); this._horizontal = flipValues.ElementAt(1); this._timer = timer; } private bool? onlyIntBool(object value) { try { return value == null ? null : (bool?)(((int)value) != 0); } catch { return null; } } public static string[] valueNames = new string[] { "FlipFlopWheel", "FlipFlopHScroll" }; public string name { get; private set; } private string[] _keyPath; private bool? _vertical; private bool? _horizontal; Timer _timer; public bool? vertical { set { flip(Flippable.valueNames[0], value); _vertical = value; } get { return _vertical; } } public bool? horizontal { set { flip(Flippable.valueNames[1], value); _horizontal = value; } get { return _horizontal; } } public void flip(string valueName, bool? value) { using (RegistryKey hid = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\HID\", false)) { using (RegistryKey device = hid.OpenSubKey(_keyPath[0], false)) { using (RegistryKey device2 = device.OpenSubKey(_keyPath[1], false)) { using (RegistryKey devparam = device2.OpenSubKey("Device Parameters", true)) { if (value == null) { devparam.DeleteValue(valueName); } else { devparam.SetValue(valueName, value == true ? 1 : 0); _timer.Enabled = true; } } } } } } } } 

REF: https : //github.com/jamie-pate/flipflop-windows-wheel/blob/master/Form1.cs

免责声明:通常这个问题将作为副本关闭,但因为它有一个赏金,并且副本在SuperUser上结束我选择在这里分享这个答案。 完全归功于原作者: https : //superuser.com/users/108033/richard和https://superuser.com/users/132069/jamie-pate

我想你想要的是一个ViewPort。

基本上你将一个Control放在PictureBox中。 Control具有比PictureBox更大的高度,使其成为ViewPort。

之前

在此处输入图像描述

您需要更改表单设计器代码以获取PictureBox中的控件:

 ' 'PictureBox1 ' Me.PictureBox1.Location = New System.Drawing.Point(96, 87) Me.PictureBox1.Name = "PictureBox1" Me.PictureBox1.Size = New System.Drawing.Size(231, 195) Me.PictureBox1.TabIndex = 0 Me.PictureBox1.TabStop = False ' 'VScrollBar1 ' Me.VScrollBar1.Location = New System.Drawing.Point(330, 88) Me.VScrollBar1.Name = "VScrollBar1" Me.VScrollBar1.Size = New System.Drawing.Size(34, 194) Me.VScrollBar1.TabIndex = 2 ' 'TextBox1 ' Me.TextBox1.Location = New System.Drawing.Point(0, 0) Me.TextBox1.Multiline = True Me.TextBox1.Name = "TextBox1" Me.TextBox1.Size = New System.Drawing.Size(211, 251) Me.TextBox1.TabIndex = 3 ' 'Form1 ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(522, 392) Me.Controls.Add(Me.VScrollBar1) Me.Controls.Add(Me.PictureBox1) '======= THIS IS THE CRITICAL CHANGE ======= PictureBox1.Controls.Add(Me.TextBox1) 

在此处输入图像描述

然后手动将ScrollBar放置在PictureBox的右侧并自行促进行为,例如:

 //set the VScroll the difference VScroll.Max = Textbox.Height - PictureBox.Height; 

在VScroll事件中:

 TextBox.Top = -VScroll.Value; 

这样可以避免您在系统设置中乱码,从而生成QuickViewer自定义控件。

你可以添加智能,就像编写PictureBox拖动事件来设置ScrollBar(以及随后的内部控件Top)。 对于大多数内部控件,您只需要计算出使用for循环很容易的高度,例如:

 foreach(var ctrl in PictureBox.Controls) { // tally up the controls height ... 

对于内部文本框控件,您可以根据字体大小和行数计算高度。 网上有很多例子说明如何做到这一点。 由于你正在使用图形文本,例如e.Graphics.DrawString ,因此将内部控件作为innerPictureBox应该很容易。

要交换滚动/滑动方向,请将VScroll默认起始值​​设置为其最大值,并设置内部控件Top = VScroll.Value (不需要减号)