question

RatheeshVA-1454 avatar image
0 Votes"
RatheeshVA-1454 asked SongZhu-MSFT commented

Why does SystemParametersInfo with SPI_SETMOUSESPEED hang? Is there any solution

Hello everyone,

I am using SystemParametersInfo API in my application to change the cursor speed.
At some times, this API makes my OS hanged.
Is this API makes system hang.
If so, is there any solution?

Below is the code,

// FreeCursorDlg.cpp : implementation file
//

 const int kCallbackTimeridFreeCursor  = 1237;
 bool bSet = false;
 int speedinfo[3];
 define SETMOUSESPEED         0x0071    // hardcoded event for SystemParametersInfo
 // CAboutDlg dialog used for App About
    
 class CAboutDlg : public CDialogEx
 {
 public:
 CAboutDlg();
    
 // Dialog Data
 enum { IDD = IDD_ABOUTBOX };
    
 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    
 // Implementation
 protected:
 DECLARE_MESSAGE_MAP()
 };
    
 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
 {
 }
    
 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 {
 CDialogEx::DoDataExchange(pDX);
 }
    
 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 END_MESSAGE_MAP()
    
    
 // CFreeCursorDlg dialog
    
    
    
    
 CFreeCursorDlg::CFreeCursorDlg(CWnd* pParent /*=NULL*/)
 : CDialogEx(CFreeCursorDlg::IDD, pParent)
 {
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   speedinfo[0] = 6;  // CURSOR_THRESHOLD1;
   speedinfo[1] = 10;  // CURSOR_THRESHOLD2;
   speedinfo[2] = 1;  // CURSOR_SPEED;
 }
    
 void CFreeCursorDlg::DoDataExchange(CDataExchange* pDX)
 {
 CDialogEx::DoDataExchange(pDX);
 }
    
 BEGIN_MESSAGE_MAP(CFreeCursorDlg, CDialogEx)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
   ON_WM_TIMER()
   ON_BN_CLICKED(IDC_BUTTON_FREECURSOR, &CFreeCursorDlg::OnBnClickedButtonFreecursor)
 END_MESSAGE_MAP()
    
    
 // CFreeCursorDlg message handlers
    
 BOOL CFreeCursorDlg::OnInitDialog()
 {
 CDialogEx::OnInitDialog();
    
 // Add "About..." menu item to system menu.
    
 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);
    
 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
 BOOL bNameValid;
 CString strAboutMenu;
 bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 ASSERT(bNameValid);
 if (!strAboutMenu.IsEmpty())
 {
 pSysMenu->AppendMenu(MF_SEPARATOR);
 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
 }
 }
    
 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE); // Set big icon
 SetIcon(m_hIcon, FALSE); // Set small icon
    
 // TODO: Add extra initialization here
    
 return TRUE;  // return TRUE  unless you set the focus to a control
 }
    
 void CFreeCursorDlg::OnSysCommand(UINT nID, LPARAM lParam)
 {
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
 CAboutDlg dlgAbout;
 dlgAbout.DoModal();
 }
 else
 {
 CDialogEx::OnSysCommand(nID, lParam);
 }
 }
    
 // If you add a minimize button to your dialog, you will need the code below
 //  to draw the icon.  For MFC applications using the document/view model,
 //  this is automatically done for you by the framework.
    
 void CFreeCursorDlg::OnPaint()
 {
 if (IsIconic())
 {
 CPaintDC dc(this); // device context for painting
    
 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
 // Center icon in client rectangle
 int cxIcon = GetSystemMetrics(SM_CXICON);
 int cyIcon = GetSystemMetrics(SM_CYICON);
 CRect rect;
 GetClientRect(&rect);
 int x = (rect.Width() - cxIcon + 1) / 2;
 int y = (rect.Height() - cyIcon + 1) / 2;
    
 // Draw the icon
 dc.DrawIcon(x, y, m_hIcon);
 }
 else
 {
 CDialogEx::OnPaint();
 }
 }
    
 // The system calls this function to obtain the cursor to display while the user drags
 //  the minimized window.
 HCURSOR CFreeCursorDlg::OnQueryDragIcon()
 {
 return static_cast<HCURSOR>(m_hIcon);
 }
    
 void CFreeCursorDlg::OnTimer(UINT_PTR nIDEvent)
 {
   // TODO: Add your message handler code here and/or call default
   if (nIDEvent == kCallbackTimeridFreeCursor) {
     SetFreeCursor();
     bSet = bSet ? false : true;
   }
    
   CDialogEx::OnTimer(nIDEvent);
 }
    
    
 void CFreeCursorDlg::OnBnClickedButtonFreecursor()
 {
   KillTimer(kCallbackTimeridFreeCursor);
   UINT_PTR timerid = SetTimer(kCallbackTimeridFreeCursor, 10, NULL);
   if (timerid == 0) {
     AfxMessageBox(L"UnableToObtainTimer For FreeCursor");
   }
 }
    
 void CFreeCursorDlg::SetFreeCursor() {
   ClipCursor(NULL);
   SetInitialCursorSpeed();
   ::SetFocus(m_hWnd);
   if (!bSet) {
     ShowCursor(true);
     ClipCursor(NULL);
   } else {
     ShowCursor(false);
     ClipCursorOn();
   }
   SetCursorSpeed();
   POINT pntSaveCursorPos;
   GetCursorPos(&pntSaveCursorPos);
   SetCursorPos(pntSaveCursorPos.x, pntSaveCursorPos.y);
 }
    
 void CFreeCursorDlg::ShowCursor(bool boShow) {
   if(boShow == true) {
     int nCount = ::ShowCursor( TRUE );
     while( nCount < 0 )
     {
       nCount = ::ShowCursor( TRUE );
     }
   } else {
     int nCount = ::ShowCursor( FALSE );
     while( nCount >= 0 )
     {
       nCount = ::ShowCursor( FALSE );
     }
   }
 }
    
 void CFreeCursorDlg::ClipCursorOn() {
   CRect rect;
   ::GetWindowRect(m_hWnd, rect);
   if(( rect.top != 0 ) && ( rect.bottom != 0 ) && ( rect.left != 0 ) && ( rect.right != 0 ))
   {
     ClipCursor(&rect);
   }
 }
    
 void CFreeCursorDlg::SetCursorSpeed() {
   SystemParametersInfo(SPI_SETMOUSE, 0, speedinfo, 0);
   int iSpeed = 8;
   BOOL boResult = SystemParametersInfo(SPI_SETMOUSESPEED, 0, reinterpret_cast<PVOID>(static_cast<INT_PTR>(iSpeed)), 0);
 }
    
 void CFreeCursorDlg::SetInitialCursorSpeed() {
   int ini_speedinfo[3];
   INT_PTR nSpeed;
   if (!bSet) {
     ini_speedinfo[0] = 8;  // CURSOR_THRESHOLD1;
     ini_speedinfo[1] = 12;  // CURSOR_THRESHOLD2;
     ini_speedinfo[2] = 3;  // CURSOR_SPEED;
     nSpeed = 9;
   }
   else {
     ini_speedinfo[0] = 9;  // CURSOR_THRESHOLD1;
     ini_speedinfo[1] = 13;  // CURSOR_THRESHOLD2;
     ini_speedinfo[2] = 2;  // CURSOR_SPEED;
     nSpeed = 4;
   }
   SystemParametersInfo(SPI_SETMOUSE, 0, ini_speedinfo, 0);
   BOOL result = SystemParametersInfo(SETMOUSESPEED, 0,
     reinterpret_cast<void*>(nSpeed), 0);
 }


Thanks in advance.
Ratheesh

windows-api
· 9
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, I tested the code and it works fine for me. Could you give more details? Such as test environment, system information or more code information?

0 Votes 0 ·

Thankyou SongZhu for the quick reply.

Please note TestEnvironment:
OS - Windows 10
Compiler - MSVC
Development environment: Visual studio 2017 (Professional edition - 15.9.33 version)
I have updated the dependent APIs with the source code.
Could you please check.


0 Votes 0 ·

Sorry that the code is a bit complicated and I am not sure what caused the hang. Do you have a simple test of your setMyCursorSpeed function to check if it is working properly, like:

 void setMyCursorSpeed(int speed)
 {
     int speedInfo[3] = { 6, 10, 1 };
     SystemParametersInfo(SPI_SETMOUSE, 0, speedInfo, 0);
     INT_PTR ptrSpeed = speed;     // speed =  6
     SystemParametersInfo(SPI_SETMOUSESPEED, 0, reinterpret_cast<void*>(ptrSpeed), 0);
 }
    
    
 int main(int argc, const char* argv[])
 {
     setMyCursorSpeed(10);
     return 0;
 }

Also could you please show a minimal, reproducible sample without private information to help us reproduce this issue?




0 Votes 0 ·
Show more comments
RatheeshVA-1454 avatar image
0 Votes"
RatheeshVA-1454 answered

We got this issue reproduced in almost all situations.
When SystemParamterersInfo is called continuously from our application, sometimes it makes a system hang.

Below two API’s are called from our application:

 SystemParametersInfo(SPI_SETMOUSESPEED, 0, reinterpret_cast<PVOID>(static_cast<INT_PTR>(iSpeed)), 0);
 SystemParametersInfo(SPI_SETMOUSE, 0, speedinfo, 0);

On a reproduction, we have made a testapp.
We put these code in OnTimer() to call it continuously.
While running the Timer, we move the cursor in a random manner upon the screen.
We get the system hang almost all times.


 int speedinfo[3];
 CFreeCursorIssueDlg::CFreeCursorIssueDlg(CWnd* pParent /*=NULL*/)
 : CDialogEx(CFreeCursorIssueDlg::IDD, pParent)
 {
   m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   speedinfo[0] = 6; 
   speedinfo[1] = 10; 
   speedinfo[2] = 1;
 }
    
 void CFreeCursorIssueDlg::SetCursorSpeed() {
     int iSpeed = 8;
     BOOL boResult = SystemParametersInfo(SPI_SETMOUSESPEED, 0, reinterpret_cast<PVOID>(static_cast<INT_PTR>(iSpeed)), 0);
     SystemParametersInfo(SPI_SETMOUSE, 0, speedinfo, 0);
 }
    
 void CFreeCursorIssueDlg::OnTimer(UINT_PTR nIDEvent){
     SetCursorSpeed();
     CDialogEx::OnTimer(nIDEvent);
 }


OS Name : Windows 10 Pro
Version : 10.0.17763 Build 17763
System Info is uploaded.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RatheeshVA-1454 avatar image
0 Votes"
RatheeshVA-1454 answered

100625-systeminfo.png100592-dxdiag.png



systeminfo.png (105.8 KiB)
dxdiag.png (32.1 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.