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


    大家还是先来看看效果吧


    这次之所以一次写两个控件,其实主要是因为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实现

    咱们从第一行代码就要吧看出来是继承自系统控件而来的。
    public class ListBox : System.Windows.Forms.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现有的滚动条用现在的滚动条代替,第三步,让现有的滚动条和系统的滚动条实现同步即可。
    我实现滚动条的代码,大家也可以自己写这里只是一个参考吧
    看一下效果

    看一下代码吧,具体的素材大家到我源代码里面找吧,呵呵

    代码


    关于一些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 << 16));
    }
    public const int SB_THUMBTRACK = 5;
    public const int WM_HSCROLL = 0x114;
    public const int WM_VSCROLL = 0x115;
    [DllImport("user32.dll", EntryPoint = "GetScrollInfo")]
    public static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
    [DllImport("user32.dll", EntryPoint = "SetScrollInfo")]
    public static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO lpsi, bool fRedraw);

    [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool PostMessage(IntPtr hWnd, uint Msg, long wParam, int lParam);
    }



    最后一步控件同步效果

    代码
    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

    -------------------------------------------------------------------推荐文章--------------------------------------------------------------
    1.C#仿QQ皮肤 2.Sql2005学习笔记 3.httpHelper类

  • 相关阅读:
    链表的常用操作
    android简易论坛的制作
    Bmob后端云的使用
    马哥第九周
    马哥第八周
    马哥第七周
    马哥第六周
    马哥第五周
    马哥第四周
    马哥第三周
  • 原文地址:https://www.cnblogs.com/blogpro/p/11463127.html
Copyright © 2020-2023  润新知