天天看点

C# WinForm控件美化扩展系列之TabControl控件(1)C# WinForm控件美化扩展系列之TabControl控件(1)

C# WinForm控件美化扩展系列之TabControl控件(1)

2009-10-30  来自:CS 程序员之窗  字体大小:【 大  中  小】

  • 摘要:这篇文章我们将介绍TabControl控件的美化,因为它跟NumericUpDown控件一样,也包含一个UpDownButton按钮,这篇文章只介绍对TabControl的UpDownButton按钮的美化,接下来的文章将一步步的介绍对TabControl的完全美化。

前面的文章C# WinForm控件美化扩展系列之UpDown控件NumericUpDown中介绍了对NumericUpDown控件的美化,这篇文章我们将介绍TabControl控件的美化,因为它跟NumericUpDown控件一样,也包含一个UpDownButton按钮,这篇文章只介绍对TabControl的UpDownButton按钮的美化,接下来的文章将一步步的介绍对TabControl的完全美化。

当TabControl控件的TabPage页比较多的时候,TabPage页有些显示不完,它就会显示一个UpDownButton按钮,用来操作移动TabPage的显示。这个UpDownButton按钮不像NumericUpDown控件那样容易得到,需要通过API函数FindWindowEx来得到,通过FindWindowEx函数来查找UpDownButton按钮,需要知道它的类名,通过SPY++可以查询到,它的类名为“msctls_updown32”。看看查找UpDownButton按钮的代码:

        private IntPtr FindUpDownButton()

        {

            return NativeMethods.FindWindowEx(

                base.Handle,

                IntPtr.Zero,

                UpDownButtonClassName,

                null);

        }

    得到了UpDownButton按钮,就可以用NumericUpDown一样的步骤方法对它进行美化了,不过要注意的是,当TabControl控件增加TabPage页或者TabControl控件调整大小的时候,需要查询是否需要显示UpDownButton按钮,否者就不能对它进行美化了,因为如果刚开始的时候控件不需要显示UpDownButton按钮的话,是查询不到它的,那样就没能对它的绘制消息进行截取。

    跟以前一样,还是要实现一个UpDownButtonNativeWindow类,把UpDownButton的句柄分配给它,就可以通过它截取UpDownButton的消息了。在这个类里面,截取WM_PAINT消息,重绘UpDownButton控件。来看看UpDownButtonNativeWindow类的完整实现代码:

        private class UpDownButtonNativeWindow : NativeWindow, IDisposable

        {

            private TabControlEx _owner;

            private bool _bPainting;

            public UpDownButtonNativeWindow(TabControlEx owner)

                : base()

            {

                _owner = owner;

                base.AssignHandle(owner.UpDownButtonHandle);

            }

            private bool LeftKeyPressed()

            {

                if (SystemInformation.MouseButtonsSwapped)

                {

                    return (NativeMethods.GetKeyState(NativeMethods.VK_RBUTTON) < 0);

                }

                else

                {

                    return (NativeMethods.GetKeyState(NativeMethods.VK_LBUTTON) < 0);

                }

            }

            private void DrawUpDownButton()

            {

                bool mouseOver = false;

                bool mousePress = LeftKeyPressed();

                bool mouseInUpButton = false;

                NativeMethods.RECT rect = new NativeMethods.RECT();

                NativeMethods.GetClientRect(base.Handle, ref rect);

                Rectangle clipRect = Rectangle.FromLTRB(

                    rect.Top, rect.Left, rect.Right, rect.Bottom);

                Point cursorPoint = new Point();

                NativeMethods.GetCursorPos(ref cursorPoint);

                NativeMethods.GetWindowRect(base.Handle, ref rect);

                mouseOver = NativeMethods.PtInRect(ref rect, cursorPoint);

                cursorPoint.X -= rect.Left;

                cursorPoint.Y -= rect.Top;

                mouseInUpButton = cursorPoint.X < clipRect.Width / 2;

                using (Graphics g = Graphics.FromHwnd(base.Handle))

                {

                    UpDownButtonPaintEventArgs e =

                        new UpDownButtonPaintEventArgs(

                        g,

                        clipRect,

                        mouseOver,

                        mousePress,

                        mouseInUpButton);

                    _owner.OnPaintUpDownButton(e);

                }

            }

            protected override void WndProc(ref Message m)

            {

                switch (m.Msg)

                {

                    case NativeMethods.WM_PAINT:

                        if (!_bPainting)

                        {

                            NativeMethods.PAINTSTRUCT ps =

                                new NativeMethods.PAINTSTRUCT();

                            _bPainting = true;

                            NativeMethods.BeginPaint(m.HWnd, ref ps);

                            DrawUpDownButton();

                            NativeMethods.EndPaint(m.HWnd, ref ps);

                            _bPainting = false;

                            m.Result = NativeMethods.TRUE;

                        }

                        else

                        {

                            base.WndProc(ref m);

                        }

                        break;

                    default:

                        base.WndProc(ref m);

                        break;

                }

            }

            #region IDisposable 成员

            public void Dispose()

            {

                _owner = null;

                base.ReleaseHandle();

            }

            #endregion

        }

    根据前面的说明,需要在控件创建、增加TabPage页、调整大小的时候,对其进行消息截取,看看下面相应的几个方法:

        protected override void OnHandleCreated(EventArgs e)

        {

            base.OnHandleCreated(e);

            if (UpDownButtonHandle != IntPtr.Zero)

            {

                if (_upDownButtonNativeWindow == null)

                {

                    _upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);

                }

            }

        }

        protected override void OnCreateControl()

        {

            base.OnCreateControl();

            if (UpDownButtonHandle != IntPtr.Zero)

            {

                if (_upDownButtonNativeWindow == null)

                {

                    _upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);

                }

            }

        }

        protected override void OnControlAdded(ControlEventArgs e)

        {

            base.OnControlAdded(e);

            if (UpDownButtonHandle != IntPtr.Zero)

            {

                if (_upDownButtonNativeWindow == null)

                {

                    _upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);

                }

            }

        }

        protected override void OnSizeChanged(EventArgs e)

        {

            base.OnSizeChanged(e);

            if (UpDownButtonHandle != IntPtr.Zero)

            {

                if (_upDownButtonNativeWindow == null)

                {

                    _upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);

                }

            }

        }

    当然,在控件销毁的时候,也需要清理UpDownButtonNativeWindow:

     protected override void OnHandleDestroyed(EventArgs e)

        {

            base.OnHandleDestroyed(e);

            if (_upDownButtonNativeWindow != null)

            {

                _upDownButtonNativeWindow.Dispose();

                _upDownButtonNativeWindow = null;

            }

        }

    这样,我们实现了对TabControl的UpDownButton按钮的美化,因为这个代码还没有完整的实现TabControl的美化,所以先不提供源码下载了,接下来的文章将实现对TabControl进一步的美化,到时候就可以把完整的代码提供下载了,希望大家继续关注。

声明:

本文版权归作者和CS 程序员之窗所有,欢迎转载,转载必须保留以下版权信息,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

作者:Starts_2000

出处:CS 程序员之窗 http://www.csharpwin.com。

你可以免费使用或修改提供的源代码,但请保留源代码中的版权信息,详情请查看:

CS程序员之窗开源协议 http://www.csharpwin.com/csol.html。