A call to TMouse.GetCursorPos sometimes fails with "OS Function Call Failure"

Sometimes my application gets an error below.

This usually happens when the user moves away from his desk, leaving my program open. When they return, this error has appeared.

TMouse.GetCursorPostion does nothing except that calling the Windows API calls GetCursorPosition. Then it checks the return value and raises GetLastError if it fails.

An “OS function call error” doesn’t really help in tracking down the reason for this. Can a screen saver or hibernate cause an error? I could change the component to just catch and ignore the error, but if possible, I would rather find out what / why this happens in the first place.

My application uses Delphi 2007, and the call is made from the Transfer @Once (v 1.7) Quasidata component.

Here is the call stack:

  operating system: Windows XP Service Pack 3 build 2600
 exception number: 1
 exception class: EOSError
 exception message: A call to an OS function failed.

 main thread ($ d34):
 0045e208 UaarSales.exe SysUtils RaiseLastOSError
 0045e191 UaarSales.exe SysUtils RaiseLastOSError
 0045e237 UaarSales.exe SysUtils Win32Check
 004c6de9 UaarSales.exe Controls TMouse.GetCursorPos
 00736d8b UaarSales.exe taoCntrr 3999 TtaoHoverTimer.Timer
 004a1d27 UaarSales.exe ExtCtrls TTimer.WndProc
 0047a7a0 UaarSales.exe Classes StdWndProc
 7e4196c2 USER32.dll DispatchMessageA
 004da230 UaarSales.exe Forms TApplication.ProcessMessage
 004da26a UaarSales.exe Forms TApplication.HandleMessage
 004da55f UaarSales.exe Forms TApplication.Run
 00b3ea76 UaarSales.exe UaarSales 117 initialization

Here is the timer procedure

procedure TtaoHoverTimer.Timer; var lPos: TPoint; begin lPos := Mouse.CursorPos; // this is line 3999 if (lPos.X = FMousePos.X) and (lPos.Y = FMousePos.Y) and not ((lPos.X = FOutdatedPos.X) and (lPos.Y = FOutdatedPos.Y)) then begin inherited Timer; FOutdatedPos := Point(MaxInt, MaxInt); end; Enabled := False; end; 
+4
source share
3 answers

CursorPos uses the GetCursorPos method of Windows. MSDN comments say that it has two requirements:

  • "The calling process must have WINSTA_READATTRIBUTES access to the window station."
  • "The input desktop should be the current desktop when calling GetCursorPos. Call OpenInputDesktop to determine if the current desktop is the desktop. If not, call SetThreadDesktop with the HDESK returned by OpenInputDesktop to switch to this desktop."

So, it is likely that the screensaver is running on a different desktop. Alternatively, if you are using Vista, I am sure that the password dialog (for unlocking the computer) also launches on another desktop.

Since you have a source for this component, you can write your own wrapper for CursorPos, which returns a dummy value when a problem occurs. (Edit: or the commentator suggested processing the refusal to get the inline position instead of writing a function to return a dummy value.)

Finally, you can call GetLastError to find out what happened to the last Windows error after it raised an exception. This should tell you exactly what the problem it is facing. As in the comment (thanks!), You have already encountered an error message in the exception message.

+13
source

Without seeing the code and version of Windows, one can only guess. I would consider the TtaoHoverTimer.Timer procedure code in the taoCntrr module.

-1
source

Try calling the GetCursorPos (cursorPos) method ; on Windows .

Something like that:

 var cursorPos : TPoint; begin GetCursorPos(cursorPos); cursorPos := ScreenToClient(cursorPos); 

It works without problems in all my applications.

-1
source

Source: https://habr.com/ru/post/1286107/


All Articles