• Welcome to TechPowerUp Forums, Guest! Please check out our forum guidelines for info related to our community.
  • The forums have been upgraded with support for dark mode. By default it will follow the setting on your system/browser. You may override it by scrolling to the end of the page and clicking the gears icon.

SystemParametersInfo Question - C#

Kreij

Senior Monkey Moderator
Joined
Feb 6, 2007
Messages
13,817 (2.05/day)
Location
Cheeseland (Wisconsin, USA)
I'm using P/Invoke to accesss the SystemParametersInfo method in the user32.dll and trying to set the mouse hover time (the time that elapses before a hover event is triggered).

Code:
[[COLOR="Teal"]DllImport[/COLOR]([COLOR="Red"]"user32.dll"[/COLOR], EntryPoint=[COLOR="Red"]"SystemParametersInfo"[/COLOR], SetLastError = [COLOR="Blue"]true[/COLOR])]
[[COLOR="Blue"]return[/COLOR]: [COLOR="Teal"]MarshalAs[/COLOR]([COLOR="Teal"]UnmanagedType[/COLOR].Bool)]
[COLOR="Blue"]public static extern bool [/COLOR]SystemParametersInfo([COLOR="blue"]uint [/COLOR]action, [COLOR="blue"]uint [/COLOR]param, [COLOR="blue"]uint [/COLOR]vparam, [COLOR="blue"]uint [/COLOR]init);

[COLOR="blue"]private const uint[/COLOR] SPI_SETMOUSEHOVERTIME = 103;
[COLOR="blue"]private const uint [/COLOR]SPIF_UPDATEINIFILE = 0x01;
[COLOR="blue"]private const uint [/COLOR]SPIF_SENDCHANGE = 0x02;

[COLOR="blue"]public [/COLOR]Form1()
{
    InitializeComponent();
    SetAccesses();

    [COLOR="Teal"]MessageBox[/COLOR].Show([COLOR="Teal"]SystemInformation[/COLOR].MouseHoverTime.ToString());
    SystemParametersInfo(SPI_SETMOUSEHOVERTIME, ([COLOR="blue"]uint[/COLOR])2000, ([COLOR="blue"]uint[/COLOR])0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
    [COLOR="Teal"]MessageBox[/COLOR].Show([COLOR="Teal"]SystemInformation[/COLOR].MouseHoverTime.ToString());
}

The above code has exactly zero effect on the hover delay (visually), even though the first message box reports the delay to be 50ms and the second one shows it has changed to 2000ms.
When I display the return value from SystemParametersInfo, it returns true.

Anyone have any working code for changing this in SystemParameters, or perhaps pointing out something I'm doing wrong?

Thanks!
 
http://msdn.microsoft.com/en-us/library/ms724947(VS.85).aspx

Sets the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent to generate a WM_MOUSEHOVER message. This is used only if you pass HOVER_DEFAULT in the dwHoverTime parameter in the call to TrackMouseEvent. Set the uiParam parameter to the new time.

The time specified should be between USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM. If uiParam is less than USER_TIMER_MINIMUM, the function will use USER_TIMER_MINIMUM. If uiParam is greater than USER_TIMER_MAXIMUM, the function will be USER_TIMER_MAXIMUM.

Windows Server 2003 and Windows XP: The operating system does not enforce the use of USER_TIMER_MAXIMUM and USER_TIMER_MINIMUM until Windows Server 2003 with SP1 and Windows XP with SP2.


Static extern has failed to work for me for usually one of two reasons:

1) The assmbly type does not match the loading assmbly (e.g. x64 loading x86 will give a generic message).

2) Parameters aren't marked by reference when they need to be.


In your scenario, these are the things I'd try:

Code:
public static extern bool SystemParametersInfo(uint action, uint param, [u]IntPtr[/u] vparam, uint init);

Code:
SystemParametersInfo(SPI_SETMOUSEHOVERTIME, (uint)2000, [u]null[/u], SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);


If that doesn't work:

Code:
public static extern bool SystemParametersInfo(uint action, uint param, [u]ref[/u] uint vparam, uint init);
 
Thanks for the ideas, Ford, but neither passing the vParam as a ref or using an IntPtr does anything.
Both methods will compile without error, but the delay never gets changed.

MSDN said:
This is used only if you pass HOVER_DEFAULT in the dwHoverTime parameter in the call to TrackMouseEvent

Off to try to figure this litte gem out. :D
 
I'd leave it as IntPtr (pvparam--p = pointer XD).


From itags.org:
Technically, you can change it with the SystemParametersInfo() API function using the SPI_SETMOUSEHOVERTIME argument. You shouldn't do this though, it will affect the hover time for all applications, not just yours. You can't reliably delay the hover event with the timer, it won't run again when you've moved the mouse after it fired but before the timer expired. Here's an alternative:
Code:
public partial class Form1 : Form {
private Point mHoverPos;
private bool mHoverDone;
private Timer mHoverTimer = new Timer();
public Form1() {
InitializeComponent();
mHoverTimer.Tick += HoverTick;
mHoverTimer.Interval = 2000;
}
private void panel1_MouseMove(object sender, MouseEventArgs e) {
if (mHoverDone) return;
if (mHoverTimer.Enabled) {
// Restart timer if the mouse moved too far
if (Math.Abs(e.X - mHoverPos.X) <= 4 && Math.Abs(e.Y - mHoverPos.Y) <= 4) return;
mHoverTimer.Enabled = false;
} 
// Start hover timer
mHoverPos = e.Location;
mHoverTimer.Enabled = true;
}
private void panel1_MouseLeave(object sender, EventArgs e) {
mHoverTimer.Enabled = false;
mHoverDone = false;
}
private void HoverTick(object sender, EventArgs e) {
mHoverTimer.Enabled = false;
mHoverDone = true;
// Put your hover event code here:
panel1.BackColor = panel1.BackColor == Color.White ? Color.Black : Color.White;
}
}
 
Yes, I've seen that post (it's being serverd by a million sites :D ), but that method leaves a little to be desired.
Also, since I started trying to get the SystemParametersInfo method to work, I can no longer give up until I do, whether I use it or not.
The computer never wins.

I'm fiddling around with overriding TrackMouseEvents at the moment.
 
So far ... Computer 1, Kreij 0

Nothing seems to work. The MouseHoverTime is being updated in the registry, but it does not seem to have any effect whatsoever.
 
simpsons_nelson_haha2.gif


Have you tried restarting explorer.exe after changing it? It might simply be obsolete.
 
I lol'd at the image. :D

Yeah, I tried logging out and back in and same.
Back to the drawing board.
 
Back
Top