ToolBar的模样自己画(五)

类别:.NET开发 点击:0 评论:0 推荐:

'最后一部分,也是最核心的消息处理代码与主绘图过程

Friend Function MsgProc(lParam As Long, MouseDown As Boolean) As Long
    Dim tHDR As NMHDR
    Dim className As String * 32
    Dim retval As Long
    CopyMemory tHDR, ByVal lParam, Len(tHDR)
    If tHDR.hwndFrom <> 0 Then
        retval = GetClassName(tHDR.hwndFrom, className, 33)
        If retval > 0 Then
            If Left$(className, retval) = "msvb_lib_toolbar" Then
                MsgProc = OnCustomDraw(lParam, MouseDown)
            End If
        End If
    End If
End Function
Private Function OnCustomDraw(lParam As Long, MouseDown As Boolean) As Long
    Dim tTBCD As NMTBCUSTOMDRAW
    Dim hBrush As Long
    CopyMemory tTBCD, ByVal lParam, Len(tTBCD)
    With tTBCD.nmcd
        Select Case .dwDrawStage
            Case CDDS_ITEMPREPAINT
                OnCustomDraw = CDRF_SKIPDEFAULT
                DrawToolbarButton .hdr.hwndFrom, .hdc, .dwItemSpec, .uItemState, .rc, MouseDown
            Case CDDS_PREPAINT
                OnCustomDraw = CDRF_NOTIFYITEMDRAW
                GetClientRect .hdr.hwndFrom, .rc
                If mpicBk Is Nothing Then
                    hBrush = CreateSolidBrush(m_lngBackColor)
                Else
                    hBrush = CreatePatternBrush(mpicBk)
                End If
                FillRect .hdc, .rc, hBrush
                DeleteObject hBrush
        End Select
    End With
End Function
Private Sub DrawToolbarButton(ByVal hWnd As Long, ByVal hdc As Long, itemSpec As Long, ByVal itemState As Long, tR As RECT, MouseDown As Boolean)
    Dim i As Long
    Dim bPushed As Boolean, bDropDown As Boolean, bHover As Boolean
    Dim bDisabled As Boolean, bChecked As Boolean
    Dim bSkipped As Boolean, bBottomText As Boolean, bNoDsbIcon As Boolean
    Dim hIcon As Long, hImageList As Long
    Dim tTB As TBBUTTON
    Dim szText As Size, rcDrop As RECT, rcIcon As RECT
    Dim hOldPen As Long, hPen As Long
    Dim hFont As Long, hOldFont As Long
    Dim sCaption As String, bFirstSetBk As Boolean
    Dim lDropWidth As Long, lTxtColor As Long
    sCaption = String$(128, vbNullChar)
    i = SendMessage(hWnd, TB_GETBUTTONTEXTA, itemSpec, ByVal sCaption)
    If i > 0 Then
        sCaption = Left$(sCaption, i)
    Else
        sCaption = ""
    End If
    i = GetWindowLong(hWnd, GWL_STYLE)
    bBottomText = ((i And TBSTYLE_LIST) = 0)
    i = SendMessage(hWnd, TB_COMMANDTOINDEX, itemSpec, ByVal 0)
    SendMessage hWnd, TB_GETBUTTON, i, tTB
   
    bDisabled = (itemState And CDIS_DISABLED)
    bChecked = (itemState And CDIS_CHECKED)
    bHover = (itemState And CDIS_HOT)
    bPushed = (itemState And CDIS_SELECTED)
   
    If tTB.fsStyle And TBSTYLE_SEP Then '分隔线按钮
        hPen = CreatePen(PS_SOLID, 1, vb3DShadow)
        hOldPen = SelectObject(hdc, hPen)
        MoveToEx hdc, tR.Left + 2&, tR.Top + 1&, ByVal 0
        LineTo hdc, tR.Left + 2&, tR.Bottom - 1&
        SelectObject hdc, hOldPen
        DeleteObject hPen
        Exit Sub
    Else
        hImageList = SendMessage(hWnd, TB_GETIMAGELIST, 0, ByVal 0)
        If hImageList <> 0 Then '取得主图像列表
            If mlngImgList <> hImageList Then
                mlngImgList = hImageList
                bFirstSetBk = True
                mlngIconWidth = 0
            End If
            If bDisabled Then   '取得禁用图像列表
                i = SendMessage(hWnd, TB_GETDISABLEDIMAGELIST, 0, ByVal 0)
                If i <> 0 And i <> hImageList Then
                    hImageList = i
                    If mlngDsbImgList <> i Then
                        mlngDsbImgList = i
                        bFirstSetBk = True
                    End If
                Else
                    bNoDsbIcon = True
                End If
            ElseIf bHover Then  '取得热图像列表
                i = SendMessage(hWnd, TB_GETHOTIMAGELIST, 0, ByVal 0)
                If i <> 0 And i <> hImageList Then
                    hImageList = i
                    If mlngHotImgList <> i Then
                        mlngHotImgList = i
                        bFirstSetBk = True
                    End If
                End If
            End If
            If bFirstSetBk Then '首次使用需设定背景色
                If ImageList_GetBkColor(hImageList) <> -1 Then
                    ImageList_SetBkColor hImageList, CLR_NONE
                End If
            End If
            hIcon = ImageList_GetIcon(hImageList, tTB.iBitmap, ILD_NORMAL)
            If mlngIconWidth = 0 Then GetIconSize hIcon
        End If
        '根据状态创建不同刷子与画笔
        lTxtColor = m_lngTextColor
        If bChecked Or bPushed Then
            AlphaBlend hdc, tR.Left, tR.Top, tR.Right - tR.Left, tR.Bottom - tR.Top, mdcWhite.hdc, 0, 0, tR.Right - tR.Left, tR.Bottom - tR.Top, mlngBtnDownAlpha * &H10000
        ElseIf bHover Then
            AlphaBlend hdc, tR.Left, tR.Top, tR.Right - tR.Left, tR.Bottom - tR.Top, mdcWhite.hdc, 0, 0, tR.Right - tR.Left, tR.Bottom - tR.Top, mlngBtnHiAlpha * &H10000
            lTxtColor = m_lngTextHiColor
        Else
            bSkipped = True
        End If
        SetTextColor hdc, lTxtColor
        If tTB.fsStyle And TBSTYLE_DROPDOWN Then
            lDropWidth = 14
            bDropDown = bHover And MouseDown And Not bPushed
            SetRect rcDrop, tR.Right - lDropWidth, tR.Top, tR.Right, tR.Bottom
            tR.Right = tR.Right - lDropWidth
        End If
    End If
    SetBkMode hdc, 1    '文本背景透明
    If bSkipped = False Then    '根据样式不同,画不同边框并填充
        If bChecked Or bPushed Then
            DrawRect hdc, tR, 2
        Else
            DrawRect hdc, tR, 1
        End If
    Else
        DrawRect hdc, tR, 0
    End If
    If tTB.fsStyle And TBSTYLE_DROPDOWN Then    '处理下拉菜单的小按钮
        If bSkipped = False Or m_lngBrdStyle > 0 Then
            If bDropDown Then
                AlphaBlend hdc, rcDrop.Left, rcDrop.Top, lDropWidth, rcDrop.Bottom - rcDrop.Top, mdcWhite.hdc, 0, 0, rcDrop.Right - rcDrop.Left, rcDrop.Bottom - rcDrop.Top, mlngBtnDownAlpha * &H10000
            End If
            If bDropDown Or bPushed Then
                DrawRect hdc, rcDrop, 2, True
            ElseIf bHover Then
                DrawRect hdc, rcDrop, 1, True
            Else
                DrawRect hdc, rcDrop, 0, True
                MouseDown = False
            End If
        Else
            MouseDown = False
        End If
        DrawPloy3 hdc, rcDrop, bHover And Not (bDropDown Or bPushed)
    End If
    '画图标与文本
    With rcIcon
        '计算图标区域
        .Top = tR.Top + 3
        If bBottomText = False Then .Left = tR.Left + 3
        If mlngIconWidth < 16 Then
            If bBottomText Then .Left = tR.Left + (tR.Right - tR.Left - 16) \ 2
            .Right = .Left + 16
        Else
            If bBottomText Then .Left = tR.Left + (tR.Right - tR.Left - mlngIconWidth) \ 2
            .Right = .Left + mlngIconWidth
        End If
        If mlngIconHeight < 16 Then
            .Bottom = .Top + 16
        Else
            .Bottom = .Top + mlngIconHeight
        End If
        If bHover And (Not (bPushed Or bChecked)) Then
            .Left = .Left - 1
            .Top = .Top - 1
            .Right = .Right - 1
            .Bottom = .Bottom - 1
        End If
        If hImageList <> 0 Then
            If bDisabled And bNoDsbIcon Then
                If hIcon Then
                      DrawState hdc, 0, 0, hIcon, 0, .Left, .Top, 0, 0, DST_ICON Or DSS_DISABLED
                End If
            Else
                ImageList_Draw hImageList, tTB.iBitmap, hdc, .Left, .Top, ILD_NORMAL
            End If
        End If
        If Len(sCaption) > 0 Then
            hFont = CreateFontIndirect(Font)
            hOldFont = SelectObject(hdc, hFont)
            If bBottomText Then
                If bDisabled Then
                    SetTextAlign hdc, TA_LEFT
                    GetTextExtentPoint32 hdc, sCaption, lstrlen(sCaption), szText
                    DrawState hdc, 0, 0, StrPtr(StrConv(sCaption, vbFromUnicode)), lstrlen(sCaption), (.Right + .Left - szText.cx) \ 2, .Bottom + 1, 0, 0, DST_TEXT Or DSS_DISABLED
                Else
                    SetTextAlign hdc, TA_CENTER
                    TextOut hdc, (.Right + .Left) \ 2, .Bottom + 1, sCaption, lstrlen(sCaption)
                End If
            Else
                SetTextAlign hdc, TA_LEFT
                If bDisabled Then
                    'GetTextExtentPoint32 hdc, sCaption, lstrlen(sCaption), szText
                    DrawState hdc, 0, 0, StrPtr(StrConv(sCaption, vbFromUnicode)), lstrlen(sCaption), .Right + 1, (.Top + .Bottom - Font.lfHeight) \ 2, 0, 0, DST_TEXT Or DSS_DISABLED
                Else
                    TextOut hdc, .Right + 1, (.Top + .Bottom - Font.lfHeight) \ 2, sCaption, lstrlen(sCaption)
                End If
            End If
            SelectObject hdc, hOldFont
            DeleteObject hFont
        End If
    End With
    If hIcon <> 0 Then DestroyIcon hIcon
End Sub

初涉Custom Draw消息处理,ToolBar本来我就很少用,所以我的兴趣是处理过程本身,而不是应用需求,很难静心深入研究它。

本文地址:http://com.8s8s.com/it/it41304.htm