Foreros:
Resulta que la rueda del ratón (MouseWheel) no funciona en un ComboBox
con estilo DROPDOWNLIST, alguna idea?
Saludos
La rueda del ratón no funciona en DROPDOWNLIST
La rueda del ratón no funciona en DROPDOWNLIST
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
- Antonio Linares
- Site Admin
- Posts: 42268
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: La rueda del ratón no funciona en DROPDOWNLIST
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:
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:
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.
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 )
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 );
}
}
}
- Antonio Linares
- Site Admin
- Posts: 42268
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Re: La rueda del ratón no funciona en DROPDOWNLIST
Estábamos equivocados
Sin ningún cambio en FWH, la rueda de mouse SI funciona con listas de combobox cuando la lista es más grande que el área de la lista.
Cuando la lista es grande, vemos una barra de desplazamiento y luego tanto la barra de desplazamiento como la rueda de mouse funcionan.
Cuando la lista es pequeña, no hay necesidad y ni siquiera tiene sentido que la rueda de mouse funcione.
Gracias a Rao por sabiamente observar esto!
Sin ningún cambio en FWH, la rueda de mouse SI funciona con listas de combobox cuando la lista es más grande que el área de la lista.
Cuando la lista es grande, vemos una barra de desplazamiento y luego tanto la barra de desplazamiento como la rueda de mouse funcionan.
Cuando la lista es pequeña, no hay necesidad y ni siquiera tiene sentido que la rueda de mouse funcione.
Gracias a Rao por sabiamente observar esto!
Re: La rueda del ratón no funciona en DROPDOWNLIST
Maestro Antonio y Mr. Rao:
Tienen la boca llena de razón, tengo dos PRG que usan el control, ahora que lo mencionaste
comparé uno con otro y efectivamente, uno funciona y en el otro no.
Revisé el control y en el que no funcionaba tenia yo el WINDOWS-STYLE Vert Scrollbar a NO.
Me disculpo fue mi error.
Saludos
Tienen la boca llena de razón, tengo dos PRG que usan el control, ahora que lo mencionaste
comparé uno con otro y efectivamente, uno funciona y en el otro no.
Revisé el control y en el que no funcionaba tenia yo el WINDOWS-STYLE Vert Scrollbar a NO.
Me disculpo fue mi error.
Saludos
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero