`
wangangie5
  • 浏览: 36385 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

C#仿QQ皮肤-Label与ListBox 控件实现----寻求滚动条的解决方案

 
阅读更多

  C#仿QQ皮肤-实现原理系列文章导航 
  http://www.cnblogs.com/sufei/archive/2010/03/10/16 82847.html 
  大家还是先来看看效果吧
  
  这次之所以一次写两个控件,其实主要是因为Label控件实在是太简单了没有必要放放一个文章里写,所以就一次性来了。
  Label控件我就不再多说了,我直接把代码贴一下吧因为就几行代码,相信大家一眼就能看明白了。 
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  namespace CRD.WinUI.Misc
  {
  public  class Label:System.Windows.Forms.Label
  {
  public Label()
  : base()
  {
  this.BackColor = System.Drawing.Color.Transparent;
  }
  }
  }
  ListBox实现 咱们从第一行代码就要吧看出来是继承自系统控件而来的。 所以本身就具备了系统的ListBox的一些特性。老方法我们先来看看WndProc方法的实现  
  
  protected override void WndProc(ref System.Windows.Forms.Message m)
  {
  IntPtr hDC = IntPtr.Zero;
  Graphics gdc = null;
  switch (m.Msg)
  {
  case 133:
  hDC = Win32.GetWindowDC(m.HWnd);
  gdc = Graphics.FromHdc(hDC);
  Win32.SendMessage(this.Handle, WM_ERASEBKGND, hDC.ToInt32(), 0);
  SendPrintClientMsg();
  Win32.SendMessage(this.Handle, WM_PAINT, 0, 0);
  OverrideControlBorder(gdc);
  m.Result = (IntPtr)1;
  Win32.ReleaseDC(m.HWnd, hDC);
  gdc.Dispose();
  break;
  case WM_PAINT:
  base.WndProc(ref m);
  hDC = Win32.GetWindowDC(m.HWnd);
  gdc = Graphics.FromHdc(hDC);
  OverrideControlBorder(gdc);
  Win32.ReleaseDC(m.HWnd, hDC);
  gdc.Dispose();
  break;
  default:
  base.WndProc(ref m);
  break;
  }
  }
  这边的实现方法基本上和之前的控件一个样,所以我就不再多说原理了,大家随便看一下前几次的文章就明白了。
  下面我们来看一下怎么样换皮肤的事件
  也就是说在换皮肤的时候我们应该做那些工作 
  
  protected override void OnDrawItem(DrawItemEventArgs e)
  {
  Graphics g = e.Graphics;
  //绘制区域
  Rectangle r = e.Bounds;
  Font fn = null;
  if (e.Index >= 0)
  {
  if (e.State == DrawItemState.None)
  {
  //设置字体、字符串格式、对齐方式
  fn = e.Font;
  string s = (string)this.Items[e.Index];
  StringFormat sf = new StringFormat();
  sf.Alignment = StringAlignment.Near;
  //根据不同的状态用不同的颜色表示
  if (e.State == (DrawItemState.NoAccelerator | DrawItemState.NoFocusRect))
  {
  e.Graphics.FillRectangle(new SolidBrush(Color.Red), r);
  e.Graphics.DrawString(s, fn, new SolidBrush(Color.Black), r, sf);
  e.DrawFocusRectangle();
  }
  else
  {
  e.Graphics.FillRectangle(new SolidBrush(Color.White), r);
  e.Graphics.DrawString(s, fn, new SolidBrush(Shared.FontColor), r, sf);
  e.DrawFocusRectangle();
  }
  }
  else
  {
  fn = e.Font;
  StringFormat sf = new StringFormat();
  sf.Alignment = StringAlignment.Near;
  string s = (string)this.Items[e.Index];
  e.Graphics.FillRectangle(new SolidBrush(Shared.ControlBackColor), r);
  e.Graphics.DrawString(s, fn, new SolidBrush(Shared.FontColor), r, sf);
  }  
  } 
  }
  其实这些都不是今天要说的重点,这个控件的实现基础跟之前的一些控件基本上是一样的,像Textbox就和这个差不多,
  唯一我想说的是滚动条的实现,不多说了下面开始吧
  滚动条的实现
  如上面的图片大家已经看到了,图片在我的源代码里都有,我在这里就不多说了,一起来看是怎么实现 的吧,先说说思路,
  第一步,先制做一个自己的滚动条,随便做只要自己感觉漂亮就可以,第二步就是,利用Api把Listbox现有的滚动条用现在的滚动条代替,第三步,让现有的滚动条和系统的滚动条实现同步即可。
  我实现滚动条的代码,大家也可以自己写这里只是一个参考吧
  看一下效果
  看一下代码吧,具体的素材大家到我源代码里面找吧,呵呵 
  
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Drawing;
  using System.Data;
  using System.Text;
  using System.Windows.Forms;
  using System.Windows.Forms.Design;
  using System.Diagnostics;
  namespace CRD.WinUI.Misc
  {
  [Designer(typeof(ScrollbarControlDesigner))]
  public partial class CustomScrollbar : UserControl
  {
  protected Color moChannelColor = Color.Empty;
  protected Image moUpArrowImage = null;//上箭头
  //protected Image moUpArrowImage_Over = null;
  //protected Image moUpArrowImage_Down = null;
  protected Image moDownArrowImage = null;//下箭头
  //protected Image moDownArrowImage_Over = null;
  //protected Image moDownArrowImage_Down = null;
  protected Image moThumbArrowImage = null;
  protected Image moThumbTopImage = null;
  protected Image moThumbTopSpanImage = null;
  protected Image moThumbBottomImage = null;
  protected Image moThumbBottomSpanImage = null;
  protected Image moThumbMiddleImage = null;
  protected int moLargeChange = 10;
  protected int moSmallChange = 1;
  protected int moMinimum = 0;
  protected int moMaximum = 100;
  protected int moValue = 0;
  private int nClickPoint;
  protected int moThumbTop = 0;
  protected bool moAutoSize = false;
  private bool moThumbDown = false;
  private bool moThumbDragging = false;
  public new event EventHandler Scroll = null;
  public event EventHandler ValueChanged = null;
  private int GetThumbHeight()
  {
  int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
  float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
  int nThumbHeight = (int)fThumbHeight;
  if (nThumbHeight > nTrackHeight)
  {
  nThumbHeight = nTrackHeight;
  fThumbHeight = nTrackHeight;
  }
  if (nThumbHeight  nTrackHeight)
  {
  nThumbHeight = nTrackHeight;
  fThumbHeight = nTrackHeight;
  }
  if (nThumbHeight Skin"), Description("Channel Color")]
  public Color ChannelColor
  {
  get { return moChannelColor; }
  set { moChannelColor = value; }
  }
  [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
  public Image UpArrowImage
  {
  get { return moUpArrowImage; }
  set { moUpArrowImage = value; }
  }
  [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
  public Image DownArrowImage
  {
  get { return moDownArrowImage; }
  set { moDownArrowImage = value; }
  }
  [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
  public Image ThumbBottomImage
  {
  get { return moThumbBottomImage; }
  set { moThumbBottomImage = value; }
  }
  [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
  public Image ThumbMiddleImage
  {
  get { return moThumbMiddleImage; }
  set { moThumbMiddleImage = value; }
  }
  protected override void OnPaint(PaintEventArgs e)
  {
  e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Nearest Neighbor;
  if (UpArrowImage != null)
  {
  e.Graphics.DrawImage(UpArrowImage, new Rectangle(new Point(0, 0), new Size(this.Width, UpArrowImage.Height)));
  }
  Brush oBrush = new SolidBrush(moChannelColor);
  Brush oWhiteBrush = new SolidBrush(Color.FromArgb(255, 255, 255));
  //          函数名: rectangle 
  //功 能: 画一个矩形 
  //用 法: void far rectangle(int left, int top, int right, int bottom); 
  //draw channel left and right border colors
  e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(0, UpArrowImage.Height, 1, (this.Height - DownArrowImage.Height)));
  e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(this.Width - 1, UpArrowImage.Height, 1, (this.Height - DownArrowImage.Height)));
  //draw channel
  //e.Graphics.FillRectangle(oBrush, new Rectangle(1, UpArrowImage.Height, this.Width-2, (this.Height-DownArrowImage.Height)));
  e.Graphics.DrawImage(ThumbBottomImage, new Rectangle(0, UpArrowImage.Height, this.Width, (this.Height - DownArrowImage.Height)));
  //draw thumb
  int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
  float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
  int nThumbHeight = (int)fThumbHeight;
  if (nThumbHeight > nTrackHeight)
  {
  nThumbHeight = nTrackHeight;
  fThumbHeight = nTrackHeight;
  }
  //MessageBox.Show(nThumbHeight.ToString());
  if (nThumbHeight  nTrackHeight)
  {
  nThumbHeight = nTrackHeight;
  fThumbHeight = nTrackHeight;
  }
  if (nThumbHeight  0)
  {
  if (nPixelRange > 0)
  {
  if ((moThumbTop - SmallChange)  0)
  {
  if (nPixelRange > 0)
  {
  if ((moThumbTop + SmallChange) > nPixelRange)
  moThumbTop = nPixelRange;
  else
  moThumbTop += SmallChange;
  //figure out value
  float fPerc = (float)moThumbTop / (float)nPixelRange;
  float fValue = fPerc * (Maximum - LargeChange);
  moValue = (int)fValue;
  Debug.WriteLine(moValue.ToString());
  if (ValueChanged != null)
  ValueChanged(this, new EventArgs());
  if (Scroll != null)
  Scroll(this, new EventArgs());
  Invalidate();
  }
  }
  }
  }
  private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
  {
  this.moThumbDown = false;
  this.moThumbDragging = false;
  }
  private void MoveThumb(int y)
  {
  int nRealRange = Maximum - Minimum;
  int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
  float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
  int nThumbHeight = (int)fThumbHeight;
  if (nThumbHeight > nTrackHeight)
  {
  nThumbHeight = nTrackHeight;
  fThumbHeight = nTrackHeight;
  }
  if (nThumbHeight  0)
  {
  if (nPixelRange > 0)
  {
  int nNewThumbTop = y - (UpArrowImage.Height + nSpot);
  if (nNewThumbTop  nPixelRange)
  {
  moThumbTop = nNewThumbTop = nPixelRange;
  }
  else
  {
  moThumbTop = y - (UpArrowImage.Height + nSpot);
  }
  //figure out value
  float fPerc = (float)moThumbTop / (float)nPixelRange;
  float fValue = fPerc * (Maximum - LargeChange);
  moValue = (int)fValue;
  Debug.WriteLine(moValue.ToString());
  Application.DoEvents();
  Invalidate();
  }
  }
  }
  private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
  {
  if (moThumbDown == true)
  {
  this.moThumbDragging = true;
  }
  if (this.moThumbDragging)
  {
  MoveThumb(e.Y);
  }
  if (ValueChanged != null)
  ValueChanged(this, new EventArgs());
  if (Scroll != null)
  Scroll(this, new EventArgs());
  }
  }
  internal class ScrollbarControlDesigner : System.Windows.Forms.Design.ControlDesigner
  {
  public override SelectionRules SelectionRules
  {
  get
  {
  SelectionRules selectionRules = base.SelectionRules;
  PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];
  if (propDescriptor != null)
  {
  bool autoSize = (bool)propDescriptor.GetValue(this.Component);
  if (autoSize)
  {
  selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | SelectionRules.TopSizeable;
  }
  else
  {
  selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;
  }
  }
  return selectionRules;
  }
  }
  }
  }
  关于一些Api的方法吧,我都定义出来了直接用就行了 
  
  public class Win32API
  {
  [StructLayout(LayoutKind.Sequential)]
  public struct tagSCROLLINFO
  {
  public uint cbSize;
  public uint fMask;
  public int nMin;
  public int nMax;
  public uint nPage;
  public int nPos;
  public int nTrackPos;
  }
  public enum fnBar
  {
  SB_HORZ = 0,
  SB_VERT = 1,
  SB_CTL = 2
  }
  public enum fMask
  {
  SIF_ALL,
  SIF_DISABLENOSCROLL = 0X0010,
  SIF_PAGE = 0X0002,
  SIF_POS = 0X0004,
  SIF_RANGE = 0X0001,
  SIF_TRACKPOS = 0X0008
  }
  public static int MakeLong(short lowPart, short highPart)
  {
  return (int)(((ushort)lowPart) | (uint)(highPart
  SCROLLINFO info = tvImageListScrollInfo;
  info.nPos = customScrollbar1.Value;
  Win32API.SetScrollInfo(listBox1.Handle, (int)ScrollBarDirection.SB_VERT, ref info, true);
  Win32API.PostMessage(listBox1.Handle, Win32API.WM_VSCROLL, Win32API.MakeLong((short)Win32API.SB_THUMBTRACK, (short)(info.nPos)), 0);
  好了,现在我们拉一个控件到窗体上,就是我图1中的效果了。中间还有一些不好的地方,我争取改正,
  也希望大家多多提建议,
  我个人感觉这种方法不是什么很好的方法,如果是用C++来写的话会方便很多,但不知道c#是怎么写的,小弟确实不知道,还希望能得大家的帮助,一起来解决这个问题
  其实我在网上也找了不少的资料,有些方法清空是抄别别人的,不过效果是实现 的,但总是感觉 不理想,不是自己想要的,也希望能通过这篇文章收集到一些好的解决方案,欢迎大家提供资源和解决方法,小弟在些谢过。                                    欢迎大家转载,如有转载请注明文章来自:   http://sufei.cnblogs.com/   
  签名:做一番一生引以为豪的事业;在有生之年报答帮过我的人;并有能力帮助需要帮助的人;     
  QQ:361983679 Email:sufei.1013@163.com  MSN:sufei.1013@163.com 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics