Option Explicit
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Public WithEvents Worksheet As Worksheet
Private Sub WorkSheet_SelectionChange(ByVal Target As Range)
Dim lngArr As Variant
Dim Item As Variant
lngArr = Array(vbKeyUp, vbKeyDown, vbKeyLeft, vbKeyRight, vbKeyTab, vbKeyReturn _
, vbKeyHome, vbKeyEnd, vbKeyPageDown, vbKeyPageUp)
'\ check if any of the navigation keys are pressed
For Each Item In lngArr
'\ if so, skip the event handler
If CBool(GetAsyncKeyState(Item) And &H8000) Then
Exit Sub
End If
Next
'\ we got here means sheet has been navigated with the mouse
'\ so execute event handler
MsgBox "You Clicked Cell : " & Target.Address
'\do your stuff here ...
End Sub
Option Explicit
Dim colWorksheets_OnClick_ As Collection
Sub test()
Dim Sht As Worksheet
Dim objWorksheet_OnClick As clsWorksheet_OnClick
Set colWorksheets_OnClick_ = New Collection
For Each Sht In ThisWorkbook.Worksheets
Set objWorksheet_OnClick = New clsWorksheet_OnClick
Set objWorksheet_OnClick.Worksheet = Sht
colWorksheets_OnClick_.Add objWorksheet_OnClick
Next
Set objWorksheet_OnClick = Nothing
End Sub
Subclassing XL is something that i always try to avoid as it has a bad inpact on performance.
Here is a solution without having to Subclass the Application. It basically checks for the worksheet navigation keys state when a cell(s) is selected.
{snip}
is it possible to stop executing the code on right click?
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Long
Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" _
(lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, _
ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type MSG
hwnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As POINTAPI
End Type
Private Const WM_MOUSEMOVE = &H200
Private Const MK_RBUTTON = &H2
Private Const PM_NOREMOVE = &H0
Private Const PM_NOYIELD = &H2
Public WithEvents Worksheet As Excel.Worksheet
Private Sub WorkSheet_SelectionChange(ByVal Target As Range)
Dim lngArr() As Variant
Dim Item As Variant
Dim lngXLhWnd As Long
Dim mssg As MSG
lngArr = Array(vbKeyUp, vbKeyDown, vbKeyLeft, vbKeyRight, vbKeyTab, vbKeyReturn _
, vbKeyHome, vbKeyEnd, vbKeyPageDown, vbKeyPageUp)
'\ check if any of the navigation keys are pressed
For Each Item In lngArr
'\ if so, skip the event handler
If CBool(GetAsyncKeyState(Item) And &H8000) Then
Exit Sub
End If
Next
'\ ok, we got here it means the sheet has been navigated with the mouse
'\ so we are ready to execute the selection_change event handler.
'\ but first,let's find out which mouse button was clicked.
'\ get the XL app window handle
lngXLhWnd = FindWindow("XLMAIN", Application.Caption)
'\ check for the WM_MOUSEMOVE in the app window message queue
PeekMessage mssg, lngXLhWnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE + PM_NOYIELD
'\ if a WM_MOUSEMOVE is detected and the mouse right button
'\ wasn't down then proceed with your code
If mssg.message = WM_MOUSEMOVE And mssg.wParam <> MK_RBUTTON Then
MsgBox "You Clicked Cell(s) : " & Target.Address
End If
'\...do your stuff here ...
End Sub
Option Explicit
Dim colWorksheets_OnClick_ As Collection
Sub Test()
Dim Sht As Worksheet
Dim objWorksheet_OnClick As clsWorksheet_OnClick
Set colWorksheets_OnClick_ = New Collection
For Each Sht In ThisWorkbook.Worksheets
Set objWorksheet_OnClick = New clsWorksheet_OnClick
Set objWorksheet_OnClick.Worksheet = Sht
colWorksheets_OnClick_.Add objWorksheet_OnClick
Next
Set objWorksheet_OnClick = Nothing
End Sub
'__________________________________________________
Sub UnHookWorksheets()
Set colWorksheets_OnClick_ = Nothing
End Sub
Jaafar,
I am a novice as far as class modules are concerned. Can you help me with how to use this code please? I created a class module and copied the contents, as well as a regular module for the test sub. Nothing happens when i run the test macro.
regards
Raja
Subclassing XL is something that i always try to avoid as it has a bad inpact on performance.
Here is a solution without having to Subclass the Application. It basically checks for the worksheet navigation keys state when a cell(s) is selected.
If any of these keys is down, the Selection_Change event handler is simply skipped which means that the only time the event is triggered is when the a cell is selected with the mouse thus simulating a Mouse Click event.
I have wrapped the code in a Class for easy use.I named the class clsWorksheet_*******.
Here is a download showing a workbook whose worksheets were assigned to this Class: http://www.savefile.com/files/4179059
Here is the Class Code :
Here is a Test Procedure that uses the Class to hook all the worksheets in a Workbook :Code:Option Explicit Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer Public WithEvents Worksheet As Worksheet Private Sub WorkSheet_SelectionChange(ByVal Target As Range) Dim lngArr As Variant Dim Item As Variant lngArr = Array(vbKeyUp, vbKeyDown, vbKeyLeft, vbKeyRight, vbKeyTab, vbKeyReturn _ , vbKeyHome, vbKeyEnd, vbKeyPageDown, vbKeyPageUp) '\ check if any of the navigation keys are pressed For Each Item In lngArr '\ if so, skip the event handler If CBool(GetAsyncKeyState(Item) And &H8000) Then Exit Sub End If Next '\ we got here means sheet has been navigated with the mouse '\ so execute event handler MsgBox "You Clicked Cell : " & Target.Address '\do your stuff here ... End Sub
Place in a Standard Module:
Regards.Code:Option Explicit Dim colWorksheets_*******_ As Collection Sub test() Dim Sht As Worksheet Dim objWorksheet_******* As clsWorksheet_******* Set colWorksheets_*******_ = New Collection For Each Sht In ThisWorkbook.Worksheets Set objWorksheet_******* = New clsWorksheet_******* Set objWorksheet_*******.Worksheet = Sht colWorksheets_*******_.Add objWorksheet_******* Next Set objWorksheet_******* = Nothing End Sub