首页 > 开发 > 综合 > 正文

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

2024-07-21 02:20:58
字体:
来源:转载
供稿:网友
  • 网站运营seo文章大全
  • 提供全面的站长运营经验及seo技术!
  • vb打造超酷个性化菜单(三)



    现在到了最关键,最精彩,也是最复杂的部分了。我们最关心的就是怎样“画”菜单,怎样处理菜单事件,在menuwndproc这个处理消息的函数里,我们要处理如下消息:wm_command(单击菜单项),wm_measureitem(处理菜单高度和宽度),wm_menuselect(选择菜单项),wm_drawitem(绘制菜单项)。

    打开上次建好的工程,添加一个标准模块,并将其名称设置为mmenu,代码如下:

    '**************************************************************************************************************

    '* 本模块配合 cmenu 菜单类模块

    '*

    '* 版权: lpp软件工作室

    '* 作者: 卢培培(goodname008)

    '* (******* 复制请保留以上信息 *******)

    '**************************************************************************************************************



    option explicit



    ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- api 函数声明 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



    public declare function bitblt lib "gdi32" (byval hdestdc as long, byval x as long, byval y as long, byval nwidth as long, byval nheight as long, byval hsrcdc as long, byval xsrc as long, byval ysrc as long, byval dwrop as long) as long

    public declare function callwindowproc lib "user32" alias "callwindowproca" (byval lpprevwndfunc as long, byval hwnd as long, byval msg as long, byval wparam as long, byval lparam as long) as long

    public declare function createcompatibledc lib "gdi32" (byval hdc as long) as long

    public declare function createpen lib "gdi32" (byval npenstyle as long, byval nwidth as long, byval crcolor as long) as long

    public declare function createpopupmenu lib "user32" () as long

    public declare function createsolidbrush lib "gdi32" (byval crcolor as long) as long

    public declare function deletedc lib "gdi32" (byval hdc as long) as long

    public declare function deletemenu lib "user32" (byval hmenu as long, byval nposition as long, byval wflags as long) as long

    public declare function deleteobject lib "gdi32" (byval hobject as long) as long

    public declare function destroymenu lib "user32" (byval hmenu as long) as long

    public declare function drawedge lib "user32" (byval hdc as long, qrc as rect, byval edge as long, byval grfflags as long) as long

    public declare function drawiconex lib "user32" (byval hdc as long, byval xleft as long, byval ytop as long, byval hicon as long, byval cxwidth as long, byval cywidth as long, byval istepifanicur as long, byval hbrflickerfreedraw as long, byval diflags as long) as long

    public declare function drawstate lib "user32" alias "drawstatea" (byval hdc as long, byval hbrush as long, byval lpdrawstateproc as long, byval lparam as long, byval wparam as long, byval n1 as long, byval n2 as long, byval n3 as long, byval n4 as long, byval un as long) as long

    public declare function drawtext lib "user32" alias "drawtexta" (byval hdc as long, byval lpstr as string, byval ncount as long, lprect as rect, byval wformat as long) as long

    public declare function fillrect lib "user32" (byval hdc as long, lprect as rect, byval hbrush as long) as long

    public declare function getdc lib "user32" (byval hwnd as long) as long

    public declare function getmenuitemcount lib "user32" (byval hmenu as long) as long

    public declare function getmenuitemid lib "user32" (byval hmenu as long, byval npos as long) as long

    public declare function getmenuiteminfo lib "user32" alias "getmenuiteminfoa" (byval hmenu as long, byval un as long, byval b as long, lpmenuiteminfo as menuiteminfo) as long

    public declare function getsyscolor lib "user32" (byval nindex as long) as long

    public declare function getsystemmetrics lib "user32" (byval nindex as long) as long

    public declare function inflaterect lib "user32" (lprect as rect, byval x as long, byval y as long) as long

    public declare function insertmenuitem lib "user32" alias "insertmenuitema" (byval hmenu as long, byval un as long, byval bool as boolean, byref lpcmenuiteminfo as menuiteminfo) as long

    public declare function lineto lib "gdi32" (byval hdc as long, byval x as long, byval y as long) as long

    public declare function lstrlen lib "kernel32" alias "lstrlena" (byval lpstring as string) as long

    public declare function movetoex lib "gdi32" (byval hdc as long, byval x as long, byval y as long, lppoint as long) as long

    public declare function rectangle lib "gdi32" (byval hdc as long, byval x1 as long, byval y1 as long, byval x2 as long, byval y2 as long) as long

    public declare function releasedc lib "user32" (byval hwnd as long, byval hdc as long) as long

    public declare function selectobject lib "gdi32" (byval hdc as long, byval hobject as long) as long

    public declare function sendmessage lib "user32" alias "sendmessagea" (byval hwnd as long, byval wmsg as long, byval wparam as long, lparam as any) as long

    public declare function setbkmode lib "gdi32" (byval hdc as long, byval nbkmode as long) as long

    public declare function setmenuiteminfo lib "user32" alias "setmenuiteminfoa" (byval hmenu as long, byval un as long, byval bool as boolean, lpcmenuiteminfo as menuiteminfo) as long

    public declare function settextcolor lib "gdi32" (byval hdc as long, byval crcolor as long) as long

    public declare function setwindowlong lib "user32" alias "setwindowlonga" (byval hwnd as long, byval nindex as long, byval dwnewlong as long) as long



    public declare sub copymemory lib "kernel32" alias "rtlmovememory" (destination as any, source as any, byval length as long)





    ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- api 常量声明 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



    public const gwl_wndproc = (-4) ' setwindowlong 设置窗口函数入口地址

    public const sm_cymenu = 15 ' getsystemmetrics 获得系统菜单项高度



    public const wm_command = &h111 ' 消息: 单击菜单项

    public const wm_drawitem = &h2b ' 消息: 绘制菜单项

    public const wm_exitmenuloop = &h212 ' 消息: 退出菜单消息循环

    public const wm_measureitem = &h2c ' 消息: 处理菜单高度和宽度

    public const wm_menuselect = &h11f ' 消息: 选择菜单项



    ' odt

    public const odt_menu = 1 ' 菜单

    public const odt_listbox = 2 ' 列表框

    public const odt_combobox = 3 ' 组合框

    public const odt_button = 4 ' 按钮



    ' ods

    public const ods_selected = &h1 ' 菜单被选择

    public const ods_grayed = &h2 ' 灰色字

    public const ods_disabled = &h4 ' 禁用

    public const ods_checked = &h8 ' 选中

    public const ods_focus = &h10 ' 聚焦



    ' diflags to drawiconex

    public const di_mask = &h1 ' 绘图时使用图标的mask部分 (如单独使用, 可获得图标的掩模)

    public const di_image = &h2 ' 绘图时使用图标的xor部分 (即图标没有透明区域)

    public const di_normal = di_mask or di_image ' 用常规方式绘图 (合并 di_image 和 di_mask)



    ' nbkmode to setbkmode

    public const transparent = 1 ' 透明处理, 即不作上述填充

    public const opaque = 2 ' 用当前的背景色填充虚线画笔、阴影刷子以及字符的空隙

    public const newtransparent = 3 ' 在有颜色的菜单上画透明文字





    ' mf 菜单相关常数

    public const mf_bycommand = &h0& ' 菜单条目由菜单的命令id指定

    public const mf_byposition = &h400& ' 菜单条目由条目在菜单中的位置决定 (零代表菜单中的第一个条目)



    public const mf_checked = &h8& ' 检查指定的菜单条目 (不能与vb的checked属性兼容)

    public const mf_disabled = &h2& ' 禁止指定的菜单条目 (不与vb的enabled属性兼容)

    public const mf_enabled = &h0& ' 允许指定的菜单条目 (不与vb的enabled属性兼容)

    public const mf_grayed = &h1& ' 禁止指定的菜单条目, 并用浅灰色描述它. (不与vb的enabled属性兼容)

    public const mf_hilite = &h80&

    public const mf_separator = &h800& ' 在指定的条目处显示一条分隔线

    public const mf_string = &h0& ' 在指定的条目处放置一个字串 (不与vb的caption属性兼容)

    public const mf_unchecked = &h0& ' 检查指定的条目 (不能与vb的checked属性兼容)

    public const mf_unhilite = &h0&



    public const mf_bitmap = &h4& ' 菜单条目是一幅位图. 一旦设入菜单, 这幅位图就绝对不能删除, 所以不应该使用由vb的image属性返回的值.

    public const mf_ownerdraw = &h100& ' 创建一个物主绘图菜单 (由您设计的程序负责描绘每个菜单条目)

    public const mf_usecheckbitmaps = &h200&



    public const mf_menubarbreak = &h20& ' 在弹出式菜单中, 将指定的条目放置于一个新列, 并用一条垂直线分隔不同的列.

    public const mf_menubreak = &h40& ' 在弹出式菜单中, 将指定的条目放置于一个新列. 在顶级菜单中, 将条目放置到一个新行.



    public const mf_popup = &h10& ' 将一个弹出式菜单置于指定的条目, 可用于创建子菜单及弹出式菜单.

    public const mf_help = &h4000&



    public const mf_default = &h1000

    public const mf_rightjustify = &h4000



    ' fmask to insertmenuitem ' 指定 menuiteminfo 中哪些成员有效

    public const miim_state = &h1

    public const miim_id = &h2

    public const miim_submenu = &h4

    public const miim_checkmarks = &h8

    public const miim_type = &h10

    public const miim_data = &h20

    public const miim_string = &h40

    public const miim_bitmap = &h80

    public const miim_ftype = &h100



    ' ftype to insertmenuitem ' menuiteminfo 中菜单项类型

    public const mft_bitmap = &h4&

    public const mft_menubarbreak = &h20&

    public const mft_menubreak = &h40&

    public const mft_ownerdraw = &h100&

    public const mft_separator = &h800&

    public const mft_string = &h0&



    ' fstate to insertmenuitem ' menuiteminfo 中菜单项状态

    public const mfs_checked = &h8&

    public const mfs_disabled = &h2&

    public const mfs_enabled = &h0&

    public const mfs_grayed = &h1&

    public const mfs_hilite = &h80&

    public const mfs_unchecked = &h0&

    public const mfs_unhilite = &h0&



    ' nformat to drawtext

    public const dt_left = &h0 ' 水平左对齐

    public const dt_center = &h1 ' 水平居中对齐

    public const dt_right = &h2 ' 水平右对齐



    public const dt_singleline = &h20 ' 单行



    public const dt_top = &h0 ' 垂直上对齐 (仅单行时有效)

    public const dt_vcenter = &h4 ' 垂直居中对齐 (仅单行时有效)

    public const dt_bottom = &h8 ' 垂直下对齐 (仅单行时有效)



    public const dt_calcrect = &h400 ' 多行绘图时矩形的底边根据需要进行延展, 以便容下所有文字; 单行绘图时, 延展矩形的右侧, 不描绘文字, 由lprect参数指定的矩形会载入计算出来的值.

    public const dt_wordbreak = &h10 ' 进行自动换行. 如用settextalign函数设置了ta_updatecp标志, 这里的设置则无效.



    public const dt_noclip = &h100 ' 描绘文字时不剪切到指定的矩形

    public const dt_noprefix = &h800 ' 通常, 函数认为 & 字符表示应为下一个字符加上下划线, 该标志禁止这种行为.



    public const dt_expandtabs = &h40 ' 描绘文字的时候, 对制表站进行扩展. 默认的制表站间距是8个字符. 但是, 可用dt_tabstop标志改变这项设定.

    public const dt_tabstop = &h80 ' 指定新的制表站间距, 采用这个整数的高 8 位.

    public const dt_externalleading = &h200 ' 计算文本行高度的时候, 使用当前字体的外部间距属性.



    ' nindex to getsyscolor 标准: 0--20

    public const color_activeborder = 10 ' 活动窗口的边框

    public const color_activecaption = 2 ' 活动窗口的标题

    public const color_appworkspace = 12 ' mdi桌面的背景

    public const color_background = 1 ' windows 桌面

    public const color_btnface = 15 ' 按钮

    public const color_btnhighlight = 20 ' 按钮的3d加亮区

    public const color_btnshadow = 16 ' 按钮的3d阴影

    public const color_btntext = 18 ' 按钮文字

    public const color_captiontext = 9 ' 窗口标题中的文字

    public const color_graytext = 17 ' 灰色文字; 如使用了抖动技术则为零

    public const color_highlight = 13 ' 选定的项目背景

    public const color_highlighttext = 14 ' 选定的项目文字

    public const color_inactiveborder = 11 ' 不活动窗口的边框

    public const color_inactivecaption = 3 ' 不活动窗口的标题

    public const color_inactivecaptiontext = 19 ' 不活动窗口的文字

    public const color_menu = 4 ' 菜单

    public const color_menutext = 7 ' 菜单文字

    public const color_scrollbar = 0 ' 滚动条

    public const color_window = 5 ' 窗口背景

    public const color_windowframe = 6 ' 窗框

    public const color_windowtext = 8 ' 窗口文字



    ' un to drawstate

    public const dst_complex = &h0 ' 绘图在由lpdrawstateproc参数指定的回调函数期间执行, lparam和wparam会传递给回调事件.

    public const dst_text = &h1 ' lparam代表文字的地址(可使用一个字串别名),wparam代表字串的长度.

    public const dst_prefixtext = &h2 ' 与dst_text类似, 只是 & 字符指出为下各字符加上下划线.

    public const dst_icon = &h3 ' lparam包括图标的句柄

    public const dst_bitmap = &h4 ' lparam包括位图的句柄

    public const dss_normal = &h0 ' 普通图像

    public const dss_union = &h10 ' 图像进行抖动处理

    public const dss_disabled = &h20 ' 图象具有浮雕效果

    public const dss_mono = &h80 ' 用hbrush描绘图像

    public const dss_right = &h8000 ' 无任何作用



    ' edge to drawedge

    public const bdr_raisedouter = &h1 ' 外层凸

    public const bdr_sunkenouter = &h2 ' 外层凹

    public const bdr_raisedinner = &h4 ' 内层凸

    public const bdr_sunkeninner = &h8 ' 内层凹

    public const bdr_outer = &h3

    public const bdr_raised = &h5

    public const bdr_sunken = &ha

    public const bdr_inner = &hc

    public const edge_bump = (bdr_raisedouter or bdr_sunkeninner)

    public const edge_etched = (bdr_sunkenouter or bdr_raisedinner)

    public const edge_raised = (bdr_raisedouter or bdr_raisedinner)

    public const edge_sunken = (bdr_sunkenouter or bdr_sunkeninner)



    ' grfflags to drawedge

    public const bf_left = &h1 ' 左边缘

    public const bf_top = &h2 ' 上边缘

    public const bf_right = &h4 ' 右边缘

    public const bf_bottom = &h8 ' 下边缘

    public const bf_diagonal = &h10 ' 对角线

    public const bf_middle = &h800 ' 填充矩形内部

    public const bf_soft = &h1000 ' msdn: soft buttons instead of tiles.

    public const bf_adjust = &h2000 ' 调整矩形, 预留客户区

    public const bf_flat = &h4000 ' 平面边缘

    public const bf_mono = &h8000 ' 一维边缘



    public const bf_rect = (bf_left or bf_top or bf_right or bf_bottom)

    public const bf_topleft = (bf_top or bf_left)

    public const bf_topright = (bf_top or bf_right)

    public const bf_bottomleft = (bf_bottom or bf_left)

    public const bf_bottomright = (bf_bottom or bf_right)

    public const bf_diagonal_endtopleft = (bf_diagonal or bf_top or bf_left)

    public const bf_diagonal_endtopright = (bf_diagonal or bf_top or bf_right)

    public const bf_diagonal_endbottomleft = (bf_diagonal or bf_bottom or bf_left)

    public const bf_diagonal_endbottomright = (bf_diagonal or bf_bottom or bf_right)



    ' npenstyle to createpen

    public const ps_dash = 1 ' 画笔类型:虚线 (nwidth必须是1) -------

    public const ps_dashdot = 3 ' 画笔类型:点划线 (nwidth必须是1) _._._._

    public const ps_dashdotdot = 4 ' 画笔类型:点-点-划线 (nwidth必须是1) _.._.._

    public const ps_dot = 2 ' 画笔类型:点线 (nwidth必须是1) .......

    public const ps_solid = 0 ' 画笔类型:实线 _______





    ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- api 类型声明 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



    public type rect

    left as long

    top as long

    right as long

    bottom as long

    end type



    public type drawitemstruct

    ctltype as long

    ctlid as long

    itemid as long

    itemaction as long

    itemstate as long

    hwnditem as long

    hdc as long

    rcitem as rect

    itemdata as long

    end type



    public type menuiteminfo

    cbsize as long

    fmask as long

    ftype as long

    fstate as long

    wid as long

    hsubmenu as long

    hbmpchecked as long

    hbmpunchecked as long

    dwitemdata as long

    dwtypedata as string

    cch as long

    end type



    public type measureitemstruct

    ctltype as long

    ctlid as long

    itemid as long

    itemwidth as long

    itemheight as long

    itemdata as long

    end type



    public type size

    cx as long

    cy as long

    end type





    ' 自定义菜单项数据结构

    public type mymenuiteminfo

    itemicon as stdpicture

    itemalias as string

    itemtext as string

    itemtype as menuitemtype

    itemstate as menuitemstate

    end type



    ' 菜单相关结构

    private measureinfo as measureitemstruct

    private drawinfo as drawitemstruct



    public hmenu as long

    public premenuwndproc as long

    public myiteminfo() as mymenuiteminfo



    ' 菜单类属性

    public barwidth as long ' 菜单附加条宽度

    public barstyle as menuleftbarstyle ' 菜单附加条风格

    public barimage as stdpicture ' 菜单附加条图像

    public barstartcolor as long ' 菜单附加条过渡色起始颜色

    public barendcolor as long ' 菜单附加条过渡色终止颜色

    public selectscope as menuitemselectscope ' 菜单项高亮条的范围

    public textenabledcolor as long ' 菜单项可用时文字颜色

    public textdisabledcolor as long ' 菜单项不可用时文字颜色

    public textselectcolor as long ' 菜单项选中时文字颜色

    public iconstyle as menuitemiconstyle ' 菜单项图标风格

    public edgestyle as menuitemselectedgestyle ' 菜单项边框风格

    public edgecolor as long ' 菜单项边框颜色

    public fillstyle as menuitemselectfillstyle ' 菜单项背景填充风格

    public fillstartcolor as long ' 菜单项过渡色起始颜色

    public fillendcolor as long ' 菜单项过渡色终止颜色

    public bkcolor as long ' 菜单背景颜色

    public sepstyle as menuseparatorstyle ' 菜单分隔条风格

    public sepcolor as long ' 菜单分隔条颜色

    public menustyle as menuuserstyle ' 菜单总体风格



    ' 拦截菜单消息 (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



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

    在看完这个系列的文章后,我想你应该已经对采用物主绘图技术的自绘菜单有一定的了解了,回过头来再看看ms office 2003的菜单,其实也没什么难的嘛。以后,我们就可以在自己的任何程序中调用这个写好的菜单类,为自己的程序添光加彩了。 :)

    该程序在windows xp、vb6下调试通过。

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

    发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表