GetCursorPos(...) in Access

I have this code to move the mouse pointer to a desired location on a form (I think):

Private Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long
using:

Call SetCursorPos 100,45 ' for example.

Now, I need similar function to return X, and Y value of the mouse pointer where ever it might be on the form. I am looking for GetCursorPos(...)

Thanks.
LVL 34
Mike EghtebasDatabase and Application DeveloperAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rockiroadsCommented:
something like this perhaps?
http://www.freevbcode.com/ShowCode.Asp?ID=1120

Option Explicit

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Public Function GetXCursorPos() As Long
   Dim pt As POINTAPI
   GetCursorPos pt
   GetXCursorPos = pt.X
End Function

Public Function GetYCursorPos() As Long
   Dim pt As POINTAPI
   GetCursorPos pt
   GetYCursorPos = pt.Y
End Function


0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Now, I guess all I need to do is:

Debug.Print  "x= " & GetXCursorPos()  & ", y= " & GetYCursorPos

I am testing although your solution don't need to be tested.

Mike
0
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
"I have this code to move the mouse pointer to a desired location on a form"

When using GetCursorPos() and SetCursorPos(), remember that you are working with SCREEN coordinates.

If you need convert Form cooordinates to Screen coords then use:

    Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

and the oppositie would be:

    Private Declare Function ScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
0
10 Tips to Protect Your Business from Ransomware

Did you know that ransomware is the most widespread, destructive malware in the world today? It accounts for 39% of all security breaches, with ransomware gangsters projected to make $11.5B in profits from online extortion by 2019.

Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Idle_Mind,

What a pleasure to hear from you. Year 2004, I learned a lot from you with my VB questions.

Conversion issue was one of the points I was strugling with just now.  your post will be helpfull in that regard.

Another issue I am dealing with is to find left position of the form. In VB, I have used me.left but it seems not working in Access.

FYI: What I am tying to do to detect (in the form timer event) if the user has the cursor on a certain button:

    If (GetXCursorPos >= cmdStop.Left And GetXCursorPos <= (cmdStop.Left + cmdStop.Width)) Then And _
    (GetYCursorPos <= cmdStop.Top And GetYCursorPos >= (cmdStop.Top + cmdStop.Height)) Then
        bolStop = True
        cmdStop.SetFocus
    Else
        bolStop = False
    End If

Of course, I need yet to include form's .left and .top property in the code.

Thank you to both my favorite experts.

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Background: variable bolStop is set to control the code used to print files. By holding/clicking cmdStop, user is able to stop print process.

At a later question I will post, I would try to send a commant to the printer to cancle all print jobs from a specific user (to cancle all print jobs qued to be printed). I am not sure whether such action is possible or not.

Regards,

Mike
0
EDDYKTCommented:
? should you just trap the mousemove event?
0
rockiroadsCommented:
Hi Mike, I went offline after I posted but I see what you are trying to do

idle mind, I didnt know about that api, now I do, thanks

If u just want to capture the position of a mouse to see if its over a certain control then I think the answer from EDDYKT would solve that for you

cmdstop_mousemove  is called whenever the mouse is moved over that button
u may want to handle users using the keyboard as well? so perhaps u also need to check for cmdstop_gotfocus as well
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
re:> ? should you just trap the mousemove event?

Maybe. I am not sure. The reason for my uncertainty is while cpu is engaged running the print routine, why all of sudden a mouse move would be recognized (fire) in middle the print routine. I suspect it will come to it when the print routine is finished which to late then.

I am not even sure the print routine would allow timer to fire either. Then again I could test it to see how each behaves.

brb,

Mike
0
rockiroadsCommented:
your print job, surely its just a case of you issuing it. You dont wait for that proces to end surely. One would assume u issue the command and revert focus back to access.
U could disable any buttons prior to call to print and renable them after print if that is what u are worried about
0
rockiroadsCommented:
no, its stop print u want eh
oh
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Test results:


Timer event fires: 4/10/2007 8:57:18 AM
Timer event fires: 4/10/2007 8:57:19 AM
Timer event fires: 4/10/2007 8:57:19 AM
Timer event fires: 4/10/2007 8:57:20 AM

Print started at: 4/10/2007 8:57:20 AM

Timer event fires: 4/10/2007 8:57:20 AM
Timer event fires: 4/10/2007 8:57:21 AM
Timer event fires: 4/10/2007 8:57:21 AM
Timer event fires: 4/10/2007 8:57:22 AM

Print finished at: 4/10/2007 8:57:31 AM

Although I clicked on cmdStop quickly right after clicking on cmdStop, it kept these two events (cmdStop_MouseMove and cmdStop_GotFocus) to fire after it was done printing.

cmdStop_MouseMove fires at: 4/10/2007 8:57:31 AM
cmdStop_GotFocus fires at: 4/10/2007 8:57:31 AM
cmdStop_MouseMove fires at: 4/10/2007 8:57:31 AM
Timer event fires: 4/10/2007 8:57:31 AM
Timer event fires: 4/10/2007 8:57:32 AM

But timer event fired without DoEvents or something else.

This is the reason why I though I have to use timer to check if the pointer is within cmdStop's boundry.

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
correction...

Although I clicked on cmdStop quickly right after clicking on cmdPrint, it kept these two events (cmdStop_MouseMove and cmdStop_GotFocus) to fire after it was done printing.
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
re:> your print job, surely its just a case of you issuing it. You dont wait for that proces to end surely.

My code cycles through files selected and prints them one at a time. If I have 12 files selected and the timer sets bolStop = True and my print routine has:

If bolStop = True Then
   now print
Else
  MsgBox "Print job is cancled by user."
  Exit Sub
End If

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
I am not sure how to apply code from Idle_Mind:

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Private Declare Function ScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

to my code:

Private Sub Form_Timer()

    Dim intX As Long        ' x-position of the cursor
    Dim intY As Long        ' y-position of the cursor
   
    Dim intLeft As Long     ' left of smdStop
    Dim intRight As Long    ' right of smdStop
   
    Dim intTop As Long      ' top of smdStop
    Dim intBottom As Long   ' bottom of smdStop
   
    intX = GetXCursorPos
    intY = GetYCursorPos
   
    intLeft = cmdStop.Left
    intRight = cmdStop.Left + cmdStop.Width
   
    intTop = cmdStop.Top
    intBottom = cmdStop.Top + cmdStop.Height
   
    If (intX >= intLeft And intX <= intRight) And _
       (intY <= intTop And intY >= intBottom) Then
       
            bolStop = True
            cmdStop.SetFocus
            DoEvents
    Else
        bolStop = False
    End If

End Sub

to make it work. Also I am not quite sure about:

...  (intY <= intTop And intY >= intBottom) Then

portion.

Thank you,

Mike
0
jefftwilleyCommented:
Hey Mike...

Read this thread over. I helped this guy with positioning his mouse.

http://www.experts-exchange.com/Microsoft/Development/MS_Access/Access_Coding-Macros/Q_22452987.html
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
jefftwilley,

I have a good solution here. What I need a bit help to make it work that is if you have a moment to make sense of my last post.

Mike
0
jefftwilleyCommented:
No time tonight...let me tackle it again in the morning.
J
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Thanks.
0
jefftwilleyCommented:
Mike,
I've had time this morning to read through your posts...and here's what I think.

I also have a process...mine involves importing and exporting though...but I'm still simply looping through and starting processes. There can be up to 20 or 30 of them. I use a method similar to this one

If bolStop = True Then
   now print
Else
  MsgBox "Print job is cancled by user."
  Exit Sub
End If

However...because the button click itself isn't actually recognized until my process finishes and tries to start the next item in the loop...I too am forced to wait for that ONE import/export to finish.

While designing and testing this particular process, I too thought there had to be a way to stop it immediately...and issuing a BREAK did at times cancel the process....but often times, that had unpredictable results.

I understand that you're trying to create a predictive process...where by you are relying on a big assumption, that IF your user's mouse is hovering over the CANCEL button, then he must be about to press it. I don't think that's good practice.

In theory, you can issue your mouse to move...you can gain it's coordinates in a timer event, but you're still within a process, that when cancelled, could quite possibly error out and bypass your exit routine within your code.

This can...will leave recordsets open, file handles open, etc...and probably orphan a print job that you'll have to manually cancel.

Convince me that my points have all been taken into consideration, and that you have it under control, and I too would love to have this function that handles a situation I too have been in....and opted for a more Code friendly answer to.

I'll play with this..get it working...but I won't know how to apply it to cancel your print job. I'm assuming you have that handled?
J
0
rockiroadsCommented:
Mike, instead of worrying about the cursor position, what if u used a global variable (well global to the form) and the mousemove events of detail and cmdStop

dim m_bOnStopBtn as boolean

private sub form_load()
    m_bOnStopBtn = False
end sub

Private Sub Detail_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    m_bOnStopBtn = False
end sub

Private Sub cmdStop_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    m_bOnStopBtn = True
end sub


then perhaps use m_bOnStopBtn to determine whether to kick off other events or not

eg

private sub form_timer()
    if m_bOnStopBtn = True then
          'do what u need to if cursor on stopbtn
    else
          'etc
    end if
end sub
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
rockiroads,

I guess you haven't read one of my earlier post on "Test results:"


Timer event fires: 4/10/2007 8:57:18 AM
Timer event fires: 4/10/2007 8:57:19 AM
Timer event fires: 4/10/2007 8:57:19 AM
Timer event fires: 4/10/2007 8:57:20 AM

If you do, you would see mouse move cannot be activated (fired) during the print process.

Please help me with my last post which starts with:

"I am not sure how to apply code from Idle_Mind:

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Private Declare Function ScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
.
."

Thanks.

Now, I am reading the posts from Jeff.

Mike

0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
jefftwilley,

In my case, the Timer is able to fire and change the value of bolStop from True to False and visa versa. And, my print routine involves reading some file names from a list box. Using the code below:

If bolStop = True Then
   now print
Else
  MsgBox "Print job is cancled by user."
  Exit Sub
End If

if bolStop = True it will print. And once the print code is executed there is no way to undo it (at least for now. I will discuss this further later on with you).

So, there will be no files left open or orphan. The only point is I am dealing with buton left, form left and cursor position using code from Idle_Mind.

Unfortunately, I am not how to bring all together. But, I will eventually will be able to accomplish this task.
=======
Future quest:
Scenario: 10 files are sent to the printer and at this moment the printer is printing file 3 of 10.

User moves the mouse to Panic or Stop Print button. Usere resets bolStop to True when the next file (the 11th file) is being processed.

If bolStop = True Then
   now print
Else
  MsgBox "Print job is cancled by user."
  CancelAllPrintJobsInThePrinter
  Exit Sub
End If

Routine like "CancelAllPrintJobsInThePrinter" might be possible may be not.

If we have only 10 files to print, means now after 10th file is available to be clicked on and it responds to mouse move also.

Now, the idea is to accomplish the first phase of it (post starting:

"I am not sure how to apply code from Idle_Mind:

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Private Declare Function ScreenToClient Lib "user32" Alias "ScreenToClient" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
.
.")

Mike

0
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Working...standby.
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Thank you very much.

Mike
0
rockiroadsCommented:
Mike, I tried to get this going but couldnt quite get the right coordinates
Its almost perfect for X (top) but I couldnt quite get left (Y) working

this is the module code

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Public Function GetXCursorPos(ByVal lHwnd As Long) As Long
   Dim pt As POINTAPI
   GetCursorPos pt
   ScreenToClient lHwnd, pt
   GetXCursorPos = pt.X
End Function

Public Function GetYCursorPos(ByVal lHwnd As Long) As Long
   Dim pt As POINTAPI
   GetCursorPos pt
   ScreenToClient lHwnd, pt
   GetYCursorPos = pt.Y
End Function


and in the form, I call GetXCursorPos/GetYCursorPos by passing in Me.hwnd
eg
GetXCursorPos(Me.hwnd)
GetYCursorPos(Me.hwnd)

I created a sample form, one button (cmdStop), two labels (lblCurrPos, lblCmdPos)
lblCmdPos shows values of cmdStop (left,top,height,width)
lblCurrPos shows current cursor position

i.e.

Private Sub Form_Load()
    Me.lblCmdPos.Caption = "T=" & cmdStop.Top & ", L=" & cmdStop.Left & ", W=" & cmdStop.width & ", H=" & cmdStop.height
End Sub

Private Sub cmdStop_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Me.lblCurrPos.Caption = "on mouse"
End Sub

Private Sub Detail_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Me.lblCurrPos.Caption = "X=" & GetXCursorPos(Me.hwnd) & ", Y=" & GetYCursorPos(Me.hwnd)
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Me.lblCurrPos.Caption = "X=" & GetXCursorPos(Me.hwnd) & ", Y=" & GetYCursorPos(Me.hwnd)
End Sub



But Im thinking about this and still not sure if these events can also be captured during the print process. Is it because the print process has all the cpu time, not sure.
0
rockiroadsCommented:
Im gonna have another play, try to match coordinates correctly. Will have to do this 2morrow now
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Thank you rockiroads for the time.

Re:>Is it because the print process has all the cpu time, not sure.

By looking to my test resluts from the previous posts, despit the fact print process (or better to say print process of may small files) starts at:

Print started at: 4/10/2007 8:57:20 AM

the form timer fires after print has started:

Timer event fires: 4/10/2007 8:57:20 AM

and befor print finishes at:

Print finished at: 4/10/2007 8:57:31 AM
============
Now, when the user moves the mouse to Panic or Stop Print button while code is in the process of printing the value of bolStop will change to True according my test results.  If the code is in the process of printing say 100 files one at a time and before printing each file checks the value of bolStop:

If bolStop = True Then
   'continue printing current file
Else
  MsgBox "Print job is cancled by the user."
  CancelAllPrintJobsInThePrinter
  Exit Sub
End If

Routine like "CancelAllPrintJobsInThePrinter" might be possible may be not. It is considered possibly to chase the print jobs to the printer and cancled these qued files inside the printer waiting to be printed.

As I said, this is the overkill I am hoping to address later on. Plan A is to stop sending to the printer when user moves the cursor over the panic button (or cmdStop). Plan B is to develope routine like CancelAllPrintJobsInThePrinter to stop print jobs already in the printer.

Regards,

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
rockiroads,

I coppied your code and created what you have described in your last post. For clarity, I cahnged following code only:

Private Sub Form_Load()
    Me.lblCmdPos.Caption = "Y1=" & cmdStop.Top & ", Y2=" & cmdStop.Top + cmdStop.Height & " , X1=" & cmdStop.Left & ", X2=" & cmdStop.Left + cmdStop.Width
End Sub

It works now!  I need still study it a bit but it works.

Thank you.

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
rockiroads and Idle_Mind,

Rocky's code on the test form (when no printing taking places) work fine, but it doesn't let Time fire. I move the form's MouseMove event to:

Private Sub Form_Timer()
' this event never fires
    Me.lblCurrPos.Caption = "X=" & GetXCursorPos(Me.hwnd) & ", Y=" & GetYCursorPos(Me.hwnd)
    DoEvents
    Me.Repaint
   ' this never takes place----v
   If lblCurrPos.Caption = "on mouse" Then
        bolStop = True
   Else
        'bolStop = False
   End If

End Sub
=========
Is there a way we avoid to use such a indirect response:

If lblCurrPos.Caption = "on mouse" Then

In direct because lblCurrPos first need to be set to "on mouse" and then our code have some chance to works.

Or, instead of setting its caption to "on mouse", why we cannot set bolStop to True?

Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
I gave up.

Thank you to all.  My last atempt was to create another Panic.mdb with a single button (cmdStop) to change the value of TestVal (yes/no field) in a table tTest in this database. And, include the following code in the print module mdb. It read the setting from Panic.mdb okay but it doesn't fire when it is printing (despit my earlier test results). Here is the code:

Private Sub Form_Timer()
   
    If bolStop = False Then
        DoEvents
        Dim dbsNorthwind As Database
        Dim conPubs As Connection
        Dim rstTemp As Recordset
       
        Set dbsNorthwind = Workspaces(0).OpenDatabase("Panic.mdb")
       
        Set rstTemp = dbsNorthwind.OpenRecordset( _
        "tTest", dbOpenForwardOnly)
        If rstTemp.RecordCount > 0 Then
        'rstTemp.MoveFirst
        bolStop = rstTemp!TestVal
        End If
       
        rstTemp.Close
        dbsNorthwind.Close
       
        lblTest.Caption = bolStop
        Me.Repaint
        DoEvents
    End If

End Sub


Mike
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
Please see "Stop/Cancel Print Job..." at

http://www.experts-exchange.com/Microsoft/Development/MS_Access/Q_22509816.html

to handle it in a different manner. Any help is appreciated.

Mike
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Access

From novice to tech pro — start learning today.