Problems when capturing windowproc

  • Thread starter heikki.vuolteenaho
  • Start date
H

heikki.vuolteenaho

Hi,

Some background: I'm using a temporary ComboBox control (from controls
toolbox) on a worksheet to provide users with selection list with
autocompletion etc. It works very well except for one thing: When the
dropdown list of the combobox is open, using the mouse scrollwheel does
not change the list selection. Even worse than doing nothing, it
scrolls the entire worksheet while still leaving the dropdown list in
the midlle of the screen! I guess many of you have already noticed this
"feature".

So, to solve this, I googled a bit and found a way to capture the mouse
scrollwheel events. Something like this:
http://www.enhanceddatasystems.com/ED/Pages/ExcelListScrolls.htm

However, my combobox isn't on a userform but directly on a worksheet.
It seems capturing windowproc on non-userform windows is a bit tricky,
since I can't seem to get it to work.

Below is a very simple test module to capture the windowproc for the
current workbook window. The new windowproc does nothing but forwards
the received messages to previous windowproc. So, in theory, this
should not affect Excel's behaviour in any way.

Well, it does. As soon as I call Hook(), Excel becomes unresponsive. I
can't even select a cell on the workbook. I'm forced to use
ctrl-alt-del to kill Excel. Is there something wrong in my call to
CallWindowProcA? It seems OK to me.

Any other suggestiong how the fix the combobox with scrollwheel events?


Thanks in advance
Heikki


*******************************************************************************
Sample code below:
********************************************************************************

Option Explicit
Option Private Module


'
' Windows API function declarations
'

Private Declare Function SetWindowLongA Lib "user32.dll" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) _
As Long

Private Declare Function CallWindowProcA Lib "user32.dll" _
(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long,
ByVal wParam As Long, ByVal lParam As Long) _
As Long

Private Declare Function FindWindowExA Lib "user32" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String,
ByVal lpsz2 As String) _
As Long


'
' Constants
'
Private Const GWL_WNDPROC = -4
Private Const XL_DESK As String = "XLDESK"
Private Const XL_WORKBOOK As String = "EXCEL7"


'
' Variables
'
Dim PrevWndProc As Long


'
' Finds the workbook window handle
'
Private Function GetWorkbookHandle(Name As String) As Long
Dim hWndDesk As Long
' Excel desk handle
hWndDesk = FindWindowExA(Application.hWnd, 0, XL_DESK, vbNullString)
' Workbook handle
GetWorkbookHandle = FindWindowExA(hWndDesk, 0, XL_WORKBOOK, Name)
End Function



'
' Replacement WindowProc, only calls the original windowproc
'
Private Function MyWindowProc(ByVal hWnd As Long, ByVal lMsg As Long,
ByVal wParam As Long, ByVal lParam As Long) As Long
MyWindowProc = CallWindowProcA(PrevWndProc, hWnd, lMsg, wParam,
lParam)
End Function


'
' Hooks the windowproc
'
Public Sub Hook()
Dim hWnd As Long
hWnd = GetWorkbookHandle(ThisWorkbook.Name)
PrevWndProc = SetWindowLongA(hWnd, GWL_WNDPROC, AddressOf
MyWindowProc)
End Sub


'
' Return control to original windowproc
'
Public Sub UnHook()
Dim hWnd As Long
hWnd = GetWorkbookHandle(ThisWorkbook.Name)
Call SetWindowLongA(hWnd, GWL_WNDPROC, PrevWndProc)
End Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top