C# Textbox,必须同时设置属性Multiline = True、ScrollBars=Horizontal、WordWrap=False才会显示出水平滚动条,且默认字体大小下,控件的Size.Height >= 33才能正常显示完全文本。这非常的丑陋!占空间!

想着能调节压缩一下滚动条的高度就好了,只是现实太残酷,滚动条没有高度属性可设置!!!

只能想办法重写Textbox了。折腾两天,各种百度,终于实现自己想要的结果。

1、新建自定义控件,改变继承自TextBox。

public partial class TinyXScrollBarTextBox : TextBox

2、在TinyXScrollBarTextBox的设计模式中,拖放两个panel作为滚动条和滑块。分别命名为:panelXScrollBar、panelXScrollSlider。

3、在InitializeComponent()函数中设置,this.Controls.Add(this.panelXScrollBar);this.panelXScrollBar.Controls.Add(this.panelXScrollSlider);

4、初始化三个关键属性,

        public TinyXScrollBarTextBox(){InitializeComponent();base.Multiline = true;base.WordWrap = false;base.ScrollBars = ScrollBars.None;}

并加入如下代码,屏蔽其修改:

        /// <summary>/// 屏蔽系统的滚动条设置。并显示为水平滚动,实际为 base.ScrollBars = ScrollBars.None;/// </summary>[Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)]public new ScrollBars ScrollBars{get{return ScrollBars.Horizontal;}set{base.ScrollBars = ScrollBars.None;}}        /// <summary>/// 屏蔽系统的多行开关,实际为 base.Multiline = true;/// </summary>//[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)][Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)]public new bool Multiline{get{return true;}set{base.Multiline = true;}}[Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)]public new bool WordWrap{get{return false;}set{base.WordWrap = false;}}

5、文本框文本发生变化时,过滤掉转行、回车(\r or \n)。并禁止输入回车键,使现为多行模式下表现得像单行模式。

        protected override void OnTextChanged(EventArgs e){ClearRNChar();var w = panelXScrollBar.Width;textGdiWidth = TextRenderer.MeasureText(Text, Font).Width;if (textGdiWidth > w){this.panelXScrollBar.Visible = true;var ws = panelXScrollBar.Width * 2 - textGdiWidth;ws = ws < 25 ? 25 : ws; //计算滑块的长度,并设置最小为25个像素。panelXScrollSlider.Width = ws;var sliderW = panelXScrollBar.Width - panelXScrollSlider.Width;int indexWidth = GetTextGdiWidthByIndex(SelectionStart);SliderLeft = (int)((indexWidth * 1.0) / textGdiWidth * sliderW);}else{panelXScrollBar.Visible = false;var start = SelectionStart;SelectionStart = 0;ScrollToCaret();SelectionStart = start;}base.OnTextChanged(e);}private void TinyXScrollBarTextBox_KeyDown(object sender, KeyEventArgs e){//屏蔽回车键if ((int)e.KeyCode == 13){e.SuppressKeyPress = true;}}

6、滑块的滑动代码,这部分来源于网络,找不到来源了,也不难。

        private static bool IsMove = false;                 //标识 鼠标在滑块上的运动状态 初始为falseprivate int X;                                      //定义一个变量 用于记录鼠标进入滑块中并按下时的位置private void panelXScrollSlider_MouseDown(object sender, MouseEventArgs e)          //鼠标对滑块的按下事件 {IsMove = true;                                                //标识鼠标开始移动  X = e.Location.X;                                              //鼠标的初始位置的X坐标panelXScrollSlider.BackColor = Color.FromArgb(200, 100, 100, 100); ;         //滑块颜色变为深一点的色}private void panelXScrollSlider_MouseMove(object sender, MouseEventArgs e)      //鼠标对滑块的 移动 事件{if (IsMove == true)                             //如果鼠标开始移动{if (panelXScrollSlider.Right >= this.Width){if ((e.Location.X - X) < 0)                     //如果 鼠标向左滑动  {panelXScrollSlider.Left += e.Location.X - X;         //将滑块的位置增加  增加的量是鼠标移动的距离}else                                                //如果鼠标向下移动{panelXScrollSlider.Left = this.Width - panelXScrollSlider.Width;         //滑块的位置始终为 滑条最底部的位置}}else if (panelXScrollSlider.Left <= 0){if ((e.Location.X - X) > 0){panelXScrollSlider.Left += e.Location.X - X;}else{panelXScrollSlider.Left = 0;}}else{panelXScrollSlider.Left += e.Location.X - X;}}}private void panelXScrollSlider_MouseUp(object sender, MouseEventArgs e)            //当鼠标松开时候 意味着 用户 不再需要滑动滑块{IsMove = false;                             //此时将标识变为falsepanelXScrollSlider.BackColor = Color.FromArgb(100, 100, 100, 100);       //颜色变为原来的暗色SliderLeft = panelXScrollSlider.Left;//通过设置触发内容的滚动。}private void panelXScrollSlider_MouseEnter(object sender, EventArgs e){panelXScrollSlider.BackColor = Color.FromArgb(200, 100, 100, 100);}private void panelXScrollSlider_MouseLeave(object sender, EventArgs e){panelXScrollSlider.BackColor = Color.FromArgb(100, 100, 100, 100);}

7、鼠标点滚动条的操作:在滑块的右侧点击,则向右滚动,反之亦然

        /// <summary>/// 在滑块的右侧点击,则向右滚动,反之亦然/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void panelXScrollBar_MouseClick(object sender, MouseEventArgs e){if (Text.Length == 0){return;}int oldStart = SelectionStart;int oldSlectedLen = SelectionLength;var ns = 0;if (e.X > panelXScrollSlider.Right){var rightindex = GetCharIndexFromPosition(new Point(this.panelXScrollBar.Right - 3, 1));ns = rightindex + 1;ns = ns > Text.Length - 1 ? Text.Length : ns;}else if (e.X < panelXScrollSlider.Left){var leftindex = GetCharIndexFromPosition(new Point(3, 1));ns = leftindex - 1;ns = ns < 0 ? 0 : ns;}SelectionStart = ns;SelectionLength = 0;ScrollToCaret();var left = (int)((ns * 1.0 / Text.Length) * (panelXScrollBar.Width - panelXScrollSlider.Width));panelXScrollSlider.Left = left;SelectionStart = oldStart;SelectionLength = oldSlectedLen;}

8、滑块与光标的联动。这一块实现得不是丝滑,不过差不多就得了。

找了很久也没有找到文字滚动的控制方式 ,只能利用了ScrollToCaret()来控制。

ScrollToCaret()只要光标能显示出来,就不再滚动,控制起来有些不够丝滑!同时滑块的位置计算也不是很精准,只是大概这样子。

----end----夜已深。不详写了,有兴趣的同学可以下载资源:

C#重写Winform的Textbox单行模式下滚动条。-C#文档类资源-CSDN下载

重写Winform的Textbox单行模式下滚动条。相关推荐

  1. c# 的 textbox 默认情况下是有最大字符长度限制的

    c# 的 textbox 默认情况下是有最大字符长度限制的 偶然发现还以为是以前的 windows 本身控件的限制,一查 msdn 居然是 C#(.net)自己限制的. " 属性值 类型:S ...

  2. 用C#实现C/S模式下软件自动在线升级[转载]

    摘要: 本文针对目前C/S模式下编写的应用程序可维护性差的特点,提出了一套自动在线升级的解决方案,分析了在线升级的困难及实现原理,并给出了实现升级的部分代码,具有实际参考价值和现实意义.本文程序代码均 ...

  3. 检测到在集成的托管管道模式下不适用的 ASP.NET 设置, HTTP 错误 500.23 解决方案...

    由于32位和64位操作系统存在着比较大的区别, 对于在32位操作系统开发出来的网站程序或者其他软件在64位操作系统上就有可能出现问题, 例如, 最近在配置一个网站程序到server 2008 R2系统 ...

  4. 敏捷开发模式下如何更好的进行测试

    最近CTO组建了一个敏捷开发团队,团队人员包括  PM.设计.开发.测试角色,主要由PM来主导团队走向,因为以前并没有参加过敏捷开发的经验,对敏捷开发做了简单理解后,参考了前人的一些意见,总结出在 敏 ...

  5. MVVM模式下实现拖拽

    MVVM模式下实现拖拽 原文:MVVM模式下实现拖拽 在文章开始之前先看一看效果图 我们可以拖拽一个"游戏"给ListBox,并且ListBox也能接受拖拽过来的数据, 但是我们不 ...

  6. C# WPF MVVM模式下在主窗体显示子窗体并获取结果

    01 - 前言 在winform中打开一个新的子窗体很简单,直接实例化窗体并show一下就可以: Form2 f2 = new Form2();f2.Show(); 或者 Form2 f2 = new ...

  7. 微服务模式下,实现前后端多资源服务调用

    Micro Services 首先,我先解释下,文章标题的意思: 咋看起来特别像是一个标题党????,可能是我没想好怎么表达,其实白话文就是:在微服务场景下,肯定会有很多子服务API,那多个前端项目如 ...

  8. IntelliJ IDEA for Windows 默认模式下的快捷键

    文章目录 General 通用 Debugging 调试 Search/ Replace 查询/替换 Editing 编辑 Refactoring 重构 Navigation 导航 Compile a ...

  9. IntelliJ IDEA for Mac 在eclipse(MacOS)模式下的快捷键

    文章目录 Mac键盘符号 eclipse(MacOS)模式下的快捷键 General 通用 Debugging 调试 Search/ Replace 查询/替换 Editing 编辑 Refactor ...

最新文章

  1. 北斗定位2.0版来了!普通人手机可用,全免费!
  2. 华为android8适配进度,华为 荣耀 O版本(Android 8.0)适配进度公告
  3. Bochs调试Linux内核6 - 启动过程调试 - 跳到bootsect引导程序执行
  4. 前端小白的 docker 配置nginx踩坑之旅
  5. nodejs+grunt配置记
  6. CheckBox控件
  7. python 什么是原类_Python 什么是元类(metaclasses)?
  8. linux命令行终端设置tab补全文件名或路径不区分大小写(大小写不敏感)
  9. 一位程序员妹纸讲述她是如何拿到美团offer的?
  10. poj1466二分图
  11. thinkphp 通过Redis实现增删改查操作
  12. 安装svn和安装svn汉化语言包
  13. 常见内网穿透工具使用总结
  14. python3做答题器_现在很火的答题赢钱游戏,让我来简单教你怎么做自动答题器...
  15. 未来教育mysql下载_未来教育计算机二级题库中的视频为什么无法播放?
  16. 不那么完美的 RSS 订阅方案 — feedly + RSSHub Radar
  17. SAP SD跨公司销售案例教程案例介绍
  18. 完整百度登录源代码(2015年1月27日更新)
  19. 网站点击量太大崩溃怎么办_网站崩溃时该怎么办
  20. 导热电池粘合剂市场现状及未来发展趋势

热门文章

  1. 利用GEE来下载landsat-TIRES数据
  2. 药企数字化转型需要哪些软件
  3. 360 for Linux 与 setuid
  4. WebRTC 教程一:WebRTC信令、架构和 API 入门
  5. 微信10亿日活场景下,微服务架构实践!15页PPT全解
  6. Android Graphics - Architecture
  7. 计算机网络七年级教学设计,初中七年级信息技术教案
  8. Access denied for user 'root'@'localhost' (using password: NO)
  9. mysql escape的用法_#ORACLE 每日一点# ESCAPE用法
  10. 导出oracle数据字典工具,Oracle数据字典的导出