May 06, 2024, 03:41:02 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Messages for right click on a button

Started by barry, January 15, 2007, 08:28:55 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

barry

I'd like to be able to distinguish between a left and right click on a button.  I see how to do it on part of the client area, a rectangle, etc, but not how to detect a click or left click on a button.  Is there an easy way to do this?  Or should I just use a rectangular area instead of a button?  I can do either one but it seemed that using a button would be simpler.

Thanks,
Barry

sapero

January 16, 2007, 02:50:22 AM #1 Last Edit: January 16, 2007, 02:57:42 AM by sapero
A button ignores right-clicks, but we can change this bechavior by subclassing the button, or better - registering new button class with same name, but with replaced window handler (superclass).
The new button procedure handles WM_RBUTTONDOWN message and sends a standard WM_COMMAND message to the owner window with custom BN_CONTEXTMENU notification; all other messages are passed to the original button handler.
Using subclassing you would call SetWindowLong... for every button, using superclass, it is much easier!
Window Procedure Superclassing
$include "windows.inc"
main()

' define a custom notification
const BN_CONTEXTMENU = 300

dialog d1
UINT g_menu
UINT g_OldButtonProc
extern _hinstance as UINT
declare import, TrackPopupMenu alias TrackPopupMenu(hMenu:INT,wFlags:INT,x:INT,y:INT,nReserved:INT,hwnd:INT,lprc:pointer),INT

sub main()
' this call will change window handler for all buttons
RegisterButtonSuperclass()
CREATEDIALOG d1,0,0,300,51,0x80CA0880,0,"Caption",&d1_handler
CONTROL d1,@SYSBUTTON,"Button1",6,12,77,27,0x50010000,1024
CONTROL d1,@SYSBUTTON,"Button2",104,12,77,27,0x50010000,1025
CONTROL d1,@SYSBUTTON,"Button3",198,12,77,27,0x50010000,1026
Domodal(d1)
return
endsub


sub d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
g_menu = CreateMenu(true)
AppendMenu(g_menu, "context menu", 0, 1000)

CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK

CASE @IDCONTROL
if (((@CONTROLID & 0xFFF0) = 0x400) and (@NOTIFYCODE = BN_CONTEXTMENU))
POINT pt
_GetCursorPos(pt)
TrackPopupMenu(g_menu, 0, pt.x, pt.y, 0, d1.hwnd, 0)
endif
ENDSELECT
RETURN
ENDSUB


' returns 0 on failure
sub RegisterButtonSuperclass(),word
WNDCLASS wcl
_GetClassInfo(_hinstance, "button", wcl)
' save original handler address to pass to it unhandled messages
g_OldButtonProc = wcl.lpfnWndProc
' set new handler
wcl.lpfnWndProc = &MyButtonProc
wcl.hInstance = _hinstance
return _RegisterClass(wcl)
endsub


' new handler for all button controls
' detect it the mouse was right clicked, then send @IDCONTROL to owner
sub MyButtonProc(hwnd:UINT,uMsg:UINT,wParam:UINT,lParam:UINT),INT
if (uMsg = @IDRBUTTONDN)
WORD id
id = _GetWindowLong(hwnd, GWL_ID)
_SendMessage(_GetParent(hwnd), WM_COMMAND, (BN_CONTEXTMENU<<16)|id, hwnd)
return 0
endif
' other messages are unhandled
return _CallWindowProc(g_OldButtonProc,hwnd,uMsg,wParam,lParam)
endsub

barry

Thanks.  That looks like just what I need.  Not knowing much about GUI programming I have no idea how it works yet but I'll study it and that link and learn something.

Again, thanks,
Barry