using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Drawing.Design; using System.Runtime.InteropServices; using System.Windows.Forms.VisualStyles; namespace CustomCtrldemo { /// <summary> /// C#自定义控件上添加滚动条的实例 /// 开发人:NNswrod,网站:www.west163.net,QQ:16349023,Email:coolmoonf@163.com /// csdn博客:http://blog.csdn.net/nnsword /// </summary> public partial class CustomControl1 : Control { public CustomControl1() { InitializeComponent(); AddScroolBars(); m_hScroll.Visible = false; m_vScroll.Visible = false; } #region //field & property TextFormatFlags m_TextFormatFlags = TextFormatFlags.Left | TextFormatFlags.Top | TextFormatFlags.LeftAndRightPadding | TextFormatFlags.ExternalLeading | TextFormatFlags.WordBreak; /// <summary> /// 垂直滚动条 /// </summary> VScrollBar m_vScroll; /// <summary> /// 垂直滚动条panel /// </summary> Panel m_vScrollPanel; /// <summary> /// 水平滚动条 /// </summary> HScrollBar m_hScroll; /// <summary> /// 水平滚动条 /// </summary> Panel m_hScrollFiller; /// <summary> /// 水平滚动条 /// </summary> Panel m_hScrollPanel; Rectangle _RectContext = new Rectangle(); /// <summary> /// 内容绘制块 /// </summary> protected Rectangle RectContext { get { return _RectContext; } } /// <summary> /// 边框宽度 /// </summary> private int _BorderWidth = 1; private Color _BorderColor =SystemColors.GradientInactiveCaption; /// <summary> /// 边框颜色 /// </summary> public Color BorderColor { get { return _BorderColor; } set { if (_BorderColor != value) { _BorderColor = value; this.Invalidate(); } } } /// <summary> /// 控件主体区域 /// </summary> protected Rectangle BodyBounds { get { Rectangle lRect = this.ClientRectangle; lRect.Offset(_BorderWidth, _BorderWidth); if (m_vScroll.Visible) { lRect.Width -= _BorderWidth+2+m_vScroll.Width; } else { lRect.Width -= _BorderWidth * 2; } if (m_hScroll.Visible) { lRect.Height -= _BorderWidth+2+m_hScroll.Height; } else { lRect.Height -= _BorderWidth * 2; } return lRect; } } public override string Text { get { return base.Text; } set { if (base.Text != value) { base.Text = value; UpdateScroll(); this.Invalidate(); } } } #endregion #region // override protected override void OnPaint(PaintEventArgs pe) { // TODO: 在此处添加自定义绘制代码 // 调用基类 OnPaint base.OnPaint(pe); CustomPaint(pe.Graphics); } protected override void OnResize(EventArgs e) { base.OnResize(e); //UpdateContextAndScroll(); UpdateScroll(); Graphics g = Graphics.FromHwnd(this.Handle); CustomPaint(g); } #endregion #region //private void UpdateScroll() { Size si = TextRenderer.MeasureText(base.Text, this.Font, BodyBounds.Size, m_TextFormatFlags); if (si.Width > BodyBounds.Width) { m_hScroll.Visible = true; m_hScroll.Maximum = si.Width-(TextRenderer.MeasureText("我", this.Font).Width); m_hScroll.Value = 0; //_RectContext.Width = si.Width; } else { m_hScroll.Visible = false; } if (si.Height > BodyBounds.Height) { m_vScroll.Visible = true; m_vScroll.Maximum = si.Height - (TextRenderer.MeasureText("我", this.Font).Height); m_vScroll.Value = 0; //_RectContext.Height = si.Height; } else { m_vScroll.Visible = false; } _RectContext = BodyBounds; if (m_hScroll.Visible) _RectContext.Width = si.Width + (TextRenderer.MeasureText("我", this.Font).Width); if (m_vScroll.Visible) _RectContext.Height = si.Height + (TextRenderer.MeasureText("我", this.Font).Height); } private void CustomPaint(Graphics g) { try { OnPaintBody(g); OnPaintBorder(g); } catch { } finally { g.Dispose(); } } void AddScroolBars() { // I was not able to get the wanted behavior by using ScrollableControl with AutoScroll enabled. // horizontal scrolling is ok to do it by pixels, but for vertical I want to maintain the headers // and only scroll the rows. // I was not able to manually overwrite the vscroll bar handling to get this behavior, instead I opted for // custom implementation of scrollbars // to get the 'filler' between hscroll and vscroll I dock scroll + filler in a panel m_hScroll = new HScrollBar(); m_hScroll.Scroll += new ScrollEventHandler(OnHScroll); m_hScroll.Dock = DockStyle.Fill; m_vScroll = new VScrollBar(); m_vScroll.Scroll += new ScrollEventHandler(OnVScroll); m_vScroll.Dock = DockStyle.Left; m_vScrollPanel = new Panel(); m_vScrollPanel.BackColor = Color.Transparent; m_vScrollPanel.Width = m_vScroll.Width+2; m_vScrollPanel.Dock = DockStyle.Right; m_vScrollPanel.Padding = new Padding(0, 2, 2, 0); m_vScrollPanel.Controls.Add(m_vScroll); m_hScrollFiller = new Panel(); m_hScrollFiller.BackColor = Color.Transparent; m_hScrollFiller.Size = new Size(m_vScroll.Width - 1, m_hScroll.Height); m_hScrollFiller.Dock = DockStyle.Right; Controls.Add(m_vScrollPanel); m_hScrollPanel = new Panel(); m_hScrollPanel.Height = m_hScroll.Height+2; m_hScrollPanel.BackColor = Color.Transparent; m_hScrollPanel.Dock = DockStyle.Bottom; m_hScrollPanel.Controls.Add(m_hScroll); m_hScrollPanel.Controls.Add(m_hScrollFiller); m_hScrollPanel.Padding = new Padding(2, 0, 2, 2); Controls.Add(m_hScrollPanel); } void OnVScroll(object sender, ScrollEventArgs e) { int diff = e.NewValue - e.OldValue; if (e.NewValue == 0) { diff = 0; _RectContext.Y = BodyBounds.Y; } _RectContext.Offset(0,-diff); Invalidate(); } void OnHScroll(object sender, ScrollEventArgs e) { int diff = e.NewValue - e.OldValue; //assumedScrollPos += diff; if (e.NewValue == 0) { //m_firstVisibleNode = Nodes.FirstNode; diff = 0; _RectContext.X = BodyBounds.X; } _RectContext.Offset( -diff,0); Invalidate(); Invalidate(); } #endregion #region //protected protected void OnPaintBody(Graphics g) { g.FillRectangle(Brushes.White, BodyBounds); if (this.Text.Length < 1) { TextRenderer.DrawText(g, "请输入要显示文本", this.Font, _RectContext, Color.LightGray, m_TextFormatFlags); } else { TextRenderer.DrawText(g, this.Text, this.Font, _RectContext, Color.Black, m_TextFormatFlags); } } protected void OnPaintBorder(Graphics g) { Rectangle lRect = this.ClientRectangle; lRect.Width -= _BorderWidth; lRect.Height -= _BorderWidth; g.DrawRectangle(new Pen(BorderColor), lRect); } #endregion } }