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
发表评论
-
字符串补足
2012-07-06 09:51 565很多交易中都会涉及到根据一定的规则生成固定长度的流水号的问 ... -
两个正则表达式的应用-国内电话和IP
2012-07-06 09:45 680匹配中国的的电话号码: 0\d{2}-\d{8}|0 ... -
全面分析Linux正则表达式(二)
2012-07-06 09:37 731Linux正则表达式不 ... -
JS表单使用总结
2012-07-05 20:45 6551 javascript刷新页面的方法 window ... -
Android平台学习:组件的生命周期
2012-07-03 13:43 632Android平台上的应用组件生命周期,以下是我从开发者向 ... -
Flex控制对主机网页中脚本的访问
2012-07-02 10:43 530通过使用以下 Action ... -
每天学一点flex(3) :垂直布局在不同版本的sdk是否存在差异?
2012-07-02 10:43 493昨天下载了一个新版本flex 4.1 sdk 包含升级ad ... -
Flex中本地图片上传前的预览
2012-07-02 10:43 576width="456" he ... -
Flex Panel 拖动效果例子
2012-07-02 10:43 6072010-08-06 今天在flex下尝试了下panel ... -
android开发基础[源码获取及编译、模拟器使用]
2012-07-01 00:21 670原文地址:http://bbs.a ... -
myeclipse中没有add web project capability
2012-07-01 00:21 742在将flex转为web项目时,发现没有add web pr ... -
OpenMeetings的安装
2012-07-01 00:21 647最近帮别人能一个 ... -
Ext 4 概述(六)之Grid
2012-07-01 00:21 501这次升级Ext 4全部 ...
相关推荐
计算机软件-商业源码-46 响应ListBox控件的滚动条事件.zip
计算机软件-商业源码-47 为ListBox控件添加水平滚动条.zip
实现ListBox控件与ListBox控件交换数据
使用ListBox控件实现简单的餐馆点菜功能.rar使用ListBox控件实现简单的餐馆点菜功能.rar
c# Listbox自动滚动
2、Label 控件 3 3、TextBox 控件 4 4、RichTextBox控件 5 5、NumericUpDown 控件 7 6、Button 控件 7 7、GroupBox 控件 7 8、RadioButton控件 8 9、CheckBox 控件 8 10、ListBox 控件 9 11、ComboBox 控件 10 12、...
C#的winform中对combobox和listbox控件SelectedValue属性重写,使得在没有绑定数据源情况下可以使用SelectedValue获取当前选中项的value值。源码下载。
二、Label 控件 - 3 - 三、TextBox 控件 - 3 - 四、RichTextBox控件 - 5 - 五、NumericUpDown 控件 - 7 - 六、Button 控件 - 7 - 七、GroupBox 控件 - 8 - 八、RadioButton控件 - 8 - 九、CheckBox 控件 - 8 - 十、...
利用ListBox控件实现数据源字段的选择,从左边的列表中挑选数据移动至右侧列表中,当然也可从右侧移动至左边的列表中。大家在浏览网页的时候就会发现,有些招聘网站在选择职位的时候就有类似的功能,只不过是基于...
(1)通过鼠标可以将一个ListBox控件中的任意一项拖到另一个ListBox控件中,反之亦然;(2)拖动时,鼠标呈手势状,以拖动操作更具形象化。
重画ListView控件,包括重画列头、选中时颜色和隔行换色功能。
一个简单的示例教你如何实现winform的ListBox控件拖拽排序功能
listbox 上下 左右 滚动条都出现
一直就想改一下memo控件的滚动条,但一直没能实现,众里寻她千百度也没结果,现在应该差不多了,终于花了2、3天时间,给memo控件与listbox控件加上了背景图片,并自绘了他们的滚动条、光标、所选内容,同时,在memo...
重绘ListBox控件
NULL 博文链接:https://helloandy2009.iteye.com/blog/712615
在MFC中,为ListBox创建水平滚动条,使其在应该出现的时候出现,不应该出现的时候消失,而且应能自动调节自己的大小。
webfrom- ListBox 控件的使用.pdf
在C#中使用ListBox控件实例源码在