how to catch mouse event in a grid ?

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

User avatar
srvet_claudio
Posts: 2193
Joined: Thu Feb 25, 2010 8:43 pm
Location: Uruguay
Contact:

how to catch mouse event in a grid ?

Post by srvet_claudio »

Pablo César wrote:
srvet_claudio wrote:Pablo now I think I understand your demo, a Grid with Keyboard or Mouse, but not both at once.
Add in your code:

CREATE EVENT PROCNAME Check_Event_ByPass() HwND form_1.GRID_1.HANDLE STOREINDEX nIndex
EventProcessAllHookMessage (nIndex, .T.)
Casi, casi, pero todavia sin suceso. :(

Claudio, fijese que en mi ejemplo (utilize mi demo ejecutable) y verá que todos los eventos que fueron definidos en el demo son exibidos en el StatuBar:

- key_up
- key_down
- Mouse wheel
- Mouse move
- Mouse lbtn Down
- Mouse Rbtn Down

Claro, que tendrá que clicar en el CheckBox. Pero funcionan aparentemente normal, inclusive mouse e keyboard events.

Con su indicación de colocar: EventProcessAllHookMessage (nIndex, .T.) funcionó en partes, pero tiene comportamiento diferente al que fué indicado por jpp de adicionar:

Code: Select all

*-- Deb Jpp
      ELSEIF AT("BYPASS", UPPER( EventGetPROCNAME (nIndex))) > 0
          lProcessMessage := .T.
*-- Fin Jpp
Porque el CheckBox alterna el valor pre-definido en mi funcion Check_Event_ByPass() para que retorne al contrário.
Pablo,
sinceramente no me doy cuenta de la diferencia entre tu demo.exe y el creado con EventProcessAllHookMessage (nIndex, .T.),
fíjate que ambos fuerzan que se procese todos los mensajes de Windows para el procedure especificado en CREATE EVENT, obviamente el de Jpp solo si el procedure posee la palabra Bypass en su nombre:

Code: Select all

      
      lProcessMessage := .F.
      IF EventProcessAllHookMessage (nIndex) == .T.
         lProcessMessage := .T.
      ELSEIF EventProcessHMGWindowsMessage (nIndex) == .T. .AND. IsHMGWindowsMessage == .T.
         lProcessMessage := .T.
      ELSEIF EventProcessKeyboardMessage   (nIndex) == .T. .AND. IsKeyboardMessage   == .T.
         lProcessMessage := .T.
      *-- Deb Jpp
      ELSEIF AT("BYPASS", UPPER( EventGetPROCNAME (nIndex))) > 0
          lProcessMessage := .T.
      *-- Fin Jpp      
      ENDIF
Best regards.
Dr. Claudio Soto
(from Uruguay)
http://srvet.blogspot.com
User avatar
Pablo César
Posts: 4059
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil

how to catch mouse event in a grid ?

Post by Pablo César »

srvet_claudio wrote:Pablo,
sinceramente no me doy cuenta de la diferencia entre tu demo.exe y el creado con EventProcessAllHookMessage (nIndex, .T.)
Tienes razón, Claudio. Disculpame, no sé lo que yo habia hecho, que me habia dado resultado distinto. Pero ahora veo que funcionan las dos formas iguales, falla mia (perdón). Entonces no hay necesidad de cambiar el source de h_windows.prg. Gracias por tu esclarecimiento. :)

Re-edicté mensajes para que no haya confusion y en cambio estoy confirmando con Rathinagiri:
Rathinagiri wrote:Thanks for explaining Claudio. So, it is already implemented.
Yes Rathinagiri, Mr. Claudio is right. Do not need to make changes at h_windows.prg for this propose. For changing lib source by suggestion of jpp, we can replace with just adding this line after EVENT creation:

EventProcessAllHookMessage (nIndex, .T.)

Please note my demo re-done with new instructions without any changing at hmg lib:

Code: Select all

#include <hmg.ch>

#define DO_EVENT    Nil
#define NO_EVENT    1

#define WM_MOUSEMOVE      512    // 0x0200      // ok
#define WM_LBUTTONDOWN    513    // 0x0201      // ok
#define WM_LBUTTONUP      514    // 0x0202      // ok

#define WM_RBUTTONDOWN    516    // 0x0204      // ok
#define WM_RBUTTONUP      517    // 0x0205      // ok
#define WM_MOUSEWHEEL     522    // 0x020A      // ok

Function Main
Private cMsg

DEFINE WINDOW Form_1 ;
    AT 0,0 ;
    WIDTH 430 ;
    HEIGHT 500 ;
    TITLE 'Demo Events - EventProcessAllHookMessage' ;
    MAIN NOSIZE
    
    DEFINE STATUSBAR FONT "Courier New" SIZE 9
        STATUSITEM PadC("",75)
    END STATUSBAR
    
    @ 10,10 GRID Grid_1 ;
        WIDTH 400 ;
        HEIGHT 330 ;
        HEADERS {'Column 1','Column 2','Column 3'} ;
        WIDTHS {120,120,120} ;
        VIRTUAL ;
        CELLNAVIGATION ;
        ITEMCOUNT 1000 ;
        ON QUERYDATA QueryTest()
    
    @ 360, 50 CHECKBOX Check_1 CAPTION 'Switch behaviour' WIDTH 150
    
    @ 360, 250 TEXTBOX Text_1 ;
        VALUE "" ;
        TOOLTIP 'Just Setting Focus and test'
        
    @ 400,10 LABEL Label_1 VALUE "Test with: keys Down and Up | Mouse Wheel | Mouse Left Btn | Mouse Right Btn" WIDTH 400 HEIGHT 20 FONT 'Arial' SIZE 8
    
    @ 420,60 LABEL Label_2 VALUE "Mouse moving | Switch Check Box | Set Focus in TextBox" WIDTH 400 HEIGHT 20 FONT 'Arial' SIZE 8
    
END WINDOW
CREATE EVENT PROCNAME Check_Grid_Events() HWND Form_1.Grid_1.HANDLE STOREINDEX nIndex
EventProcessAllHookMessage (nIndex, .T.)

// CREATE EVENT PROCNAME Check_Event_Form() 
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
Return Nil

Function Check_Event_Form()
Local WM_:=EventMSG()

IF EventHWND() == Form_1.HANDLE
   DO CASE
      CASE WM_ == WM_KEYDOWN
           msgbox("key_down")
      CASE WM_ == WM_MOUSEWHEEL
           msgbox("Mouse wheel")
      CASE WM_ == WM_LBUTTONDOWN
           msgbox("Mouse lbtn Down")
      CASE WM_ == WM_RBUTTONDOWN 
           msgbox("Mouse Rbtn Down")
   ENDCASE
ENDIF
Return Nil

Function Check_Grid_Events()
Local nMsg := EventMsg()
Local xRet := DO_EVENT

DO CASE
   CASE nMsg == WM_KEYUP
        cMsg:="key_up"
        xRet:=NO_EVENT
   CASE nMsg == WM_KEYDOWN
        cMsg:="key_down"
        xRet:=NO_EVENT
   CASE nMsg == WM_MOUSEWHEEL
        cMsg:="Mouse wheel"
        xRet:=NO_EVENT
   CASE nMsg == WM_MOUSEMOVE
        cMsg:="Mouse move"
        xRet:=NO_EVENT
   CASE nMsg == WM_LBUTTONDOWN
        cMsg:="Mouse lbtn Down"
   CASE nMsg == WM_RBUTTONDOWN 
        cMsg:="Mouse Rbtn Down"
ENDCASE
If GetProperty("Form_1","Check_1","Value")=.T.
   xRet:=If(xRet==DO_EVENT,NO_EVENT,DO_EVENT)
Endif
Form_1.StatusBar.Item(1):=cMsg
Return xRet

Procedure QueryTest()
This.QueryData := Str ( This.QueryRowIndex ) + ',' + Str ( This.QueryColIndex )
Return Nil
Thanks to Claudio and jpp for this management of events which help us to elaborate this demo. :)
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
User avatar
srvet_claudio
Posts: 2193
Joined: Thu Feb 25, 2010 8:43 pm
Location: Uruguay
Contact:

Re: how to catch mouse event in a grid ?

Post by srvet_claudio »

Pablo César wrote:Tienes razón, Claudio. Disculpame, no sé lo que yo habia hecho, que me habia dado resultado distinto. Pero ahora veo que funcionan las dos formas iguales, falla mia (perdón). Entonces no hay necesidad de cambiar el source de h_windows.prg. Gracias por tu esclarecimiento.
Ok, Pablo no hay problema.
Best regards.
Dr. Claudio Soto
(from Uruguay)
http://srvet.blogspot.com
Javier Tovar
Posts: 1275
Joined: Tue Sep 03, 2013 4:22 am
Location: Tecámac, México

Re: how to catch mouse event in a grid ?

Post by Javier Tovar »

Gracias a todos por compartir. Bonita aplicación! :D
User avatar
Pablo César
Posts: 4059
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil

how to catch mouse event in a grid ?

Post by Pablo César »

mol wrote:Could you do not mix english and spanish?
FREE COMUNICATION.
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
User avatar
Pablo César
Posts: 4059
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil

How to catch mouse event in a grid ?

Post by Pablo César »

Thanks to Jean Pierre (Nick name: jpp) and Claudio implementations, I could make it a better example:

Code: Select all

/*
   Grid Events Demo
   Demo1.prg - Right click identification for each Grid column
   Enhanced by Pablo César Arrascaeta
   On March 7th, 2015
*/

#include <hmg.ch>

#define DO_EVENT    Nil
#define NO_EVENT    1

Function Main()
Private cMsg, aRows [21] [3]

aRows  [1]  := {'Simpson',  'Homer',    '555-5555'}
aRows  [2]  := {'Mulder',   'Fox',      '324-6432'} 
aRows  [3]  := {'Smart',    'Max',      '432-5892'} 
aRows  [4]  := {'Grillo',   'Pepe',     '894-2332'} 
aRows  [5]  := {'Kirk',     'James',    '346-9873'} 
aRows  [6]  := {'Barriga',  'Carlos',   '394-9654'} 
aRows  [7]  := {'Flanders', 'Ned',      '435-3211'} 
aRows  [8]  := {'Smith',    'John',     '123-1234'} 
aRows  [9]  := {'Pedemonti','Flavio',   '000-0000'} 
aRows [10]  := {'Gomez',    'Juan',     '583-4832'} 
aRows [11]  := {'Fernandez','Raul',     '321-4332'} 
aRows [12]  := {'Borges',   'Javier',   '326-9430'} 
aRows [13]  := {'Alvarez',  'Alberto',  '543-7898'} 
aRows [14]  := {'Gonzalez', 'Ambo',     '437-8473'} 
aRows [15]  := {'Batistuta','Gol',      '485-2843'} 
aRows [16]  := {'Vinazzi',  'Amigo',    '394-5983'} 
aRows [17]  := {'Pedemonti','Flavio',   '534-7984'} 
aRows [18]  := {'Samarbide','Armando',  '854-7873'} 
aRows [19]  := {'Pradon',   'Alejandra','???-????'} 
aRows [20]  := {'Reyes',    'Monica',   '432-5836'} 
aRows [21]  := {'Fernández','Vicente',  '000-0000'}

DEFINE WINDOW Form_1 ;
    AT 0,0 ;
    WIDTH 430 ;
    HEIGHT 500 ;
    TITLE 'Grid Events Demo - EventProcessAllHookMessage' ;
    MAIN NOSIZE
    
    DEFINE STATUSBAR FONT "Courier New" SIZE 9
        STATUSITEM PadC("",75)
    END STATUSBAR
    
    @ 10,10 GRID Grid_1 ;
        WIDTH 400 ;
        HEIGHT 330 ;
        HEADERS {'Column 1','Column 2','Column 3'} ;
        WIDTHS {120,120,120} ;
		ITEMS aRows ;
        VALUE 1 ;
        CELLNAVIGATION
    
    @ 360, 50 CHECKBOX Check_1 CAPTION 'Switch behaviour' WIDTH 150 VALUE .T.
    
    @ 360, 250 TEXTBOX Text_1 ;
        VALUE "" ;
        TOOLTIP 'Just Setting Focus and test'
        
    @ 400,10 LABEL Label_1 VALUE "Test with: keys Down and Up | Mouse Wheel | Mouse Left Btn | Mouse Right Btn" WIDTH 400 HEIGHT 20 FONT 'Arial' SIZE 8
    
    @ 420,60 LABEL Label_2 VALUE "Mouse moving | Switch Check Box | Set Focus in TextBox" WIDTH 400 HEIGHT 20 FONT 'Arial' SIZE 8
    
END WINDOW
CREATE EVENT PROCNAME Check_Grid_Events() HWND Form_1.Grid_1.HANDLE STOREINDEX nIndex
EventProcessAllHookMessage (nIndex, .T.)

// CREATE EVENT PROCNAME Check_Event_Form() 
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
Return Nil

Function Check_Event_Form()
Local WM_:=EventMSG()

IF EventHWND() == Form_1.HANDLE
   DO CASE
      CASE WM_ == WM_KEYDOWN
           msgbox("key_down")
      CASE WM_ == WM_MOUSEWHEEL
           msgbox("Mouse wheel")
      CASE WM_ == WM_LBUTTONDOWN
           msgbox("Mouse lbtn Down")
      CASE WM_ == WM_RBUTTONDOWN 
           msgbox("Mouse Rbtn Down")
   ENDCASE
ENDIF
Return Nil

Function Check_Grid_Events()
Local nMsg := EventMsg()
Local xRet := DO_EVENT
Local aCell

DO CASE
   CASE nMsg == WM_KEYUP
        cMsg:="key_up"
        xRet:=NO_EVENT
   CASE nMsg == WM_KEYDOWN
        cMsg:="key_down"
        xRet:=NO_EVENT
   CASE nMsg == WM_MOUSEWHEEL
        cMsg:="Mouse wheel"
        xRet:=NO_EVENT
   CASE nMsg == WM_MOUSEMOVE
        cMsg:="Mouse move"
        xRet:=NO_EVENT
   CASE nMsg == WM_LBUTTONDOWN
        cMsg:="Mouse lbtn Down"
   CASE nMsg == WM_RBUTTONDOWN 
        cMsg:="Mouse Rbtn Down"
		aCell:=GetCellClicked("Form_1","Grid_1")
		SetProperty("Form_1","Grid_1","Value",aCell)
		MsgInfo("Right-Clicked on Column "+AllTrim(Str(aCell[2])))
ENDCASE
If GetProperty("Form_1","Check_1","Value")=.T.
   xRet:=If(xRet==DO_EVENT,NO_EVENT,DO_EVENT)
Endif
Form_1.StatusBar.Item(1):=cMsg
Return xRet

Function GetCellClicked(cForm,cControl)
Local aRet, nIndex:=GetControlIndex(cControl,cForm)
Local aCellData:=_GetGridCellData(nIndex)

aRet:={aCellData[1],aCellData[2]}
Return aRet
This example can ilustrate how events can be so helpful for us. Of course this code could it get better.
But there is an extra feature to get CellClicked on Right-Button in the grid.
Screen1.png
Screen1.png (135.31 KiB) Viewed 4359 times
I hope be useful ! :D
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
User avatar
Pablo César
Posts: 4059
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil

How to catch mouse event in a grid ?

Post by Pablo César »

After identifying with Right-Button clicked on Grid column, it's easy to implement personalized ContextMenu:

Code: Select all

/*
   Grid Events Demo
   Demo2.prg - ContextMenu and ToolTip for each Grid column
   Enhanced by Pablo César Arrascaeta
   On March 7th, 2015
*/

#include <hmg.ch>

Function Main()
Private cMsg, aRows [21] [3]

aRows  [1]  := {'Simpson',  'Homer',    '555-5555'}
aRows  [2]  := {'Mulder',   'Fox',      '324-6432'} 
aRows  [3]  := {'Smart',    'Max',      '432-5892'} 
aRows  [4]  := {'Grillo',   'Pepe',     '894-2332'} 
aRows  [5]  := {'Kirk',     'James',    '346-9873'} 
aRows  [6]  := {'Barriga',  'Carlos',   '394-9654'} 
aRows  [7]  := {'Flanders', 'Ned',      '435-3211'} 
aRows  [8]  := {'Smith',    'John',     '123-1234'} 
aRows  [9]  := {'Pedemonti','Flavio',   '000-0000'} 
aRows [10]  := {'Gomez',    'Juan',     '583-4832'} 
aRows [11]  := {'Fernandez','Raul',     '321-4332'} 
aRows [12]  := {'Borges',   'Javier',   '326-9430'} 
aRows [13]  := {'Alvarez',  'Alberto',  '543-7898'} 
aRows [14]  := {'Gonzalez', 'Ambo',     '437-8473'} 
aRows [15]  := {'Batistuta','Gol',      '485-2843'} 
aRows [16]  := {'Vinazzi',  'Amigo',    '394-5983'} 
aRows [17]  := {'Pedemonti','Flavio',   '534-7984'} 
aRows [18]  := {'Samarbide','Armando',  '854-7873'} 
aRows [19]  := {'Pradon',   'Alejandra','???-????'} 
aRows [20]  := {'Reyes',    'Monica',   '432-5836'} 
aRows [21]  := {'Fernández','Vicente',  '000-0000'}

DEFINE WINDOW Form_1 ;
    AT 0,0 ;
    WIDTH 426 ;
    HEIGHT 395 ;
    TITLE 'Grid Events Demo - ContextMenu for each column' ;
    MAIN NOSIZE
	
	DEFINE STATUSBAR FONT "Courier New" SIZE 9
        STATUSITEM PadC("",75)
    END STATUSBAR
    
    @ 10,10 GRID Grid_1 ;
        WIDTH 400 ;
        HEIGHT 330 ;
        HEADERS {'Column 1','Column 2','Column 3'} ;
        WIDTHS {120,120,120} ;
		TOOLTIP "ToolTip for Grid" ;
		ON CHANGE Define_Column_ToolTip("Form_1","Grid_1") ;
		ITEMS aRows ;
        VALUE {1,1} ;
        CELLNAVIGATION
    
	Define_Control_Context_Menu("Form_1","Grid_1",1) // Needs to start definition for this control
	
END WINDOW
// CREATE EVENT PROCNAME Check_Grid_Events HWND Form_1.Grid_1.HANDLE
SET CONTROL Grid_1 OF Form_1 ONMOUSEEVENT Check_Grid_Events()
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
Return Nil

Function Check_Grid_Events()
Local aCell, nMsg := EventMsg()
Static cCtrlSelected:=""

If nMsg == WM_RBUTTONDOWN
   aCell:=GetCellClicked("Form_1","Grid_1")
   SetProperty("Form_1","Grid_1","Value",aCell)
   Define_Control_Context_Menu("Form_1","Grid_1",aCell[2])
Endif
Return Nil

Function GetCellClicked(cForm,cControl)
Local aRet, nIndex:=GetControlIndex(cControl,cForm)
Local aCellData:=_GetGridCellData(nIndex)

aRet:={aCellData[1],aCellData[2]}
Return aRet

Function Define_Control_Context_Menu(cParentForm,cControl,nColumn)
If IsControlContextMenuDefined( cControl, cParentForm )
   ReleaseControlContextMenu( cControl, cParentForm )
Endif
Do Case
   Case nColumn=1
        DEFINE CONTROL CONTEXTMENU &cControl OF &cParentForm
            ITEM "Option 1 (Column 1)" ACTION MsgInfo("Grid Column 1 | Option 1")
            ITEM "Option 2 (Column 1)" ACTION MsgInfo("Grid Column 1 | Option 2")
            ITEM "Option 3 (Column 1)" ACTION MsgInfo("Grid Column 1 | Option 3")
        END MENU
   Case nColumn=2
        DEFINE CONTROL CONTEXTMENU &cControl OF &cParentForm
            ITEM "Option 1 (Column 2)" ACTION MsgInfo("Grid Column 2 | Option 1")
            ITEM "Option 2 (Column 2)" ACTION MsgInfo("Grid Column 2 | Option 2")
            ITEM "Option 3 (Column 2)" ACTION MsgInfo("Grid Column 2 | Option 3")
        END MENU
   Case nColumn=3
        DEFINE CONTROL CONTEXTMENU &cControl OF &cParentForm
            ITEM "Option 1 (Column 3)" ACTION MsgInfo("Grid Column 3 | Option 1")
            ITEM "Option 2 (Column 3)" ACTION MsgInfo("Grid Column 3 | Option 2")
            ITEM "Option 3 (Column 3)" ACTION MsgInfo("Grid Column 3 | Option 3")
        END MENU
EndCase
Return Nil

Function Define_Column_ToolTip(cParentForm,cControl)
Local nColumn:=GetProperty(cParentForm,cControl,"CellColFocused")

Do Case
   Case nColumn=1
        _SetToolTip(cControl,cParentForm,"ToolTip Column 1")
   Case nColumn=2
        _SetToolTip(cControl,cParentForm,"ToolTip Column 2")
   Case nColumn=3
        _SetToolTip(cControl,cParentForm,"ToolTip Column 3")
EndCase
Return Nil
I've included a personalized ToolTip for each column of grid too. It's not the best way, but at least I got something to show. I make this thru ON CHANGE event.

It's look like this:
Screen4.png
Screen4.png (55.81 KiB) Viewed 4337 times
I hope be useful too ! :D
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
User avatar
serge_girard
Posts: 3165
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: How to catch mouse event in a grid ?

Post by serge_girard »

Great !

Serge
There's nothing you can do that can't be done...
EduardoLuis
Posts: 682
Joined: Tue Jun 04, 2013 6:33 pm
Location: Argentina

Re: How to catch mouse event in a grid ?

Post by EduardoLuis »

Hi Pablo Cesar:

Excellent and very usefull. Thanks for share.-
Eduardo
Post Reply