Visual Basic, .NET, ASP, VBScript
 

   
 
Описание для автора не найдено
 
     
   
 

загрузить пример к статье

Введение

    Часто, команды строки меню могут быть запутаны и непонятны новому пользователю Вашего приложения. В то время как стандартные команды Windows, типа File, Open, или Close знакомы, другие команды могут казаться непонятными . К счастью, с помощью subclassing и нескольких функций API, Вы можете иметь больше возможностей. Используя эти инструментальные средства, Ваше приложение может отображать текст подсказки, когда пользователь выбирает пункт меню. Например, заголовок текущего окна или строка состояния могли бы кратко объяснять выбранный пункт меню. В этой статье, мы покажем Вам, как создать callback функцию, чтобы использовать эту особенность.

Подключение callback функции к оконной процедуре

    Чтобы создать систему подсказок для строки меню, мы будем использовать SetWindowLong функцию API. Эта функция API объявляется следующим образом:

Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long)  As Long

    Чтобы заменить стандартную оконную процедуру, мы установим nIndex параметр в GWL_WNDPROC, и dwNewLong к адресу нашей новой функции. Функция SetWindowLong возвращает значение типа Long, которое указывает на предыдущую оконную процедуру. Поскольку каждое окно имеет только одну оконную процедуру, которая обрабатывает все сообщения, посланные ему Windows, то наша новая функция станет единственной, которая будет их получать и обрабатывать.

    После подключения наша функция может определит, когда приложению было послано сообщение WM_MENUSELECT, которое происходит, когда Вы выбираете пункт меню. Если это имеет, то функция отобразит соответствующий текст Help в заголовке окна. Во всех остальных случаях, процедура передаст сообщения первоначальной функции обработки сообщений окна для их обычной обработки. Это гарантирует, что все другие операции окна (изменение размеров, отображение меню, перерисовка содержимого и т.д.) будут выполнены.

    Чтобы обслуживать все остальные сообщения окна, мы объявим API функцию CallWindowProc. Единственная цель этой функции состоит в том, чтобы передать сообщения окну в указанную процедуру. Эта функция объявляется следующим образом:

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

Где lpPrevWndFunc содержит указатель на предыдущую оконную процедуру. В нашем случае, мы будем хранить указатель на первоначальную оконную процедуру, полученную от SetWindowLong, и затем передавать это значение указателя в этом параметре.

Восстановление старой процедуры

    Чтобы восстановить первоначальную оконную процедуру окна, мы будем еще раз использовать функцию SetWindowLong с установкой GWL_WNDPROC. На сей раз, мы передадим адрес первоначальной оконной процедуры в dwNewLong параметре. Теперь, когда мы описали основные функции API, мы будем использовать их в нашей работе. Давайте помещать это все вместе в программу.

Вывод подсказки для строки меню

    Для начала создайте новый проект Visual Basic и сохраните его как Minihelp. Форму переименуйте в frmCallbacks. Затем, в меню Visual Basic, выберите Add Module. Когда VB добавит Module1.BAS, добавьте в него объявления API:

Declare Function SetWindowLong Lib "user32" Alias _
    "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex _
    As Long, ByVal dwNewLong As Long) As Long
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 Const GWL_WNDPROC = -4
Private Const WM_MENUSELECT = &H11F
Public gWH As Long
Public OldWndProc As Long

    Теперь, давайте добавлять процедуру, которая будет принимать сообщения. Добавьте в модуль следующий код:

Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
On Error Resume Next
Dim X As Long
Dim MenuText(0 To 7) As String

    X = CallWindowProc(OldWndProc, hwnd, Msg, wParam, lParam)
    Select Case Msg
        Case WM_MENUSELECT
            MenuText(0) = "This helps catch a big one!"
            MenuText(1) = "Help Options"
            MenuText(2) = "Operatin a callbacks 'n rod"
            MenuText(3) = "Findin a deep API pond"
            MenuText(4) = "Creatin a good fish story"
            MenuText(5) = "Gettin the proper bait"
            MenuText(6) = "Unhook it now that you got it."
            MenuText(7) = "Exit the program"
            frmCallbacks.Caption = MenuText(LowOrd(wParam))
    End Select
    WindowProc = X
End Function

Function LowOrd(DbleWord As Long) As Integer
    If DbleWord And &H8000& Then
        LowOrd = &H8000 Or (DbleWord And &H7FFF&)
    Else
        LowOrd = DbleWord And &HFFFF&
    End If
End Function

Обратите внимание, что там есть также функция LowOrd, которую мы объясним позже.

    Теперь давайте добавим меню. Чтобы это сделать, выберите Tools | Menu Editor. Добавьте следующие пункты в меню:

Caption Name
&Fishin mnuFishin
=>&Operatin menuOperatin
=>F&indin mnuFindin
=>&Creatin mnuCreatin
&Help mnuHelp
=>Help Off mnuHelpOff
&Exitin mnuExitin

    Наконец, мы можем добавить код, чтобы подключить процедуру WindowProc. Добавьте следующий код  к окну кода формы.

Private Sub Form_Load()
    gWH = Me.hwnd
    OldWndProc = SetWindowLong(gWH, GWL_WNDPROC, _
    AddressOf WindowProc)
End Sub

Private Sub mnuExitin_Click()
    Unload Me
End Sub

Private Sub mnuHelpOff_Click()
    SetWindowLong gWH, GWL_WNDPROC, OldWndProc
End Sub

Private Sub mnuOperatin_Click()
    MsgBox "Hook, line, and sinker."
End Sub

Функция callback в действии

    Нажмите [F5], чтобы выполнить программу и выберите пункт меню Fishin. Когда Вы это делаете, Windows использует функцию WindowProc, чтобы обработать сообщение. Сначала всё происходит как и раньше, затем, как только входящее сообщение содержит значение WM_MENUSELECT, функция определяет какой текст нужно разместить в заголовке.

    Всякий раз, когда Windows обрабатывает WM_MENUSELECT сообщение, wParam параметр содержит значение, которое указывает выбранный пункт меню. Функция передает это значение к функции LowOrd, которая обрабатывает его и получает реальное значение, в котором мы нуждаемся. Функция после использует это значение, чтобы определить какой текст подсказки нужно отобразить.

    Чтобы закрыть форму выберите опцию Exitin, или щелкните кнопку Close формы. Когда Вы делаете, Visual Basic отключает функцию WindowProc от окна и восстанавливает первоначальную оконную процедуру.

Заключение

    В этой статье, мы показали Вам, как использовать оператор AddressOf  для создания подкласса окна Windows. Кроме того, мы показали Вам, как использовать свою callback функцию для обработки сообщений Windows.

 
     

   
   
     
  VBNet рекомендует