2016-08-23 40 views
3

我發現VScrollBar(垂直滾動條可用Visual Studio工具框中)的一個奇怪的行爲。問題是「」如果我向下滑動滾動條,它會向上移動,如果向上滑動,則會向下移動「。微軟VSrollBar行爲或觸摸屏的錯誤 - Windows窗體

步驟來複制錯誤或行爲 - 1

1)添加VScrollBar作爲一個孩子的任何用戶控制。

2)向上或向下滑動用戶控件(不在滾動條上)。在相反的方向上垂直滾動條移動時,即使沒有內容控件和VScrollBar之間任何的程序化連接

步驟來複制錯誤或行爲 - 2

1)添加VScrollBar作爲子任用戶控制。

2)上滑動的滾動條,它將滑動期間滑動時向上移動上下向下(正確的行爲)

3)向上或向下滑動所述用戶控制。垂直滾動條向相反方向移動

4)現在向上或向下滑動垂直滾動條。垂直滾動條開始在相反的方向移動(錯誤行爲,僅發生錯誤沒有之後:1)

enter image description here

簡單的控制與垂直滾動條來複制此行爲

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); 
    } 

    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 


    private System.Windows.Forms.VScrollBar vScrollBar1; 

} 

問題:

有什麼辦法來克服這種行爲或錯誤?我希望滾動條在向下滑動時向下移動,並向上滑動時向上移動。當滑過內容時不應該有任何滾動

回答

4

我想要滾動條在向下滑動時向下移動並在向上滑動時向上移動。

按照漢斯Passants評論它只是一個系統設置(在註冊表項的形式):

enter image description here

答案其實是在爲超級用戶:

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<DataGridViewCheckBoxColumn>()) { 
       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<Flippable> flips = new List<Flippable>(); 
      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<bool?> 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

免責聲明:通常這個問題會得到封閉,重複但因爲它賞金,副本結束在超級用戶的我選擇在這裏分享這個問題的答案。完全感謝原作者:https://superuser.com/users/108033/richardhttps://superuser.com/users/132069/jamie-pate

+0

酷內部控制Top = VScroll.Value(沒有減號需要),給它一個去,讓我知道你如何去: ) –

+0

我試過這個應用程序,但仍然沒有運氣。另外,這與系統設置無關。我也在MSDN上發佈了關於這個行爲的問題https://social.msdn.microsoft.com/Forums/en-US/981f8b1c-9f7b-4a6f-9bda-4327703a3492/vertical-scrollbar-behavior-with-touch-screen?論壇=的WinForms。 – Kira

+1

註冊表中的設置是***全局***設置。你的應用程序不應該篡改它。如果用戶喜歡以某種方式讓她的電腦滾動,那麼您應該尊重這一點。 Hans評論的目的是爲了證明這不是Windows中的錯誤,而是一個可配置的設置(因爲它在Mac OS上)。讓用戶決定。 –

3

我想你想要的是一個視口。

基本上你把一個控制在一個PictureBox中。該控件的高度比使其成爲ViewPort的PictureBox高。

以前

enter image description here

你需要改變窗體設計器代碼來獲取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) 

enter image description here

然後手動將一個滾動條的圖片框的右側,便於行爲自己,如:

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

在VSCROLL事件:

TextBox.Top = -VScroll.Value; 

這將節省你從周圍碴系統設置以生成QuickViewer自定義控件。

您可以像編程PictureBox拖動事件一樣添加智能來設置ScrollBar(以及隨後的內部控件頂部)。對於大多數的內部控制你只需要制定出高這是很容易使用for循環,例如:

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

對於內部TextBox控件就可以制定出基於字體大小和行數的高度。網上有很多examples顯示如何做到這一點。由於您使用圖形來編輯文本框,例如e.Graphics.DrawString,應該很容易將內部控件作爲innerPictureBox。

要交換滾動/滑動方向VSCROLL默認初始值設置到最大值,並設置

+0

謝謝,我會試一試 – Kira

+0

現在我有一個很不錯的主意,現在誰投票給我..... ooooh我偷了其他人們在這裏打雷?!戰略投票,所以複製的答案到頂部..不錯的一個! –

+0

我希望這不是因爲我在meta – Kira