Estimado Armando,
La
cuestión que planteas aunque parece fácil es bastante complicada. Te explico el por qué:
1. Windows no proporciona un estilo de combobox que automaticamente procese el mensaje WM_MOUSEWHEEL en la lista desplegada del combobox.
2. Los mensajes WM_MOUSEWHEEL llegan a la lista desplegada y no al combobox por lo que no podemos usar oCombo:bMouseWheel
3. La única solución que parece posible es localizar el handle de ventana de la lista desplegable y "subclasear" su procedimiento para que procese WM_MOUSEWHEEL adecuadamente.
Para localizar el handle de la lista desplegada podemos hacer esto:
Code: Select all | Expand
METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TComboBox
local hWndComboList
if nMsg == FM_CLOSEUP
return ::CloseUp()
endif
if nMsg == FM_DROPDOWN
return ::DropDown()
endif
if ::hWndComboList == nil .and. IsWindow( hWndComboList := hWndComboList( ::hWnd ) )
::hWndComboList = hWndComboList
// SetWindowProc( hWndComboList, { || nil } ) // probando la nueva función SetWindowProc()
endif
return ::Super:HandleEvent( nMsg, nWParam, nLParam )
Ahora en ::hWndComboList tenemos el handle de ventana de la lista desplegada y tenemos que implementar una nueva función SetWindowProc() para "subclasearla" y asi poder implementar el comportamiento para los mensajes WM_MOUSEWHEEL.
El código de la nueva función SetWindowProc() es un tanto complicado pero debera funcionar correctamente implementado asi:
Code: Select all | Expand
#include <windows.h>
#include <hbapi.h>
#include <hbapiitm.h>
#include <hbvm.h>
#if ( defined( _MSC_VER ) && ( _MSC_VER < 1500 ) ) // VC98
#define GWLP_USERDATA -21
#define GWLP_WNDPROC -4
LONG_PTR GetWindowLongPtr( HWND hWnd, int nIndex );
LONG_PTR SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong );
#endif
typedef struct
{
PHB_ITEM pBlock;
WNDPROC pOldProc;
} HB_SUBCLASSED, * PHB_SUBCLASSED;
static LRESULT CALLBACK HB_SubclassedProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
PHB_SUBCLASSED pSubclassed = ( PHB_SUBCLASSED ) GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( pSubclassed && pSubclassed->pBlock )
{
PHB_ITEM pReturn;
#ifndef _WIN64
PHB_ITEM phWnd = hb_itemPutNL( NULL, ( long ) hWnd );
PHB_ITEM pMessage = hb_itemPutNL( NULL, ( long ) message );
PHB_ITEM pwParam = hb_itemPutNL( NULL, ( long ) wParam );
PHB_ITEM plParam = hb_itemPutNL( NULL, ( long ) lParam );
#else
PHB_ITEM phWnd = hb_itemPutNLL( NULL, ( HB_LONGLONG ) hWnd );
PHB_ITEM pMessage = hb_itemPutNLL( NULL, ( HB_LONGLONG ) message );
PHB_ITEM pwParam = hb_itemPutNLL( NULL, ( HB_LONGLONG ) wParam );
PHB_ITEM plParam = hb_itemPutNLL( NULL, ( HB_LONGLONG ) lParam );
#endif
hb_evalBlock( pSubclassed->pBlock, phWnd, pMessage, pwParam, plParam, NULL );
hb_itemRelease( phWnd );
hb_itemRelease( pMessage );
hb_itemRelease( pwParam );
hb_itemRelease( plParam );
pReturn = hb_param( -1, HB_IT_ANY );
if( HB_IS_NUMERIC( pReturn ) )
return hb_itemGetNL( pReturn );
}
return pSubclassed && pSubclassed->pOldProc ?
CallWindowProc( pSubclassed->pOldProc, hWnd, message, wParam, lParam ) :
DefWindowProc( hWnd, message, wParam, lParam );
}
HB_FUNC( SETWINDOWPROC )
{
#ifndef _WIN64
HWND hWnd = ( HWND ) hb_parnl( 1 );
#else
HWND hWnd = ( HWND ) hb_parnll( 1 );
#endif
PHB_ITEM pBlock = hb_param( 2, HB_IT_BLOCK );
if( hWnd && pBlock )
{
PHB_SUBCLASSED pSubclassed = ( PHB_SUBCLASSED ) GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( ! pSubclassed )
{
pSubclassed = ( PHB_SUBCLASSED ) hb_xgrab( sizeof( HB_SUBCLASSED ) );
SetWindowLongPtr( hWnd, GWLP_USERDATA, ( LONG_PTR ) pSubclassed );
}
else
hb_itemRelease( pSubclassed->pBlock );
pSubclassed->pBlock = hb_itemNew( pBlock );
pSubclassed->pOldProc = ( WNDPROC ) SetWindowLongPtr( hWnd, GWLP_WNDPROC,
( LONG_PTR ) HB_SubclassedProc );
hb_retnl( ( LONG_PTR ) pSubclassed->pOldProc );
}
else
hb_retnl( 0 );
}
HB_FUNC( REMOVEWINDOWPROC )
{
#ifndef _WIN64
HWND hWnd = ( HWND ) hb_parnl( 1 );
#else
HWND hWnd = ( HWND ) hb_parnll( 1 );
#endif
if( hWnd )
{
PHB_SUBCLASSED pSubclassed = ( PHB_SUBCLASSED ) GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( pSubclassed )
{
SetWindowLongPtr( hWnd, GWLP_WNDPROC, ( LONG_PTR ) pSubclassed->pOldProc );
hb_itemRelease( pSubclassed->pBlock );
SetWindowLongPtr( hWnd, GWLP_USERDATA, 0 );
hb_xfree( pSubclassed );
}
}
}
En principio todo parece estar bien y ya podriamos continuar implementando el soporte para WM_MOUSEWHEEL. El problema es que al intentar usar SetWindowProc() obtenemos un GPF que nos deja fuera de juego. Estamos buscando la razón de ese GPF.