TrackBar控件没有像其他控件那样,直接提供给用户重绘的函数,要实现个性化的TrackBar控件,一种方法是继承Control完全的自己实现,这种方法就是实现标准的Windows控件功能需要自己处理很多东西,例如:实现一样的属性、键盘的操作、鼠标滚动改变TrackBar的值等;另一种方法就是直接继承TrackBar控件,利用TrackBar的一些Windows消息,获取TrackBar控件的信息,然后自己完全重绘,这种方法的好处是保留TrackBar控件的标准操作和属性,但是需要比较清楚的了解TrackBar控件的Windows消息。本文将介绍使用第二种方法实现对TrackBar控件的美化。
首先,看看TrackBar控件美化后的效果:
下面来了解一下实现TrackBar控件美化需要的一些API消息。TrackBar控件相关的一些消息都是以TBM(TackBar Message)开头的,在TrackBar控件的美化中,主要用到了以下三个消息:
l TBM_GETCHANNELRECT 获取轨道的位置和大小。
l TBM_GETTHUMBRECT 获取滑块的位置和大小。
l TBM_GETNUMTICS 获取刻度的总个数。
要获取这些信息,只需要向TrackBar控件发送相应的消息即可,例如需要获取取轨道的位置和大小:
- SendMessage(hWnd, TBM.TBM_GETCHANNELRECT, 0, ref trackRect)
有了上面的知识,接下来就是重绘TrackBar控件了。重绘TrackBar控件,需要重写WndProc函数,在WM_PAINT消息实现重绘就行了:
- protected override void WndProc(ref Message m)
- {
- switch (m.Msg)
- {
- case WM.WM_PAINT:
- if (!_bPainting)
- {
- _bPainting = true;
- PAINTSTRUCT ps = new PAINTSTRUCT();
- NativeMethods.BeginPaint(m.HWnd, ref ps);
- DrawTrackBar(m.HWnd);
- NativeMethods.ValidateRect(m.HWnd, ref ps.rcPaint);
- NativeMethods.EndPaint(m.HWnd, ref ps);
- _bPainting = false;
- m.Result = Result.TRUE;
- }
- else
- {
- base.WndProc(ref m);
- }
- break;
- default:
- base.WndProc(ref m);
- break;
- }
- }
来看看DrawTrackBar函数,DrawTrackBar函数的功能就是获取TrackBar控件的一些信息,然后分别调用四个函数来绘制TrackBar控件:
l OnRenderBackground函数,绘制TrackBar控件的背景。
l OnRenderTick函数,绘制TrackBar控件的刻度。
l OnRenderTrack函数,绘制TrackBar控件的轨道。
l OnRenderThumb函数,绘制TrackBar控件的滑块。
这四个函数都是可以重写的,如果想实现不同样式的TrackBar控件,重写这四个函数,进行相应的绘制即可。看看DrawTrackBar函数的具体代码:
- private void DrawTrackBar(IntPtr hWnd)
- {
- ControlState state = ControlState.Normal;
- bool horizontal = base.Orientation == Orientation.Horizontal;
- ImageDc tempDc = new ImageDc(base.Width, base.Height);
- RECT trackRect = new RECT();
- RECT thumbRect = new RECT();
- Graphics g = Graphics.FromHdc(tempDc.Hdc);
- NativeMethods.SendMessage(
- hWnd, TBM.TBM_GETCHANNELRECT, 0, ref trackRect);
- NativeMethods.SendMessage(
- hWnd, TBM.TBM_GETTHUMBRECT, 0, ref thumbRect);
- Rectangle trackRectangle = horizontal ?
- trackRect.Rect :
- Rectangle.FromLTRB(
- trackRect.Top, trackRect.Left,
- trackRect.Bottom, trackRect.Right);
- if (ThumbHovering(thumbRect))
- {
- if (Helper.LeftKeyPressed())
- {
- state = ControlState.Pressed;
- }
- else
- {
- state = ControlState.Hover;
- }
- }
- using (PaintEventArgs pe = new PaintEventArgs(
- g, ClientRectangle))
- {
- OnRenderBackground(pe);
- }
- int ticks = NativeMethods.SendMessage(
- hWnd, TBM.TBM_GETNUMTICS, 0, 0);
- if (ticks > 0)
- {
- List<float> tickPosList = new List<float>(ticks);
- int thumbOffset = horizontal ?
- thumbRect.Rect.Width : thumbRect.Rect.Height;
- int trackWidth = trackRect.Right - trackRect.Left;
- float tickSpace = (trackWidth - thumbOffset) / (float)(ticks - 1);
- float offset = trackRect.Left + thumbOffset / 2f;
- for(int pos = 0; pos < ticks; pos ++)
- {
- tickPosList.Add(offset + tickSpace * pos);
- }
- using (PaintTickEventArgs pte = new PaintTickEventArgs(
- g, trackRectangle, tickPosList))
- {
- OnRenderTick(pte);
- }
- }
- using (PaintEventArgs pe = new PaintEventArgs(
- g, trackRectangle))
- {
- OnRenderTrack(pe);
- }
- using (PaintThumbEventArgs pe = new PaintThumbEventArgs(
- g, thumbRect.Rect, state))
- {
- OnRenderThumb(pe);
- }
- g.Dispose();
- IntPtr hDC = NativeMethods.GetDC(hWnd);
- NativeMethods.BitBlt(
- hDC, 0, 0, base.Width, base.Height,
- tempDc.Hdc, 0, 0, 0xCC0020);
- NativeMethods.ReleaseDC(hWnd, hDC);
- tempDc.Dispose();
- }
最后需要说明的是,扩展后的TrackBar控件还实现了一个ColorTable属性,只要通过ColorTable设置相应的颜色,就可以得到不同颜色效果的TrackBar控件了。看看TrackBar控件的完整类视图:
TrackBar控件的美化换肤到此就实现了,希望对你了解TrackBar控件的美化有所帮助。