分享
 
 
 

VB打造超酷个性化菜单(六)

王朝vb·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

VB打造超酷个性化菜单(六)

(接上篇)

' 拦截菜单消息 (frmMenu 窗口入口函数)

Function MenuWndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Select Case Msg

Case WM_COMMAND ' 单击菜单项

If MyItemInfo(wParam).itemType = MIT_CHECKBOX Then

If MyItemInfo(wParam).itemState = MIS_CHECKED Then

MyItemInfo(wParam).itemState = MIS_UNCHECKED

Else

MyItemInfo(wParam).itemState = MIS_CHECKED

End If

End If

MenuItemSelected wParam

Case WM_EXITMENULOOP ' 退出菜单消息循环(保留)

Case WM_MEASUREITEM ' 处理菜单项高度和宽度

MeasureItem hwnd, lParam

Case WM_MENUSELECT ' 选择菜单项

Dim itemID As Long

itemID = GetMenuItemID(lParam, wParam And &HFF)

If itemID <> -1 Then

MenuItemSelecting itemID

End If

Case WM_DRAWITEM ' 绘制菜单项

DrawItem lParam

End Select

MenuWndProc = CallWindowProc(preMenuWndProc, hwnd, Msg, wParam, lParam)

End Function

' 处理菜单高度和宽度

Private Sub MeasureItem(ByVal hwnd As Long, ByVal lParam As Long)

Dim TextSize As Size, hdc As Long

hdc = GetDC(hwnd)

CopyMemory MeasureInfo, ByVal lParam, Len(MeasureInfo)

If MeasureInfo.CtlType And ODT_MENU Then

MeasureInfo.itemWidth = lstrlen(MyItemInfo(MeasureInfo.itemID).itemText) * (GetSystemMetrics(SM_CYMENU) / 2.5) + BarWidth

If MyItemInfo(MeasureInfo.itemID).itemType <> MIT_SEPARATOR Then

MeasureInfo.itemHeight = GetSystemMetrics(SM_CYMENU)

Else

MeasureInfo.itemHeight = 6

End If

End If

CopyMemory ByVal lParam, MeasureInfo, Len(MeasureInfo)

ReleaseDC hwnd, hdc

End Sub

' 绘制菜单项

Private Sub DrawItem(ByVal lParam As Long)

Dim hPen As Long, hBrush As Long

Dim itemRect As RECT, barRect As RECT, iconRect As RECT, textRect As RECT

Dim i As Long

CopyMemory DrawInfo, ByVal lParam, Len(DrawInfo)

If DrawInfo.CtlType = ODT_MENU Then

SetBkMode DrawInfo.hdc, TRANSPARENT

' 初始化菜单项矩形, 图标矩形, 文字矩形

itemRect = DrawInfo.rcItem

iconRect = DrawInfo.rcItem

textRect = DrawInfo.rcItem

' 设置菜单附加条矩形

With barRect

.Left = 0

.Top = 0

.Right = BarWidth - 1

For i = 0 To GetMenuItemCount(hMenu) - 1

If MyItemInfo(i).itemType = MIT_SEPARATOR Then

.Bottom = .Bottom + 6

Else

.Bottom = .Bottom + MeasureInfo.itemHeight

End If

Next i

.Bottom = .Bottom - 1

End With

' 设置图标矩形, 文字矩形

If BarStyle <> LBS_NONE Then iconRect.Left = barRect.Right + 2

iconRect.Right = iconRect.Left + 20

textRect.Left = iconRect.Right + 3

With DrawInfo

' 画菜单背景

itemRect.Left = barRect.Right

hBrush = CreateSolidBrush(BkColor)

FillRect .hdc, itemRect, hBrush

DeleteObject hBrush

' 画菜单左边的附加条

Dim RedArea As Long, GreenArea As Long, BlueArea As Long

Dim red As Long, green As Long, blue As Long

Select Case BarStyle

Case LBS_NONE ' 无附加条

Case LBS_SOLIDCOLOR ' 实色填充

hBrush = CreateSolidBrush(BarStartColor)

FillRect .hdc, barRect, hBrush

DeleteObject hBrush

Case LBS_HORIZONTALCOLOR ' 水平过渡色

BlueArea = Int(BarEndColor / &H10000) - Int(BarStartColor / &H10000)

GreenArea = (Int(BarEndColor / &H100) And &HFF) - (Int(BarStartColor / &H100) And &HFF)

RedArea = (BarEndColor And &HFF) - (BarStartColor And &HFF)

For i = 0 To BarWidth - 1

red = Int(BarStartColor And &HFF) + Int(i / BarWidth * RedArea)

green = (Int(BarStartColor / &H100) And &HFF) + Int(i / BarWidth * GreenArea)

blue = Int(BarStartColor / &H10000) + Int(i / BarWidth * BlueArea)

hPen = CreatePen(PS_SOLID, 1, RGB(red, green, blue))

Call SelectObject(.hdc, hPen)

Call MoveToEx(.hdc, i, 0, 0)

Call LineTo(.hdc, i, barRect.Bottom)

Call DeleteObject(hPen)

Next i

Case LBS_VERTICALCOLOR ' 垂直过渡色

BlueArea = Int(BarEndColor / &H10000) - Int(BarStartColor / &H10000)

GreenArea = (Int(BarEndColor / &H100) And &HFF) - (Int(BarStartColor / &H100) And &HFF)

RedArea = (BarEndColor And &HFF) - (BarStartColor And &HFF)

For i = 0 To barRect.Bottom

red = Int(BarStartColor And &HFF) + Int(i / (barRect.Bottom + 1) * RedArea)

green = (Int(BarStartColor / &H100) And &HFF) + Int(i / (barRect.Bottom + 1) * GreenArea)

blue = Int(BarStartColor / &H10000) + Int(i / (barRect.Bottom + 1) * BlueArea)

hPen = CreatePen(PS_SOLID, 1, RGB(red, green, blue))

Call SelectObject(.hdc, hPen)

Call MoveToEx(.hdc, 0, i, 0)

Call LineTo(.hdc, barRect.Right, i)

Call DeleteObject(hPen)

Next i

Case LBS_IMAGE ' 图像

If BarImage.Handle <> 0 Then

Dim barhDC As Long

barhDC = CreateCompatibleDC(GetDC(0))

SelectObject barhDC, BarImage.Handle

BitBlt .hdc, 0, 0, BarWidth, barRect.Bottom - barRect.Top + 1, barhDC, 0, 0, vbSrcCopy

DeleteDC barhDC

End If

End Select

' 画菜单项

If MyItemInfo(.itemID).itemType = MIT_SEPARATOR Then

' 画菜单分隔条(MIT_SEPARATOR)

If MyItemInfo(.itemID).itemType = MIT_SEPARATOR Then

itemRect.Top = itemRect.Top + 2

itemRect.Bottom = itemRect.Top + 1

itemRect.Left = barRect.Right + 5

Select Case SepStyle

Case MSS_NONE ' 无分隔条

Case MSS_DEFAULT ' 默认样式

DrawEdge .hdc, itemRect, EDGE_ETCHED, BF_TOP

Case Else ' 其它

hPen = CreatePen(SepStyle, 0, SepColor)

hBrush = CreateSolidBrush(BkColor)

SelectObject .hdc, hPen

SelectObject .hdc, hBrush

Rectangle .hdc, itemRect.Left, itemRect.Top, itemRect.Right, itemRect.Bottom

DeleteObject hPen

DeleteObject hBrush

End Select

End If

Else

If Not CBool(MyItemInfo(.itemID).itemState And MIS_DISABLED) Then ' 当菜单项可用时

If .itemState And ODS_SELECTED Then ' 当鼠标移动到菜单项时

' 设置菜单项高亮范围

If SelectScope And ISS_ICON_TEXT Then

itemRect.Left = iconRect.Left

ElseIf SelectScope And ISS_TEXT Then

itemRect.Left = textRect.Left - 2

Else

itemRect.Left = .rcItem.Left

End If

' 处理菜单项无图标或为CHECKBOX时的情况

If (MyItemInfo(.itemID).itemType = MIT_CHECKBOX Or MyItemInfo(.itemID).itemIcon = 0) And SelectScope <> ISS_LEFTBAR_ICON_TEXT Then

itemRect.Left = iconRect.Left

End If

' 画菜单项边框

Select Case EdgeStyle

Case ISES_NONE ' 无边框

Case ISES_SUNKEN ' 凹进

DrawEdge .hdc, itemRect, BDR_SUNKENOUTER, BF_RECT

Case ISES_RAISED ' 凸起

DrawEdge .hdc, itemRect, BDR_RAISEDINNER, BF_RECT

Case Else ' 其它

hPen = CreatePen(EdgeStyle, 0, EdgeColor)

hBrush = CreateSolidBrush(BkColor)

SelectObject .hdc, hPen

SelectObject .hdc, hBrush

Rectangle .hdc, itemRect.Left, itemRect.Top, itemRect.Right, itemRect.Bottom

DeleteObject hPen

DeleteObject hBrush

End Select

' 画菜单项背景

InflateRect itemRect, -1, -1

Select Case FillStyle

Case ISFS_NONE ' 无背景

Case ISFS_HORIZONTALCOLOR ' 水平渐变色

BlueArea = Int(FillEndColor / &H10000) - Int(FillStartColor / &H10000)

GreenArea = (Int(FillEndColor / &H100) And &HFF) - (Int(FillStartColor / &H100) And &HFF)

RedArea = (FillEndColor And &HFF) - (FillStartColor And &HFF)

For i = itemRect.Left To itemRect.Right - 1

red = Int(FillStartColor And &HFF) + Int((i - itemRect.Left) / (itemRect.Right - itemRect.Left + 1) * RedArea)

green = (Int(FillStartColor / &H100) And &HFF) + Int((i - itemRect.Left) / (itemRect.Right - itemRect.Left + 1) * GreenArea)

blue = Int(FillStartColor / &H10000) + Int((i - itemRect.Left) / (itemRect.Right - itemRect.Left + 1) * BlueArea)

hPen = CreatePen(PS_SOLID, 1, RGB(red, green, blue))

Call SelectObject(.hdc, hPen)

Call MoveToEx(.hdc, i, itemRect.Top, 0)

Call LineTo(.hdc, i, itemRect.Bottom)

Call DeleteObject(hPen)

Next i

Case ISFS_VERTICALCOLOR ' 垂直渐变色

BlueArea = Int(FillEndColor / &H10000) - Int(FillStartColor / &H10000)

GreenArea = (Int(FillEndColor / &H100) And &HFF) - (Int(FillStartColor / &H100) And &HFF)

RedArea = (FillEndColor And &HFF) - (FillStartColor And &HFF)

For i = itemRect.Top To itemRect.Bottom - 1

red = Int(FillStartColor And &HFF) + Int((i - itemRect.Top) / (itemRect.Bottom - itemRect.Top + 1) * RedArea)

green = (Int(FillStartColor / &H100) And &HFF) + Int((i - itemRect.Top) / (itemRect.Bottom - itemRect.Top + 1) * GreenArea)

blue = Int(FillStartColor / &H10000) + Int((i - itemRect.Top) / (itemRect.Bottom - itemRect.Top + 1) * BlueArea)

hPen = CreatePen(PS_SOLID, 1, RGB(red, green, blue))

Call SelectObject(.hdc, hPen)

Call MoveToEx(.hdc, itemRect.Left, i, 0)

Call LineTo(.hdc, itemRect.Right, i)

Call DeleteObject(hPen)

Next i

Case ISFS_SOLIDCOLOR ' 实色填充

hPen = CreatePen(PS_SOLID, 0, FillStartColor)

hBrush = CreateSolidBrush(FillStartColor)

SelectObject .hdc, hPen

SelectObject .hdc, hBrush

Rectangle .hdc, itemRect.Left, itemRect.Top, itemRect.Right, itemRect.Bottom

DeleteObject hPen

DeleteObject hBrush

End Select

' 画菜单项文字

SetTextColor .hdc, TextSelectColor

DrawText .hdc, MyItemInfo(.itemID).itemText, -1, textRect, DT_SINGLELINE Or DT_LEFT Or DT_VCENTER

' 画菜单项图标

If MyItemInfo(.itemID).itemType <> MIT_CHECKBOX Then

DrawIconEx .hdc, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, MyItemInfo(.itemID).itemIcon, 16, 16, 0, 0, DI_NORMAL

Select Case IconStyle

Case IIS_NONE ' 无效果

Case IIS_SUNKEN ' 凹进

If MyItemInfo(.itemID).itemIcon <> 0 Then

DrawEdge .hdc, iconRect, BDR_SUNKENOUTER, BF_RECT

End If

Case IIS_RAISED ' 凸起

If MyItemInfo(.itemID).itemIcon <> 0 Then

DrawEdge .hdc, iconRect, BDR_RAISEDINNER, BF_RECT

End If

Case IIS_SHADOW ' 阴影

hBrush = CreateSolidBrush(RGB(128, 128, 128))

DrawState .hdc, hBrush, 0, MyItemInfo(.itemID).itemIcon, 0, iconRect.Left + 3, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2 + 1, 0, 0, DST_ICON Or DSS_MONO

DeleteObject hBrush

DrawIconEx .hdc, iconRect.Left + 1, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2 - 1, MyItemInfo(.itemID).itemIcon, 16, 16, 0, 0, DI_NORMAL

End Select

Else

' CHECKBOX型菜单项图标效果

If MyItemInfo(.itemID).itemState And MIS_CHECKED Then

DrawIconEx .hdc, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, MyItemInfo(.itemID).itemIcon, 16, 16, 0, 0, DI_NORMAL

End If

End If

Else ' 当鼠标移开菜单项时

' 画菜单项边框和背景(清除)

If BarStyle <> LBS_NONE Then

itemRect.Left = barRect.Right + 1

Else

itemRect.Left = 0

End If

hBrush = CreateSolidBrush(BkColor)

FillRect .hdc, itemRect, hBrush

DeleteObject hBrush

' 画菜单项文字

SetTextColor .hdc, TextEnabledColor

DrawText .hdc, MyItemInfo(.itemID).itemText, -1, textRect, DT_SINGLELINE Or DT_LEFT Or DT_VCENTER

' 画菜单项图标

If MyItemInfo(.itemID).itemType <> MIT_CHECKBOX Then

DrawIconEx .hdc, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, MyItemInfo(.itemID).itemIcon, 16, 16, 0, 0, DI_NORMAL

Else

If MyItemInfo(.itemID).itemState And MIS_CHECKED Then

DrawIconEx .hdc, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, MyItemInfo(.itemID).itemIcon, 16, 16, 0, 0, DI_NORMAL

End If

End If

End If

Else ' 当菜单项不可用时

' 画菜单项文字

SetTextColor .hdc, TextDisabledColor

DrawText .hdc, MyItemInfo(.itemID).itemText, -1, textRect, DT_SINGLELINE Or DT_LEFT Or DT_VCENTER

' 画菜单项图标

If MyItemInfo(.itemID).itemType <> MIT_CHECKBOX Then

DrawState .hdc, 0, 0, MyItemInfo(.itemID).itemIcon, 0, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, 0, 0, DST_ICON Or DSS_DISABLED

Else

If MyItemInfo(.itemID).itemState And MIS_CHECKED Then

DrawState .hdc, 0, 0, MyItemInfo(.itemID).itemIcon, 0, iconRect.Left + 2, iconRect.Top + (iconRect.Bottom - iconRect.Top + 1 - 16) / 2, 0, 0, DST_ICON Or DSS_DISABLED

End If

End If

End If

End If

End With

End If

End Sub

' 菜单项事件响应(单击菜单项)

Private Sub MenuItemSelected(ByVal itemID As Long)

Debug.Print "鼠标单击了:" & MyItemInfo(itemID).itemText

Select Case MyItemInfo(itemID).itemAlias

Case "exit"

Dim frm As Form

For Each frm In Forms

Unload frm

Next

End Select

End Sub

' 菜单项事件响应(选择菜单项)

Private Sub MenuItemSelecting(ByVal itemID As Long)

Debug.Print "鼠标移动到:" & MyItemInfo(itemID).itemText

End Sub

到此为止,我们就完成了菜单类的编写,且还包括一个测试窗体。现在,完整的工程里应该包括两个窗体:frmMain和frmMenu;一个标准模块:mMenu;一个类模块:cMenu。按F5编译运行一下,在窗体空白处单击鼠标右键。怎么样,出现弹出式菜单了吗?换个风格再试试。

看完这个系列的文章后,我想你应该已经对采用物主绘图技术的自绘菜单有了一定的了解,再看看MS Office 2003的菜单,其实也没什么难的嘛。

该程序在Windows XP、VB6下调试通过。

源代码下载地址:http://y365.com/ses518/soft/samplecsdn.zip

(全文完)

****************************************************************

* 转载请通知作者并注明出处,谢谢。

* 作者:goodname008(卢培培)

* 邮箱:goodname008@163.com

****************************************************************

相关链接:

VB打造超酷个性化菜单(一)VB打造超酷个性化菜单(二)VB打造超酷个性化菜单(三)VB打造超酷个性化菜单(四)VB打造超酷个性化菜单(五)VB打造超酷个性化菜单(六)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有