回 帖 发 新 帖 刷新版面

主题:[原创]打造自己的多风格按纽--用户控件制作详解(3)

打造自己的多风格按纽--用户控件制作详解(3)

五、按纽的背景色以及文本标题的字体、颜色
  到现在为止,我们这个按纽的背景色以及文本标题的字体和颜色都还不能变化,要使它能按照我们
的要求来设置,就必须要加上这三个属性。这三个属性都是 UserControl控件的基本属性,可以不需要
在 Option Explicit 节中声明相应的变量,但为了以后的编程方便,我们还是在Option Explicit节中
声明一下映射两个颜色属性的变量吧:

Dim vBackColor As Long  '背景色
Dim vForeColor As Long  '前景色

  添加三对属性过程:

Public Property Get BackColor() As OLE_COLOR
BackColor = vBackColor
End Property

Public Property Let BackColor(ByVal NewColor As OLE_COLOR)
vBackColor = NewColor
UserControl.BackColor = NewColor
PropertyChanged "BackColor"
PrintCaption
End Property

Public Property Get ForeColor() As OLE_COLOR
ForeColor = vForeColor
End Property

Public Property Let ForeColor(ByVal NewColor As OLE_COLOR)
vForeColor = NewColor
UserControl.ForeColor = NewColor
PropertyChanged "ForeColor"
PrintCaption
End Property

Public Property Get Font() As Font
Set Font = UserControl.Font
End Property

Public Property Set Font(ByVal NewFont As Font)
Set UserControl.Font = NewFont
PropertyChanged "Font"
PrintCaption
End Property

  要注意的是:
1.OLE_COLOR 的数据类型是颜色,实质上也是长整形的数据类型,但它会自动调出颜色对话框。
2.特别注意 Font 的与众不同之处:
  ①它没有“Let”过程,而是以“Set”过程取代。当要给对象变量赋值的时候,不能用 Let,而必
须用 Set 来代替。这是因为保存在控件内部的对象变量,保存的并不是对象的拷贝,而只是对象的引用
(也就是一个内存地址)。
  ②在它的两个属性过程中,均须在等式的前面加上“Set”关键字。

  属性设置好后,还需在ReadProperties过程中添加代码:

Set UserControl.Font = PropBag.ReadProperty("Font", Ambient.Font)
vForeColor = PropBag.ReadProperty("ForeColor", Ambient.ForeColor)
UserControl.ForeColor = vForeColor
vBackColor = PropBag.ReadProperty("BackColor", &H8000000F)
UserControl.BackColor = vBackColor

  在WriteProperties过程中添加代码:

PropBag.WriteProperty "Font", UserControl.Font, Ambient.Font
PropBag.WriteProperty "ForeColor", UserControl.ForeColor, Ambient.ForeColor
PropBag.WriteProperty "BackColor", UserControl.BackColor, &H8000000F
  
  在InitProperties过程中添加代码:

vBackColor = &H8000000F

  在PrintCaption过程的第一行添加代码:

UserControl.ForeColor = IIf(UserControl.Enabled, vForeColor, &H80000011)

  注意了:在这一行代码中对按纽的 Enabled属性值进行判断,如果为 False,那么就使用失效的文
本色,反之才使用 vForeColor 作为文本的当前色。为了在设置 Enabled属性时也能体现出这种效果,
还需要在 Let Enabled 过程后面加一行调用打印文本过程的语句:PrintCaption

  接着添加以下属性描述:

Font:返回/设置标题文本的字体、字型、字号以及下划线等。
BackColor:返回/设置按纽的背景色,该颜色仅在不使用渐变颜色时才起作用。
ForeColor:返回/设置按纽中标题文本和图形的前景色。

  现在进入程序设计的窗体页面,在 PrettyCmd 属性窗口可以看到这三个属性,并且可以设置它们
了。但你会发现,改变字体或者标题文本后,字符在按纽上重叠了,不要紧,后面我们会解决这个问题
的。


六、为按纽添加渐变色彩
  很多第三方的按纽控件,背景颜色都是渐变的,很好看哦。我们的按纽要体现出“多风格”的意思
,怎么着也得为它加上渐变的颜色吧。
  所谓“色彩渐变”,是指控件的颜色从上至下(或者从左至右)地由某一种颜色逐渐变化过渡到另
一种颜色,这样,我们就要增加两个颜色属性,用以表示起始色和结束色,中间的过渡色,当然是由程
序自动生成啦。为了选择颜色渐变是自上而下还是自左而右,则还要增加一个标记属性。这样,一共就
要增加三个属性,下面且听我细细道来。
  首先在Option Explicit节中声明如下:

Public Enum mBJShadeModus    '渐变方式
  无色彩渐变
  从上至下渐变
  从左至右渐变
End Enum

Dim vStartColor As Long      '渐变起始色
Dim vCeaseColor As Long      '渐变结束色
Dim BJShadeModus As Integer  '渐变方式标记

  添加三对属性过程:

Public Property Get ShadeModus() As mBJShadeModus
ShadeModus = BJShadeModus
End Property

Public Property Let ShadeModus(ByVal vNewValue As mBJShadeModus)
BJShadeModus = vNewValue
PropertyChanged "ShadeModus"
PaintColor
End Property

Public Property Get CeaseColor() As OLE_COLOR
CeaseColor = vCeaseColor
End Property

Public Property Let CeaseColor(ByVal NewColor As OLE_COLOR)
vCeaseColor = NewColor
PropertyChanged "CeaseColor"
PaintColor
End Property

Public Property Get StartColor() As OLE_COLOR
StartColor = vStartColor
End Property

Public Property Let StartColor(ByVal NewColor As OLE_COLOR)
vStartColor = NewColor
PropertyChanged "StartColor"
PaintColor
End Property

  这三个属性过程中都调用了处理颜色渐变的 PaintColor 子过程,下面是 PaintColor 的代码:

Sub PaintColor()
On Error Resume Next
Dim uH As Single, uW As Single
Dim rInfo As Single, gInfo As Single, bInfo As Single
Dim rSta As Long, gSta As Long, bSta As Long
Dim rEnd As Long, gEnd As Long, bEnd As Long


Dim R As Long, G As Long, B As Long, i As Long

If BJShadeModus > 0 Then
  uH = UserControl.ScaleHeight: uW = UserControl.ScaleWidth
  rSta = vStartColor Mod 256: gSta = vStartColor \ 256 Mod 256: bSta = vStartColor \ 256 \ 256
  rEnd = vCeaseColor Mod 256: gEnd = vCeaseColor \ 256 Mod 256: bEnd = vCeaseColor \ 256 \ 256

  rInfo = (rEnd - rSta) / IIf(BJShadeModus = 1, uH, uW)
  gInfo = (gEnd - gSta) / IIf(BJShadeModus = 1, uH, uW)
  bInfo = (bEnd - bSta) / IIf(BJShadeModus = 1, uH, uW)
End If

Select Case BJShadeModus
  Case 0
    UserControl.BackColor = vBackColor
    Cls
  Case 1
    For i = 0 To uH - 1
      R = rSta + i * rInfo: G = gSta + i * gInfo: B = bSta + i * bInfo
      UserControl.ForeColor = RGB(R, G, B)
      UserControl.Line (0, i)-(uW - 1, i)
    Next
  Case 2
    For i = 0 To uW - 1
      R = rSta + i * rInfo: G = gSta + i * gInfo: B = bSta + i * bInfo
      UserControl.ForeColor = RGB(R, G, B)
      UserControl.Line (i, 0)-(i, uH - 1)
    Next
End Select
PrintCaption
End Sub

  分析PaintColor子过程,我们得知,原来渐变色是由逐渐改变控件的前景色得到的,而不采用改变
背景色的办法,是因为背景色只能是纯色,无法产生渐变效果。好,再继续我们未竞的工作:

  将 DrawButton、Let BackColor、Let CeaseColor、Set Font 四个过程中调用 PrintCaption的语
句删除,改为调用 PaintColor。

  在 ReadProperties 过程中添加代码:

vStartColor = PropBag.ReadProperty("StartColor", &HFFFFC0)
vCeaseColor = PropBag.ReadProperty("CeaseColor", &H8000&)
BJShadeModus = PropBag.ReadProperty("ShadeModus", 1)

  在 WriteProperties 过程中添加代码:

PropBag.WriteProperty "StartColor", vStartColor, &HFFFFC0
PropBag.WriteProperty "CeaseColor", vCeaseColor, &H8000&
PropBag.WriteProperty "ShadeModus", BJShadeModus, 1

  在 InitProperties 过程中添加代码:

BJShadeModus = 1
vStartColor = &HFFFFC0
vCeaseColor = &H8000&

  添加属性描述:

ShadeModus:返回/设置按纽色彩渐变方式,即:是否渐变,以及渐变的方向。
StartColor:返回/设置当ShadeColor属性设为 1 或 2 时,按纽色彩渐变的起始色。
CeaseColor:返回/设置当ShadeColor属性设为 1 或 2 时,按纽色彩渐变的结束色。

  一切都弄好后,赶紧试一试哦,哇噻,真的好漂亮!

七、对字体的美化

  现在我们自制的按纽控件,看起来是比较赏心悦目了。美中不足的是,标题文本的字体看起来都是
平面的,让我们加上一些特技,使字体显示更加富有个性!
  为此,需要在 Option Explicit 节中作如下声明:

Public Enum mCaptionStunt  '文本特技
  常规
  立体
  浮雕
  雕刻
End Enum

Dim vCaptionStunt As Integer '文本特技值

  添加一对属性过程:

Public Property Get CaptionStunt() As mCaptionStunt
CaptionStunt = vCaptionStunt
End Property

Public Property Let CaptionStunt(ByVal vNewValue As mCaptionStunt)
vCaptionStunt = vNewValue
PropertyChanged "CaptionStunt"
PaintColor
End Property

  添加属性描述:“返回/设置标题文本的字体特技。”

  在 ReadProperties 过程中添加:

vCaptionStunt = PropBag.ReadProperty("CaptionStunt", 0)

  在 WriteProperties 过程中添加:

PropBag.WriteProperty "CaptionStunt", vCaptionStunt, 0

  对 PrintCaption 过程加以修改,修改后的代码如下:

Private Sub PrintCaption()
Dim x1 As Integer, y1 As Integer
x1 = (UserControl.ScaleWidth - UserControl.TextWidth(vCaption)) / 2
y1 = (UserControl.ScaleHeight - UserControl.TextHeight(vCaption)) / 2

If vCaptionStunt > 0 Then
  Dim x2 As Integer, y2 As Integer, z As Integer
  z = UserControl.FontSize '获取字号
  Select Case vCaptionStunt
    Case 1 '立体
      UserControl.ForeColor = &H80000011 '设置字体阴影部分的颜色
      x2 = x1 - 1 + (z > 28) + (z > 48): y2 = y1 - 1 + (z > 28) + (z > 48)
    Case 2 '浮雕
      UserControl.ForeColor = &HFFC0C0
      x2 = x1 + 1 - (z > 28) - (z > 48): y2 = y1 - 1 + (z > 28) + (z > 48)
    Case 3 '雕刻
      UserControl.ForeColor = vbWhite
      x2 = x1 + 1 - (z > 28) + (z > 48): y2 = y1 + 1 - (z > 28) - (z > 48)
  End Select
  UserControl.CurrentX = x2: UserControl.CurrentY = y2
  UserControl.Print vCaption
End If

UserControl.ForeColor = IIf(UserControl.Enabled, vForeColor, &H80000011)
UserControl.CurrentX = x1: UserControl.CurrentY = y1
UserControl.Print vCaption

UserControl.ForeColor = vForeColor
End Sub

  这三个特技实质上都是将标题文本重复打印一次,只不过稍许移动了打印位置,并且改变了前景色
而已。
  一切都OK后,再进入程序设计的窗体页面,在 PrettyCmd 属性窗口就可以看到 CaptionStunt属性
了,来吧,试一试改变它的值,并同时改变标题文本的字体、字型、字号、前景色,都试一试,怎么样,
效果还差强人意吧?建议:最好选用粗体字,这样效果明显一些。

回复列表 (共3个回复)

沙发

八、将标题文本打印到按纽控件的指定位置

  一般按纽控件的标题文本都是打印在按纽中央,这已经能满足一般情况下的使用要求了。但有时我
们希望将文本打印到指定的位置,以满足特殊的需求。没问题!Instantly Go!
  首先还是要在 Option Explicit 节中声明两个变量:

Dim vCaptionPosX As Integer     '文本的X坐标
Dim vCaptionPosY As Integer     '文本的Y坐标

  再添加两对位置属性:

Public Property Get CaptionPosX() As Integer
CaptionPosX = vCaptionPosX
End Property

Public Property Let CaptionPosX(ByVal vNewValue As Integer)
vCaptionPosX = vNewValue
PropertyChanged "CaptionPosX"
PaintColor
End Property

Public Property Get CaptionPosY() As Integer
CaptionPosY = vCaptionPosY
End Property

Public Property Let CaptionPosY(ByVal vNewValue As Integer)
vCaptionPosY = vNewValue
PropertyChanged "CaptionPosY"
PaintColor
End Property

  在 ReadProperties 过程中添加代码:

vCaptionPosX = PropBag.ReadProperty("CaptionPosX", (UserControl.ScaleWidth - UserControl.TextWidth(vCaption)) / 2)
vCaptionPosY = PropBag.ReadProperty("CaptionPosy", (UserControl.ScaleHeight - UserControl.TextHeight(vCaption)) / 2)

  在 WriteProperties 过程中添加代码:

PropBag.WriteProperty "CaptionPosX", vCaptionPosX, (UserControl.ScaleWidth - UserControl.TextWidth(vCaption)) / 2
PropBag.WriteProperty "CaptionPosY", vCaptionPosY, (UserControl.ScaleHeight - UserControl.TextHeight(vCaption)) / 2

  在 UserControl_Resize 过程中 DrawButton 语句的前面添加代码:

vCaptionPosX = (UserControl.ScaleWidth - UserControl.TextWidth(vCaption)) / 2
vCaptionPosY = (UserControl.ScaleHeight - UserControl.TextHeight(vCaption)) / 2

  这两个语句为什么不添加在 InitProperties 过程中呢?因为从工具箱中把 PrettyCmd刚画到窗体
上时,最先执行InitProperties 过程,这时,UserControl.ScaleWidth 和 UserControl.ScaleHeight
的值都还不是我们画出的按纽控件的大小值,而是控件设计阶段 UserControl 的原始大小值,这样,
vCaptionPosX 和 vCaptionPosY 就会得出错误的计算值,造成默认的标题文本不是打印在按纽的中央
(而我们却是希望打印在按纽中央的)。当停止画图动作时,系统再执行 UserControl_Resize 过程,
这时,UserControl.ScaleWidth 和 UserControl.ScaleHeight 的值已经是我们画出的按纽控件的大小
值了,vCaptionPosX 和 vCaptionPosY 就会得出正确的计算值,紧接着执行的 DrawButton过程就可以
将标题文本打印在按纽的中央了。
  接下来再对 PrintCaption 过程加以修改(“你看你看,刚刚才修改完,又要修改,干嘛不一次改
好啊,改来改去的,烦不烦啊?”“呵呵,别烦哦,循序渐进嘛”),修改后的代码应该是这样的:

Private Sub PrintCaption()
If vCaptionStunt > 0 Then
  Dim X2 As Integer, Y2 As Integer, z As Integer
  z = UserControl.FontSize '获取字号
  Select Case vCaptionStunt
    Case 1 '立体
      UserControl.ForeColor = &H80000011
      X2 = vCaptionPosX - 1 + (z > 28) + (z > 48): Y2 = vCaptionPosY - 1 + (z > 28) + (z > 48)
    Case 2 '浮雕
      UserControl.ForeColor = &HFFC0C0
      X2 = vCaptionPosX + 1 - (z > 28) - (z > 48): Y2 = vCaptionPosY - 1 + (z > 28) + (z > 48)
    Case 3 '雕刻
      UserControl.ForeColor = vbWhite
      X2 = vCaptionPosX + 1 - (z > 28) + (z > 48): Y2 = vCaptionPosY + 1 - (z > 28) - (z > 48)
  End Select
  UserControl.CurrentX = X2: UserControl.CurrentY = Y2
  UserControl.Print vCaption
End If

UserControl.ForeColor = IIf(UserControl.Enabled, vForeColor, &H80000011)
UserControl.CurrentX = vCaptionPosX: UserControl.CurrentY = vCaptionPosY
UserControl.Print vCaption

UserControl.ForeColor = vForeColor
End Sub

  最后添加属性描述:

CaptionPosX:返回/设置标题文本在按纽控件上显示时的 X 坐标(以像素为单位)。
CaptionPosY:返回/设置标题文本在按纽控件上显示时的 Y 坐标(以像素为单位)。

  现在,你再进入程序设计的窗体页面,从工具箱中选中 PrettyCmd画到窗体上,将我们自己定义的
属性都随心所欲地设置一番,呵呵,真爽!
  今天的实验就到这里吧,就到这里吧。明天接着做。记得保存成果哟。

板凳


谢谢!!
好好学习一下!!

3 楼

up
[img]http://upload.programfan.com/upfile/200711201208888.rar[/img]

我来回复

您尚未登录,请登录后再回复。点此登录或注册