Добавление иконки в SystemTray средствами Visual Basic
Эта статья является самодостаточной, то есть в ней дана исчерпывающая информация по созданию иконки в SystemTray с помощью VB. Однако при этом она является компиляцией общедоступных источников, то есть заслуга автора состоит лишь в сборе этой информации в одном месте и пояснениях. Основы создания иконки изложены в FAQ Льва Серебрякова. Используется пример на VB от Alexander Shherbakov. Описания функций и констант из книги Daniel Applemana и API.TXT. Вопросы связанные с редактором ресурсов не рассматриваются
Единственная функция для работы с иконкой Shell_NotifyIcon. Ее описание на VB выглядит так:
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _
(ByVal dwMessage As dwMess, lpData As NOTIFYICONDATA) As Long
Возвращает ноль в случае ошибки Тип dwMess описывается так:
Public Enum dwMess NIM_ADD = &H0 ' Добавление иконки NIM_DELETE = &H2 ' Удаление иконки NIM_MODIFY = &H1 ' Изменение параметров иконки End Enum
Переменная dwMessage должна иметь одно из этих значений. Тип NOTIFYICONDATA имеет следующую структуру: Type NOTIFYICONDATA cbSize As Long ' Размер переменной типа NOTIFYICONDATA hwnd As Long ' Указатель окна создающего иконку uID As Long ' Указатель на иконку в пределах приложения uFlags As uF ' Маска для следующих параметров uCallbackMessage As CallMess ' Возвращаемое событие hIcon As Long ' Указатель на изображение для иконки szTip As String * 64 ' Всплывающий над иконкой текст End Type Где тип uF имеет вид:
Public Enum uF NIF_MESSAGE = &H1 ' Значение имеет uCallbackMessage NIF_ICON = &H2 ' Значение имеет hIcon NIF_TIP = &H4 ' Значение имеет szTip End Enum
Эти константы можно применять в любых сочетаниях, для определения какой из параметров имеет значение.
Тип CallMess: Public Enum CallMess WM_MOUSEMOVE = &H200 WM_LBUTTONDOWN = &H201 WM_LBUTTONUP = &H202 WM_LBUTTONDBLCLK = &H203 WM_RBUTTONDOWN = &H204 WM_RBUTTONUP = &H205 WM_RBUTTONDBLCLK = &H206 WM_MBUTTONDOWN = &H207 WM_MBUTTONUP = &H208 WM_MBUTTONDBLCLK = &H209 WM_SETFOCUS = &H7 WM_KEYDOWN = &H100 WM_KEYFIRST = &H100 WM_KEYLAST = &H108 WM_KEYUP = &H101 End Enum
Эти константы обозначают, какое событие возвращается вызывающей форме. Буквально, все, что будет происходить с иконкой, будет вызывать у формы одно из перечисленных событий. Ясно, что самое частое событие самой иконки это MouseMove, но для формы оно будет выглядеть как событие заданное переменной uCallbackMessage. Как же узнать, что в действительности произошло с иконкой? Это можно узнать через переменные X и Y событий MouseMove, MouseDown и MouseUp вызывающей формы. При этом Y, если событие произошло с иконкой, а не формой, всегда будет равно нулю, а X несет информацию о событии с иконкой. О параметре X следует сказать отдельно. Действительно, он передает информацию о событиях с иконкой, однако эти значения зависят от масштабного коэффициента системного шрифта, но не напрямую, а через параметр свойства TwipsPerPixelX объекта Screen. То есть для одной и той же системы, при разных величинах системного шрифта, значения будут разными. Начальными значениями событий являются следующие:
MouseMove - 512 LeftButtonDown - 513 LeftButtonUp - 514 LeftButtonDblClick - 515 RightButtonDown - 516 RightButtonUp - 517 RightButtonDblClick - 518
Для того чтобы узнать действующие в данной системе значения их следует умножить на Screen.TwipsPerPixelX Как же узнать, что событие произошло с иконкой, а не с формой? Просто, по значению Y, равному нулю. Но есть и другой способ, если используется двухкнопочная мышь то параметр Button в событиях MouseDown и MouseUp формы, будет принимать значения 1 и 2, и при uCallbackMessage равно WM_MBUTTONDOWN=&H207 или WM_MBUTTONUP = &H208 Button равен 4, если событие с иконкой. Само собой разумеется, что возвращаемые X значения следуют одно за другим, как и события (Down->Up->DbClick),поэтому невозможно на одну кнопку мыши назначить два события, к примеру, Click и DbClick. События не связанные с мышью не несут практически ни какой информации, и обычно не используются, следует так же отметить, что количество констант uCallbackMessage намного больше и здесь приведена лишь небольшая часть Из описанного видно, что с иконкой можно совершить одно из следующих действий: добавить, модифицировать и удалить, при этом, модифицируя можно заменить возвращаемое событие, картинку (указатель при этом останется тем же) и всплывающую надпись (ToolTips). Следующий момент, который нужно осветить это получение hIcon (указателя на картинку). Предполагается, что иконка будет находится в исполняемом файле или в DLL с ресурсами, но ни в коем случае не валяется в виде ICO файла. Если иконка запакована в DLL, то нам понадобятся две функции:
Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal _ lpLibFileName As String) As Long Возвращающая hInstance библиотеки с именем lpLibFileName. Достаточно указать только имя файла с расширением, без пути. Возвращает ноль в случае ошибки
Declare Function LoadIconA Lib "user32" (ByVal hInstance As Long, ByVal _ lpIconName As String) As Long Возвращающая hIcon для иконки указанной параметром lpIconName в библиотеке. Этот параметр может быть String или Long, в зависимости от данного вами наименования в Res файле, соответственно надо изменить декларацию. Можно передать и число как строку, для этого перед числом ставится знак #, а все это берется в кавычки. Следует заметить, что использование срокового параметра не желательно из за значительно большего размера занимаемой памяти и соответственно, большего времени на передачу параметра. Функция возвращает ноль в случае ошибки Понадобится так же функция:
Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long Выгружающая библиотеку из памяти. Параметр hLibModule это hInstanse, возвращаемое LoadLibrary. Возвращает ноль в случае ошибки. Обязательно надо не забыть выгрузить из памяти библиотеку, для освобождения памяти. Выгрузку можно произвести сразу же после добавления иконки в SystemTray. Обязательно надо не забыть выгрузить из памяти библиотеку, для освобождения памяти. Выгрузку можно произвести сразу же после добавления иконки в SystemTray.
Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" _ (ByVal lpModuleName As String) As Long Возвращающей hInstanse нашего приложения. В качестве lpModuleName передается имя EXE файла с расширением. Следует быть внимательным, так как имя процесса в TaskMenager не всегда соответствует имени процесса для Windows. Я использую для определения имени DLLView, можно воспользоваться, встроенным в VB System Information. Функция возвращает действительное значение только при работе скомпилированного приложения, а в режиме отладки возвращает ноль, ведь реального процесса при отладке не существует. Свойство hInstanse объекта App всегда возвращает действительное значение, однако при отладке из за отсутствия процесса LoadIcon возвращает 0, и создается "пустая" иконка, тем не менее годная для отладки (реагирующая на все события).
Полученное hInstanse передаем LoadIconA, в качестве lpIconName указываем номер или имя иконки в Res файле, как и в случае с DLL. Выгружать в этом случае ничего не надо.
Создание иконки можно проиллюстрировать следующим примером.
Считается, что иконка с номером 101 находится в файле Project1.exe. Понятно, что пока мы его не скомпилировали, ее там нет (да и самого файла нет). Форма приложения называется Form1.
Dim NID As NOTIFYICONDATA Sub AddIcon() Dim IDLib As Long ' Указатель на библиотеку Dim IDIcon As Long ' Указатель на иконку Const IDMyIcon = 101 ' Идентификатор иконки внутри приложения Dim AddResult As Long ' Результат добавления иконки IDLib = GetModuleHandle("Project1.exe") ' Получаем hInstanse IDIcon = LoadIcon(IDLib, "#101") ' Получаем hIcon ' Заполняем структуру NID типа NOTIFYICONDATA NID.cbSize = Len(NID) ' Размер структуры NID.hwnd = Form1.hWnd ' Указатель на форму NID.uID = IDMyIcon ' Идентификатор иконки NID.uFlags = NIF_MESSAGE + NIF_ICON + NIF_TIP 'Указываем, что действующими являются поля uCallBackMessage, hIcon и szTip. NID.uCallbackMessage = WM_LBUTTONDOWN ' Указываем, что событием возвращаемым в форму является MouseDown с параметром Button = 2 NID.hIcon = IDIcon ' Указатель на иконку в файле NID.szTip = Left$("MyIcon", 63) & Chr(0) ' Передаем всплывающую фразу "MyIcon", при этом обрезаем ее до 63 символов и добавляем 64-й символ с кодом ноль AddResult = Shell_NotifyIcon(NIM_ADD, NID) ' Вызываем функцию, через параметр dwMessage указываем, что следует добавить иконку, и передаем заполненный NID End Sub
Удаление созданной иконки можно сделать так:
Sub DeleteIcon() Dim DeletResult As Long DeleteResult = Shell_NotifyIcon(NIM_DELETE, NID) ' Вызываем функцию, через dwMessage указываем, что 'следует удалить иконку, при этом, раз переменная NID описана на уровне модуля, не следует заполнять ее 'заново End Sub Размер структуры достаточно указывать один раз, так как за время жизни переменной он измениться не может, и в данном виде составляет 88 байт. Даже при изменении всплывающей строки ее длина (строки) не будет больше 64 байт. Для модификации иконки надо вызвать Shell_NotifyIcon с параметром dwMessage равным NIM_MODIFY и NID с внесенными изменениями, при этом параметр uFlags будет указывать, какие из параметров изменены. В форме Form1 для обработки, к примеру, DbClick левой кнопкой мыши по иконке можно применить следующий код: Private Sub Form_MouseDown(Button As Integer, Shift As Integer _ X As Single, Y As Single) ' Событие MouseDown происходит не потому, что пользователь нажал на кнопку мыши над иконкой, а из-за того, что параметр uCallbackMessage имеет значение WM_LBUTTONDOWN
If Y = 0 Then ' Y = 0 если событие с иконкой Select Case X Case 515*Screen.TwipsPerPixelX ' Значение X при LeftDblClick ' Код, выполняемый в случае LeftDblClick End Select
End If End Sub
Страница сайта http://silicontaiga.ru
Оригинал находится по адресу http://silicontaiga.ru/home.asp?artId=6264
|