Solved

Capture Mouse Down Event on form before oject on form catches it???

Posted on 2002-03-28
3
318 Views
Last Modified: 2008-02-07
I have a vb form that has an ocx.  I want to disable the Right Click popup menu of that control and show a different menu (New menu is not related to control).  I have tried to put code in the mouse down event of the ocx, but the popup menu of that control still happens after the code I put there runs.

By the way if it matters the control is a Rumba objectXUnixDisplay control.

How would I get around this?

Thanks,
0
Comment
Question by:Rog
  • 2
3 Comments
 
LVL 16

Expert Comment

by:Richie_Simonetti
ID: 6904509
Has that control an hwnd property?
If so you can install a "hook" to trap mouse event.
This code is used to trap mouse event other control but the idea is almost the same.
from MSDN:
HOWTO: Hook Into a Window's Messages Using AddressOf
Last reviewed: October 16, 1997
Article ID: Q168795  
The information in this article applies to:
Microsoft Visual Basic Enterprise Edition for Windows, version 5.0


SUMMARY
Hooking into a Window (sometimes called sub-classing) is a technique that enables interception of the messages that are being sent to that Window. Microsoft Visual Basic version 5.0 allows sub-classing through the use of the AddressOf operator.

NOTE: This article's purpose is to demonstrate a hooked message stream. It is beyond the scope of this article to describe any particular application of this technique.

WARNING: ANY USE BY YOU OF THE SAMPLE CODE PROVIDED IN THIS ARTICLE IS AT YOUR OWN RISK. Microsoft provides this sample code "as is" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.

WARNING: Failure to unhook a window before its imminent destruction will result in application errors, Invalid Page Faults, and data loss. This is due the fact that the new WindowProc function being pointed to no longer exists, but the window has not been notified of the change. Always unhook the sub-classed window upon unloading the sub-classed form or exiting the application. This is especially important while debugging an application that uses this technique within the Microsoft Visual Basic 5.0 Development Environment. Pressing the End button or selecting End from the Run menu without unhooking will cause an Invalid Page Fault and close Microsoft Visual Basic.



MORE INFORMATION
Microsoft Windows controls applications by sending messages to the windows that are created by each application. These messages alert the targeted window when it's time to redraw, when a mouse button is pressed, and all of the other information a window needs to know in order to act appropriately.

Thus, a minimal Windows application consists of a function for which these messages are processed (called WindowProc). This function is registered into the system when the window is created so the system knows where to send messages.

The following application consists of a simple form with two command buttons. The code is designed to intercept Windows messages being sent to the form and to print the values of those messages in the Immediate window.


In a new "Standard EXE" project, add Form1, two Command Buttons, and Module1.BAS. The first part of the code consists of declarations for the API functions, constant values, and variables:


      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



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



      Public Const GWL_WNDPROC = -4
      Global lpPrevWndProc As Long
      Global gHW As Long


Add the following procedures to MODULE1.BAS:


      Public Sub Hook()
          lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
          AddressOf WindowProc)
      End Sub

      Public Sub Unhook()
          Dim temp As Long
          temp = SetWindowLong(gHW, GWL_WNDPROC,lpPrevWndProc)
      End Sub

   These two procedures enable the code to hook into the stream of
   messages.

   In the first procedure, "Hook," you make use of the SetWindowLong
   function. The SetWindowLong function changes an attribute of a specified
   window. It takes the following parameters:

   hwnd:      The handle of the Window you are going to change.
   nIndex:    The action you are going to do to the window.
   dwNewLong: The new value you change to.

   In this example, you use the Form's hwnd property as the targeted window
   to change. You then use the GWL_WNDPROC constant to tell the
   SetWindowLong function that you want to change the address of the target
   window's WindowProc function. Finally you set dwNewLong to the address
   of a new WindowProc function (see next step). Notice that you store the
   previous WindowProc address in the lpPrevWndProc variable.

   The second procedure, "UnHook," simply reverses what you have done and
   puts the address of the original window procedure back.



Add the following function to MODULE1.BAS:


      Function WindowProc(ByVal hw As Long, ByVal uMsg As _
      Long, ByVal wParam As Long, ByVal lParam As Long) As Long
          Debug.Print "Message: "; hw, uMsg, wParam, lParam
          WindowProc = CallWindowProc(lpPrevWndProc, hw, _
          uMsg, wParam, lParam)
      End Function

   Here is the function that you are routing the window messages to when
   you "Hook" the form's WindowProc function. Note that you make use of the
   CallWindowProc function; using the lpPrevWndProc variable to send any
   unprocessed messages to the original handler. Hence, you are allowing a
   chain of window procedures to process all messages.



Finally, the code for the form sets the initial hWnd value, and the code for the buttons simply calls the two subroutines:


      Private Sub Form_Load()
          gHW = Me.hwnd
      End Sub

      Private Sub Command1_Click()
          Hook
      End Sub

      Private Sub Command2_Click()
          Unhook
      End Sub



Before running this sample, save your project.

The moment Command1 is clicked, the Immediate window starts filling with the messages the form is receiving, hooked through to your new WindowProc function and then passed on to the Form's own handler.  

0
 
LVL 16

Accepted Solution

by:
Richie_Simonetti earned 200 total points
ID: 6904517
Also, from MSDN:

HOWTO: Build a Windows Message Handler with AddressOf in VB5
Last reviewed: October 10, 1997
Article ID: Q170570  
The information in this article applies to:
Microsoft Visual Basic Professional and Enterprise Editions for Windows, version 5.0
Microsoft Visual Studio 97


SUMMARY
Prior to the release of Visual Basic 5.0, many developers used third-party Windows message-handling tools or developed their own with tools such as Microsoft Visual C++. With the addition of the AddressOf function to Visual Basic 5.0, developers can now create their own Windows message-handling routines within their Visual Basic applications.

For example, when a user right-clicks on a textbox in Windows 95 or Windows NT 4.0, the operating system automatically displays a default context menu. This default behavior occurs before the Visual Basic application fires the MouseUp event. Without the use of a Windows message handler, there is no way to replace the default context menu with a custom built context menu.



MORE INFORMATION
WARNING: Using AddressOf may cause unpredictable results if you don't completely understand the concept of function callbacks. You must understand how the Basic portion of the callback works, and also the code of the DLL into which you are passing your function address. Debugging such interactions is difficult because the program runs in the same process as the development environment. In some cases, systematic debugging may not be possible. See details in the REFERENCES section of this article for more information.

The following sample shows how to build a Windows message handler to trap and discard the right-click message to replace the default context menu with a custom built one:


Create a new Standard EXE project. Form1 is created by default.

Use the Menu Editor to add two menu items to the form:


    - For the first item, set its Caption property to "My Popup," its Name
      property to "mnuPopup," and its Visible property to "False."



    - For the second item, set its Caption property to "My Context," its
      Name property to "mnuPopupContext," and use the arrow keys to indent
      the item to be a submenu of the first item.


Add two CommandButtons and a textbox to the form:


    - For the first CommandButton, set its Name property to "cmdHook" and
      its Caption property to "&Hook."



    - For the second CommandButton, set its Name property to "cmdUnHook"
      and its Caption property to "&UnHook."



    - For the textbox, set its Name property to "txtHook" and its Text
      property to "Right Click On Me!"


Add the following code to the form:


      Private Sub cmdHook_Click()
          Hook
      End Sub

      Private Sub cmdUnHook_Click()
          UnHook
      End Sub

      Private Sub Form_Load()
          gHW = txtHook.hWnd
      End Sub

      Private Sub txtHook_MouseUp(Button As Integer, Shift As Integer, _
                                  X As Single, Y As Single)
          If Button = vbRightButton Then
              PopupMenu mnuPopup
          End If
      End Sub



Add a Module to the project.

Add the following code to the new Module:


    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

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

    Public Const GWL_WNDPROC = -4

    Public Const WM_RBUTTONUP = &H205

    Global lpPrevWndProc As Long
    Global gHW As Long

    Public Sub Hook()
        lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
                                     AddressOf WindowProc)
    End Sub

    Public Sub UnHook()
        Dim lngReturnValue As Long
        lngReturnValue = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
    End Sub

    Function WindowProc(ByVal hw As Long, _
                        ByVal uMsg As Long, _
                        ByVal wParam As Long, _
                        ByVal lParam As Long) As Long

        Select Case uMsg
            Case WM_RBUTTONUP
                Form1.PopupMenu Form1.mnuPopup
            Case Else
                WindowProc = CallWindowProc(lpPrevWndProc, hw, _
                                           uMsg, wParam, lParam)
        End Select
    End Function



Save the project and run it. Right-click on the textbox and notice that the default context menu appears before the custom menu. Click on the CommandButton marked "Hook" to enable the Windows message handler. Right-click on the textbox and note that the default context menu no longer appears. Be sure to click on the CommandButton marked "UnHook" before quitting the application. Always disable a custom Windows message handler before the application terminates. Clicking the End button while this sample is running with the Windows message handler still enabled will cause an IPF.

REFERENCES
This as an advanced topic for users experienced with using callbacks, typically C developers. If you are not familiar with the use of callbacks, then the following references may apply:

 
0
 
LVL 8

Author Comment

by:Rog
ID: 7384862
Thanks for the info.  Sorry for the late acceptance.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now