Why does SystemParametersInfo with SPI_SETMOUSESPEED hang? Is there any solution

Ratheesh VA 1 Reputation point
2021-05-26T05:46:44.767+00:00

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 - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,426 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Ratheesh VA 1 Reputation point
    2021-05-28T12:34:42.783+00:00

    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.

    0 comments No comments

  2. Ratheesh VA 1 Reputation point
    2021-05-28T12:37:30.29+00:00

    100625-systeminfo.png100592-dxdiag.png

    0 comments No comments