Статьи

Листинг (продолжение) к статье
"Как написать Add-In или ...
большие мучения с маленькой программой."

Форма "frmAddIn"

Public VBInstance As VBIDE.VBE
Public Connect As Connect

Option Explicit

Private Sub CancelButton_Click()
    Connect.Hide
End Sub

Private Sub cmdAbout_Click()
    frmAbout.Show vbModal
End Sub

Private Sub cmdAdd_Click()
Dim Msg$, i%

Msg = InputBox("Введите имя для основного меню:", "Создание меню")
If Trim(Msg) <> vbNullString Then
    For i = 0 To lstMenu.ListCount - 1
        If UCase(lstMenu.List(i)) = UCase(Trim(Msg)) Then
            MsgBox "Меню с именем '" & Trim(Msg) & "' уже существует!", _
                vbInformation + vbOKOnly, "Ошибка!"
            Exit Sub
        End If
    Next
    Msg = Trim(Replace(Msg, " ", ""))
    lstMenu.AddItem Msg
End If
End Sub

Private Sub cmdDelete_Click()
If lstMenu.ListIndex = -1 Then Exit Sub
    If MsgBox("Удалить меню '" & lstMenu.List(lstMenu.ListIndex) & _
        "' ?", vbYesNo + vbQuestion + vbDefaultButton2, "Удаление меню") _
        = vbYes Then
    lstMenu.RemoveItem lstMenu.ListIndex
    End If
End Sub

Private Sub Form_Load()
lblInfo.Caption = "Данный Add-In компонует коды для создания нестандартного бокового меню." & _
vbCrLf & "Выберите форму, куда Вы собираетесь это меню вставить и сформируйте перечень основных меню."
End Sub

Private Sub OKButton_Click()
Dim thisProject As VBProject
Dim thisForm As VBForm
Dim PanelMenu As VBControl
Dim ctrlMenu As VBControl
Dim mnuMenu As VBControl
Dim mnuSubMenu As VBControl
Dim thisCode As CodeModule
Dim i%, j%, NumOptExp%

If cboForm.ListCount = 0 Then
    MsgBox "Должна существовать хотя бы одна форма.", _
        vbInformation + vbOKOnly, "Ошибка!"
    Exit Sub
End If

If lstMenu.ListCount = 0 Then
    MsgBox "Необходимо создать, хотя бы одно меню.", _
        vbInformation + vbOKOnly, "Ошибка!"
    Exit Sub
End If

Screen.MousePointer = vbHourglass

If ErrName = False Then
    Exit Sub
End If

Set thisProject = VBInstance.ActiveVBProject
Set thisForm = thisProject.VBComponents.Item(cboForm.Text).Designer
Set PanelMenu = thisForm.ContainedVBControls.Add("PictureBox")

With PanelMenu
    .Properties("Name") = "picBack"
    .Properties("Align") = 3
    .Properties("AutoRedraw") = True
    .Properties("BorderStyle") = 0
    .Properties("ScaleMode") = 3
    .Properties("Width") = 375
End With

For i = 0 To lstMenu.ListCount - 1
    Set ctrlMenu = PanelMenu.ContainedVBControls.Add("PictureBox")

    With ctrlMenu
        .Properties("Name") = lstMenu.List(i)
        .Properties("AutoRedraw") = True
        .Properties("BorderStyle") = 0
        .Properties("ScaleMode") = 3
        .Properties("Left") = 4
        .Properties("Height") = 33
        .Properties("Width") = 17
    End With

    Set mnuMenu = thisForm.ContainedVBControls.Add("Menu")

    With mnuMenu
        .Properties("Name") = lstMenu.List(i) & "1"
        .Properties("Caption") = lstMenu.List(i)
        .Properties("Visible") = False
    End With

    For j = 0 To 1
        Set mnuSubMenu = mnuMenu.ContainedVBControls.Add("Menu")

        With mnuSubMenu
            .Properties("Index") = j
            .Properties("Name") = "Sub" & lstMenu.List(i)
            .Properties("Caption") = "Sub" & lstMenu.List(i)
            .Properties("Visible") = True
        End With
    Next
Next

Set thisCode = thisProject.VBComponents.Item(cboForm.Text).CodeModule
'Если Option Explicit не на первой строке
For i = 1 To 20
    If thisCode.Lines(i, 1) = "Option Explicit" Then
        NumOptExp = i + 1
        Exit For
    Else
        NumOptExp = 1
    End If
Next

thisCode.InsertLines NumOptExp, CodeText

Set thisProject = Nothing
Set thisForm = Nothing
Set PanelMenu = Nothing
Set ctrlMenu = Nothing
Set mnuMenu = Nothing
Set mnuSubMenu = Nothing
Set thisCode = Nothing

Screen.MousePointer = vbDefault

frmConfirm.Show vbModal
Connect.Hide
End Sub

Private Function ErrName() As Boolean
Dim TempProject As VBProject
Dim TempForm As VBForm
Dim iControl As Integer, sCtrl As String, i%, TempName$

Set TempProject = VBInstance.ActiveVBProject
Set TempForm = TempProject.VBComponents.Item(cboForm.Text).Designer

For iControl = 1 To TempForm.VBControls.Count
    TempName = TempForm.VBControls.Item(iControl).Properties("Name")

    If TempName = "picBack" Then
        sCtrl = "picBack"
        GoTo LineErr
    End If

    For i = 0 To lstMenu.ListCount - 1
        If TempName = lstMenu.List(i) Then
            sCtrl = lstMenu.List(i)
            GoTo LineErr
        ElseIf TempName = lstMenu.List(i) & "1" Then
            sCtrl = lstMenu.List(i) & "1"
            GoTo LineErr
        ElseIf TempName = "Sub" & lstMenu.List(i) Then
            sCtrl = "Sub" & lstMenu.List(i)
            GoTo LineErr
        End If
    Next
Next

ErrName = True

GoTo LineExit

LineErr:
MsgBox "На форме '" & cboForm.Text & "' уже имеется элемент с именем '" & _
sCtrl & "'. Ваши возможные дальнейшие действия:" & vbCrLf & _
" 1. Выбрать другую форму;" & vbCrLf & _
" 2. Переименовать на форме элемент '" & sCtrl & "'" & vbCrLf & _
" 3. Удалить на форме элемент '" & sCtrl & "'", _
vbInformation + vbOKOnly, "Ошибка совпадения имен!"
ErrName = False

LineExit:
Set TempProject = Nothing
Set TempForm = Nothing
Screen.MousePointer = vbDefault
End Function

Private Function CodeText() As String
Dim Str$, i%

Str = "Private Const LOGPIXELSX = 88" & vbCrLf
Str = Str & "Private Const LOGPIXELSY = 90" & vbCrLf
Str = Str & "Private Const LF_FACESIZE = 32" & vbCrLf
Str = Str & "Private Const FW_NORMAL = 400" & vbCrLf
Str = Str & "Private Const FW_BOLD = 700" & vbCrLf
Str = Str & "Private Const FF_DONTCARE = 0" & vbCrLf
Str = Str & "Private Const DEFAULT_QUALITY = 0" & vbCrLf
Str = Str & "Private Const DEFAULT_PITCH = 0" & vbCrLf
Str = Str & "Private Const DEFAULT_CHARSET = 1" & vbCrLf
Str = Str & "Private Const CLR_INVALID = -1" & vbCrLf
Str = Str & "Private Const OUT_DEFAULT_PRECIS = 0" & vbCrLf & vbCrLf

Str = Str & "Private Type LOGFONT" & vbCrLf
Str = Str & " lfHeight As Long" & vbCrLf
Str = Str & " lfWidth As Long" & vbCrLf
Str = Str & " lfEscapement As Long" & vbCrLf
Str = Str & " lfOrientation As Long" & vbCrLf
Str = Str & " lfWeight As Long" & vbCrLf
Str = Str & " lfItalic As Byte" & vbCrLf
Str = Str & " lfUnderline As Byte" & vbCrLf
Str = Str & " lfStrikeOut As Byte" & vbCrLf
Str = Str & " lfCharSet As Byte" & vbCrLf
Str = Str & " lfOutPrecision As Byte" & vbCrLf
Str = Str & " lfClipPrecision As Byte" & vbCrLf
Str = Str & " lfQuality As Byte" & vbCrLf
Str = Str & " lfPitchAndFamily As Byte" & vbCrLf
Str = Str & " lfFaceName(LF_FACESIZE) As Byte" & vbCrLf
Str = Str & "End Type" & vbCrLf & vbCrLf

Str = Str & "Private Const SW_SHOWNORMAL = 1" & vbCrLf
Str = Str & "Private Const SRCCOPY = &HCC0020" & vbCrLf & vbCrLf

Str = Str & "Private Declare Function CreateFontIndirect Lib " _
    & Chr(34) & "gdi32" & Chr(34) & " Alias " & Chr(34) _
    & "CreateFontIndirectA" & Chr(34) & " (lpLogFont As LOGFONT) As Long" & vbCrLf
Str = Str & "Private Declare Function TextOut Lib " & Chr(34) & _
    "gdi32" & Chr(34) & " Alias " & Chr(34) & "TextOutA" & Chr(34) & _
    " (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, " & _
    "ByVal lpString As String, ByVal nCount As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function SelectObject Lib " & Chr(34) & _
    "gdi32" & Chr(34) & " (ByVal hDC As Long, ByVal hObject As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function DeleteObject Lib " & Chr(34) & _
    "gdi32" & Chr(34) & " (ByVal hObject As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function GetDeviceCaps Lib " & Chr(34) & _
    "gdi32" & Chr(34) & " (ByVal hDC As Long, ByVal nIndex As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function MulDiv Lib " & Chr(34) & "kernel32" & Chr(34) & _
    " (ByVal nNumber As Long, ByVal nNumerator As Long, ByVal nDenominator As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function SetCapture Lib " & Chr(34) & "user32" _
    & Chr(34) & " (ByVal hwnd As Long) As Long" & vbCrLf
Str = Str & "Private Declare Function ReleaseCapture Lib " & Chr(34) & "user32" & _
    Chr(34) & " () As Long" & vbCrLf & vbCrLf

Str = Str & "Private Sub DrawSMenu(pic As PictureBox, capt As String)" & vbCrLf
Str = Str & "Dim tLF As LOGFONT" & vbCrLf
Str = Str & "Dim hFnt As Long" & vbCrLf
Str = Str & "Dim hFntOld As Long" & vbCrLf
Str = Str & "Dim lR As Long" & vbCrLf & vbCrLf

Str = Str & "On Error GoTo DrawError" & vbCrLf
Str = Str & " 'изменяем высоту в зависимости от текста" & vbCrLf
Str = Str & " 'по 4 пиксела с обеих сторон" & vbCrLf
Str = Str & " pic.Height = pic.TextWidth(capt) + 8" & vbCrLf
Str = Str & " 'рисование шрифта текста на контроле" & vbCrLf
Str = Str & " pOLEFontToLogFont pic.Font, pic.hDC, tLF" & vbCrLf
Str = Str & " 'угол наклона текста 90 градусов" & vbCrLf
Str = Str & " tLF.lfEscapement = 900" & vbCrLf
Str = Str & " hFnt = CreateFontIndirect(tLF)" & vbCrLf
Str = Str & " If (hFnt <> 0) Then" & vbCrLf
Str = Str & " hFntOld = SelectObject(pic.hDC, hFnt)" & vbCrLf
Str = Str & " 'вывод текста на контроле" & vbCrLf
Str = Str & " lR = TextOut(pic.hDC, 0, pic.Height - 4, capt, Len(capt))" & vbCrLf
Str = Str & " SelectObject pic.hDC, hFntOld" & vbCrLf
Str = Str & " DeleteObject hFnt" & vbCrLf
Str = Str & " End If" & vbCrLf
Str = Str & "Exit Sub" & vbCrLf & vbCrLf

Str = Str & "DrawError:" & vbCrLf
Str = Str & " MsgBox Err.Number & Err.Description, vbInformation, " & _
    Chr(34) & "ERROR!" & Chr(34) & vbCrLf
Str = Str & "End Sub" & vbCrLf & vbCrLf

Str = Str & "Private Sub pOLEFontToLogFont(fntThis As StdFont, hDC As Long, tLF As LOGFONT)" & vbCrLf
Str = Str & "Dim sFont As String" & vbCrLf
Str = Str & "Dim iChar As Integer" & vbCrLf & vbCrLf

Str = Str & " ' Конвертация OLE StdFont в структуру LOGFONT" & vbCrLf
Str = Str & " With tLF" & vbCrLf
Str = Str & " .lfOutPrecision = OUT_DEFAULT_PRECIS" & vbCrLf
Str = Str & " .lfClipPrecision = OUT_DEFAULT_PRECIS" & vbCrLf
Str = Str & " .lfQuality = DEFAULT_QUALITY" & vbCrLf
Str = Str & " .lfPitchAndFamily = DEFAULT_PITCH Or FF_DONTCARE" & vbCrLf
Str = Str & " .lfCharSet = DEFAULT_CHARSET" & vbCrLf & vbCrLf

Str = Str & " sFont = fntThis.Name" & vbCrLf
Str = Str & " ' Перевод в биты" & vbCrLf
Str = Str & " For iChar = 1 To Len(sFont)" & vbCrLf
Str = Str & " .lfFaceName(iChar - 1) = CByte(Asc(Mid$(sFont, iChar, 1)))" & vbCrLf
Str = Str & " Next iChar" & vbCrLf
Str = Str & " ' установка параметров шрифта" & vbCrLf
Str = Str & " .lfHeight = -MulDiv((fntThis.Size), (GetDeviceCaps(hDC, LOGPIXELSY)), 72)" & vbCrLf
Str = Str & " .lfItalic = fntThis.Italic" & vbCrLf
Str = Str & " If (fntThis.Bold) Then" & vbCrLf
Str = Str & " .lfWeight = FW_BOLD" & vbCrLf
Str = Str & " Else" & vbCrLf
Str = Str & " .lfWeight = FW_NORMAL" & vbCrLf
Str = Str & " End If" & vbCrLf
Str = Str & " .lfUnderline = fntThis.Underline" & vbCrLf
Str = Str & " .lfStrikeOut = fntThis.Strikethrough" & vbCrLf
Str = Str & " End With" & vbCrLf
Str = Str & "End Sub" & vbCrLf & vbCrLf

Str = Str & "Private Sub Form_Load()" & vbCrLf
Str = Str & " 'рисуем границу" & vbCrLf
Str = Str & " With picBack" & vbCrLf
Str = Str & " picBack.Line (.ScaleWidth - 2, 0)-(.ScaleWidth - 2, .ScaleHeight), &H8000000C" & vbCrLf
Str = Str & " picBack.Line (.ScaleWidth - 1, 0)-(.ScaleWidth - 1, .ScaleHeight), &HFFFFFF" & vbCrLf
Str = Str & " End With" & vbCrLf & vbCrLf

Str = Str & " 'Данные функции поворота шрифта работают только со шрифтами TrueType." & vbCrLf
Str = Str & " 'Шрифт Tahoma наиболее близко похож на MS Sans Serif." & vbCrLf
Str = Str & " 'Если на Вашем компьютере нет этого шрифта, замените его на любой другой TrueType-шрифт" & vbCrLf

For i = 0 To lstMenu.ListCount - 1

Str = Str & " " & lstMenu.List(i) & ".FontName = " & Chr(34) & "Tahoma" & Chr(34) & vbCrLf
Str = Str & " DrawSMenu " & lstMenu.List(i) & ", " & Chr(34) & lstMenu.List(i) & Chr(34) & vbCrLf

Next

Str = Str & "End Sub" & vbCrLf & vbCrLf

Str = Str & "Private Sub Form_Resize()" & vbCrLf
Str = Str & " 'Если форма имеет свойство ScaleMode = 3' Pixel - то в кодах необходимо убрать / Screen.TwipsPerPixelY" & vbCrLf
Str = Str & " " & lstMenu.List(0) & ".Move 4, ScaleHeight / Screen.TwipsPerPixelY - " _
    & lstMenu.List(0) & ".Height - 6" & vbCrLf

For i = 1 To lstMenu.ListCount - 1

Str = Str & " " & lstMenu.List(i) & ".Move 4, " & lstMenu.List(i - 1) & _
    ".Top - " & lstMenu.List(i) & ".Height - 2" & vbCrLf

Next

Str = Str & "End Sub" & vbCrLf & vbCrLf

For i = 0 To lstMenu.ListCount - 1

Str = Str & "Private Sub " & lstMenu.List(i) & "_Click()" & vbCrLf
Str = Str & " 'Если форма имеет свойство ScaleMode = 3' Pixel - то в кодах необходимо убрать * Screen.TwipsPerPixelX и * Screen.TwipsPerPixelY" & vbCrLf
Str = Str & " PopupMenu " & lstMenu.List(i) & "1, , (" & lstMenu.List(i) & _
    ".Left + " & lstMenu.List(i) & ".Width) * Screen.TwipsPerPixelX, " & _
    lstMenu.List(i) & ".Top * Screen.TwipsPerPixelY" & vbCrLf
Str = Str & "End Sub" & vbCrLf & vbCrLf

Str = Str & "Private Sub " & lstMenu.List(i) & _
    "_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)" & vbCrLf
Str = Str & " If X > 0 And X < " & lstMenu.List(i) & _
   
".ScaleWidth And Y > 0 And Y < " & lstMenu.List(i) & ".ScaleHeight Then" & vbCrLf
Str = Str & " SetCapture " & lstMenu.List(i) & ".hwnd" & vbCrLf
Str = Str & " " & lstMenu.List(i) & ".BorderStyle = 1" & vbCrLf
Str = Str & " Else" & vbCrLf
Str = Str & " ReleaseCapture" & vbCrLf
Str = Str & " " & lstMenu.List(i) & ".BorderStyle = 0" & vbCrLf
Str = Str & " End If" & vbCrLf
Str = Str & "End Sub" & vbCrLf & vbCrLf

Str = Str & "Private Sub " & lstMenu.List(i) & _
    "_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)" & vbCrLf
Str = Str & " ReleaseCapture" & vbCrLf
Str = Str & " " & lstMenu.List(i) & ".BorderStyle = 0" & vbCrLf
Str = Str & "End Sub" & vbCrLf & vbCrLf

Next

CodeText = Str

End Function

 

К статье Окончание листинга
Hosted by uCoz