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:
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:
#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.