The code does not work for me too. I also get one click/mouse down event followed by a double-click event.
I would suggest subclassing as the implementation is easy and clean.
You don't need to intercept button-down messages. Instead, you need to intercept double-click messages and transform them to button-down messages.
See the following example. Insert the following code in your form having a picturebox.
___
[tt]
Private Sub Form_Load()
Const GWL_WNDPROC = -4
lpWndFunc = SetWindowLong(Picture1.hwnd, GWL_WNDPROC, AddressOf WndProc)
End Sub
Private Sub Picture1_Click()
Debug.Print Time, "Click"
End Sub
Private Sub Picture1_DblClick()
Debug.Print Time, "Double Click"
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print Time, "Mouse Down", Button, Shift, X, Y
End Sub
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print Time, "Mouse Up", Button, Shift, X, Y
End Sub[/tt]
___
The following code goes in a module used for subclassing.
___
[tt]
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 lpWndFunc As Long
Const WM_LBUTTONDBLCLK = &H203
Const WM_LBUTTONDOWN = &H201
Const WM_MBUTTONDBLCLK = &H209
Const WM_MBUTTONDOWN = &H207
Const WM_RBUTTONDBLCLK = &H206
Const WM_RBUTTONDOWN = &H204
Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'convert double-click messages to button-down messages
If uMsg = WM_LBUTTONDBLCLK Then uMsg = WM_LBUTTONDOWN
If uMsg = WM_RBUTTONDBLCLK Then uMsg = WM_RBUTTONDOWN
If uMsg = WM_MBUTTONDBLCLK Then uMsg = WM_MBUTTONDOWN
WndProc = CallWindowProc(lpWndFunc, hwnd, uMsg, wParam, lParam)
End Function[/tt]
___
Run the program and test it. You will see that the double-click event never fires. Instead, you get another pair of mouse down/mouse up events followed by a click event.
The artificially created events also report all the parameters (Button, Shift, X, Y) correctly. This is because the message parameters (wParam/lParam) for button-down and double-click messages are exactly same. The parameters generated by original double-click message are used by the modified button-down message without loosing any information.
Furthermore, the code works for all 3 buttons. You can remove the check for right and middle button messages if you don't use them.