I want to hide my mouse cursor after an idle time and it will be showed up when I move the mouse. I tried to use a timer but it didn't work well. Can anybody help me? Please!
If you are using WinForms and will only deploy on Windows machines then it's quite easy to use user32 GetLastInputInfo to handle both mouse and keyboard idling.
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
}
And then in your Form
public partial class MyForm : Form
{
Timer activityTimer = new Timer();
TimeSpan activityThreshold = TimeSpan.FromMinutes(2);
bool cursorHidden = false;
public Form1()
{
InitializeComponent();
activityTimer.Tick += activityWorker_Tick;
activityTimer.Interval = 100;
activityTimer.Enabled = true;
}
void activityWorker_Tick(object sender, EventArgs e)
{
bool shouldHide = User32Interop.GetLastInput() > activityThreshold;
if (cursorHidden != shouldHide)
{
if (shouldHide)
Cursor.Hide();
else
Cursor.Show();
cursorHidden = shouldHide;
}
}
}
Here is a contrived example of how to do it. You probably had some missing logic that was overriding the cursor's visibility:
public partial class Form1 : Form
{
public TimeSpan TimeoutToHide { get; private set; }
public DateTime LastMouseMove { get; private set; }
public bool IsHidden { get; private set; }
public Form1()
{
InitializeComponent();
TimeoutToHide = TimeSpan.FromSeconds(5);
this.MouseMove += new MouseEventHandler(Form1_MouseMove);
}
void Form1_MouseMove(object sender, MouseEventArgs e)
{
LastMouseMove = DateTime.Now;
if (IsHidden)
{
Cursor.Show();
IsHidden = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan elaped = DateTime.Now - LastMouseMove;
if (elaped >= TimeoutToHide && !IsHidden)
{
Cursor.Hide();
IsHidden = true;
}
}
}
Need to account for Environment.Tickcount being negative:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
{
int idleTime = unchecked(Environment.TickCount - (int)plii.dwTime);
return TimeSpan.FromMilliseconds(idleTime);
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
}
If you try to hide the cursor from another thread you need to call Invoke(...) on the winform to enter the UI thread. Had cost me some headegg why Cursor.Hide() wasn't working. Also "PInvoke ShowCursor(bool bShow)" has the benefit to return the Show/Hide-Count.
[DllImport("user32.dll")]
static extern int ShowCursor(bool bShow);
private System.Timers.Timer _timerMouseAutoHide;
Point _lastPos = new Point(int.MaxValue);
readonly Stopwatch _stopwatch = new Stopwatch();
private int _cursorVisibilityCount = 0;
private void InitMouseAutoHide()
{
if (_timerMouseAutoHide != null)
return;
_timerMouseAutoHide = new Timer(100){AutoReset = false};
_timerMouseAutoHide.Elapsed += MouseAutoHideHit;
_timerMouseAutoHide.Start();
_stopwatch.Restart();
}
private void MouseAutoHideHit(object pSender, ElapsedEventArgs pE)
{
try
{
if (IsDisposed)
return;
var lCurrentPos = Cursor.Position;
var lCursorHasMoved = _lastPos != lCurrentPos;
_lastPos = lCurrentPos;
if (_cursorVisibilityCount < 0 && lCursorHasMoved)
{
//Cursor is not Visible and Mouse has moved
_cursorVisibilityCount = ShowCursor();
Debug.WriteLine($"Visible {lCurrentPos}, ShowCursor={_cursorVisibilityCount}");
}
else if (_cursorVisibilityCount > -1 && _stopwatch.ElapsedMilliseconds > 3000)
{
//Cursor is Visible and Mouse didn't move fox x ms.
_cursorVisibilityCount = HideCursor();
Debug.WriteLine($"Hidden {lCurrentPos}, ShowCursor={_cursorVisibilityCount}");
}
if (lCursorHasMoved)
_stopwatch.Restart();
}
catch (Exception lEx)
{
GLog.Error(lEx);
}
finally
{
_timerMouseAutoHide?.Start();
}
}
public int ShowCursor()
{
var lCursorVisibilityCount = 0;
Invoke(new Action(() =>
{
do
{
lCursorVisibilityCount = ShowCursor(true);
} while (lCursorVisibilityCount < 0);
}));
return lCursorVisibilityCount;
}
public int HideCursor()
{
var lCursorVisibilityCount = 0;
Invoke(new Action(() =>
{
do
{
lCursorVisibilityCount = ShowCursor(false);
} while (lCursorVisibilityCount > -1);
}));
return lCursorVisibilityCount;
}
Related
When dragging a borderless form to the top of the screen; if the Y coordinate is negative, it sets it back to 0. What I'm looking to do is be able to drag the form above the top, where the Y coordinate would be negative, the same way you can with every other side of the screen.
Here is what I have tried:
public partial class BorderlessForm : Form
{
public BorderlessForm()
{
InitializeComponent();
}
private bool _isNegative;
private Point _negative;
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) {
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative) {
Location = _negative;
}
//base.OnResizeEnd(e);
}
protected override void OnMove(EventArgs e)
{
if (Location.Y < 0) {
_isNegative = true;
_negative = Location;
}
else {
_isNegative = false;
}
//base.OnMove(e);
}
}
This was the best I could come up with after thinking on it for a while. The problem is that when the mouse is released and the form is finished moving, OnMove is called before OnResizeEnd, and _isNegative is then set back to false. At least, that is what I assume is happening.
Do I have the right idea, or is there some better way to go about this?
So, I thought more about what isaeid said, and was able to come up with a solution. Still not sure if this is the best way to go about it, but here it is:
public partial class ImageForm : PerPixelAlphaForm
{
public ImageForm()
{
InitializeComponent();
}
private bool _isNegative;
private Point _negative;
private bool _flag;
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) {
NativeMethods.ReleaseCapture();
NativeMethods.SendMessage(Handle, NativeMethods.WM_NCLBUTTONDOWN, NativeMethods.HT_CAPTION, 0);
}
}
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative) {
Location = _negative;
_isNegative = false;
}
}
protected override void OnMove(EventArgs e)
{
if (Location.Y < 0) {
_isNegative = true;
_flag = true;
_negative = Location;
}
else {
if (_flag) {
_flag = false;
return;
}
_isNegative = false;
}
}
}
You can change some events like this:
protected override void OnResizeEnd(EventArgs e)
{
if (_isNegative)
{
Location = _negative;
}
oldRight = this.Right;
oldBottom = this.Bottom;
//base.OnResizeEnd(e);
}
protected override void OnMove(EventArgs e)
{
if ( this.Right == oldRight || this.Bottom == oldBottom)
return;
if (Location.Y < 0)
{
_isNegative = true;
_negative = Location;
}
else
{
_isNegative = false;
}
//base.OnMove(e);
}
When top or left of window is changed, dotnet determines location of window is changed and calls onmove event, i consider if right or bottom of the window is not changed so window's location is not changed.
Add this codes too:
int oldBottom, oldRight;
private void BorderlessForm_Load(object sender, EventArgs e)
{
oldRight = this.Right;
oldBottom = this.Bottom;
}
I'm trying to make a program where when I click left click it drags the mouse down without me moving my mouse down for a game but it does not move the game at all. It moves my cursor outside of the game but does not move inside the game.
public static Point Position { get; set; }
public Anti_Recoil()
{
InitializeComponent();
}
private void Anti_Recoil_Load(object sender, EventArgs e)
{
this.BackColor = Color.Wheat;
this.TransparencyKey = Color.Wheat;
this.TopMost = true;
int initialStyle = GetWindowLong(this.Handle, -20);
SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);
PointConverter pc = new PointConverter();
Point pt = new Point();
pt = (Point)pc.ConvertFromString("765, 500");
Cursor.Position = pt;
}
private void Anti_Recoil_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Z)
Hide();
}
Use my class
First, add my class to your project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Input;
namespace Hector.Framework.Utils
{
public class Peripherals
{
public class Mouse
{
public static int X
{
get => Cursor.Position.X;
}
public static int Y
{
get => Cursor.Position.Y;
}
public static void MoveToPoint(int X, int Y)
{
Win32.SetCursorPos(X, Y);
}
public static void Hide()
{
Cursor.Hide();
}
public static void Show()
{
Cursor.Show();
}
public static bool IsHidden
{
get => Cursor.Current == null;
}
/// <summary>
/// ButtonNumber: 0-None 1-Left 2-Middle 3-Right 4-XButton1 5-XButton2
/// </summary>
public static bool MouseButtonIsDown(int ButtonNumber)
{
bool outValue = false;
bool isLeft = Control.MouseButtons == MouseButtons.Left;
bool isRight = Control.MouseButtons == MouseButtons.Right;
bool isMiddle = Control.MouseButtons == MouseButtons.Middle;
bool isXButton1 = Control.MouseButtons == MouseButtons.XButton1;
bool isXButton2 = Control.MouseButtons == MouseButtons.XButton2;
switch (ButtonNumber)
{
case 0:
outValue = false;
break;
case 1:
outValue = isLeft;
break;
case 2:
outValue = isMiddle;
break;
case 3:
outValue = isRight;
break;
case 4:
outValue = isXButton1;
break;
case 5:
outValue = isXButton2;
break;
}
return outValue;
}
/// <summary>
/// This function is in Alpha Phase
/// </summary>
/// <param name="FocusedControl">The control that is scrolled; If the control has no focus, it will be applied automatically</param>
/// <param name="FontSize">This is used to calculate the number of pixels to move, its default value is 20</param>
static int delta = 0;
static int numberOfTextLinesToMove = 0;
static int numberOfPixelsToMove = 0;
public static bool GetWheelValues(Control FocusedControl, out int Delta, out int NumberOfTextLinesToMove, out int NumberOfPixelsToMove, int FontSize = 20)
{
try
{
if (FocusedControl == null) throw new NullReferenceException("The FocusedControl can not bel null");
if (!FocusedControl.Focused) FocusedControl.Focus();
FocusedControl.MouseWheel += (object sender, MouseEventArgs e) =>
{
delta = e.Delta;
numberOfTextLinesToMove = e.Delta * SystemInformation.MouseWheelScrollLines / 120;
numberOfPixelsToMove = numberOfTextLinesToMove * FontSize;
};
Delta = delta;
NumberOfTextLinesToMove = numberOfTextLinesToMove;
NumberOfPixelsToMove = numberOfPixelsToMove;
return true;
}
catch
{
Delta = 0;
NumberOfTextLinesToMove = 0;
NumberOfPixelsToMove = numberOfPixelsToMove;
return false;
}
}
private class Win32
{
[DllImport("User32.Dll")]
public static extern long SetCursorPos(int x, int y);
[DllImport("User32.Dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT point);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
}
}
}
}
Then where you need to check the mouse's status,
bool MouseLeftButton = Hector.Framework.Utils.Peripherals.Mouse.MouseButtonIsDown(1);
And try this:
private void Form2_Load(object sender, EventArgs e)
{
Hector.Framework.Utils.Peripherals.Mouse.MoveToPoint(300, 0); //Move the cursor to Top
}
//Then use timer to move the cursor
int a = 0;
private void timer1_Tick(object sender, EventArgs e)
{
Hector.Framework.Utils.Peripherals.Mouse.MoveToPoint(300, a += 1);
}
if(MouseLeftButton)
{
timer1.Start(); //timer is initialized
}
I am working on a small project (just for fun) that allows me to display the frequencies played back in my current audio buffer.
The plan is:
The thread that is executing the WaveOutPlayer.ThreadProc() method keeps playing and refilling two audio buffers. While the first buffer is playing, the second buffer gets refilled and vice versa. To be sure that one buffer does not start playing before the other one stopped playback, I use the WaitOne() method. After the buffer's audio data has beed played back by the WaveOut device, the buffer's OnCompleted() method is called. This method cancels the waiting.
The playback itself starts, but it is very choppy.
Could anyone tell me why this happens?
The Visual Studio project is located at http://www.pour-toujours.net/lowlevelaudio.zip
(currently, only 16-bit, Stereo, 44,1kHz uncompressed wav is supported.)
Here goes some of my code that seems to be relevant:
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
namespace LowLevelAudio
{
internal class WaveOutHelper
{
public static void Try(int err)
{
if (err != WaveNative.MMSYSERR_NOERROR)
throw new Exception(err.ToString());
}
}
public delegate void BufferFillEventHandler(IntPtr data, int size);
public class WaveOutBuffer : IDisposable
{
private AutoResetEvent m_PlayEvent = new AutoResetEvent(false);
private IntPtr m_WaveOut;
private int m_buffersize;
private static byte[] m_samples;
private static double[] m_fftsamples;
private WaveNative.WaveHdr m_Header;
private byte[] m_HeaderData;
private GCHandle m_HeaderHandle;
private GCHandle m_HeaderDataHandle;
private WaveFormat m_waveformat;
private double[] m_fftOccurances;
private double[] m_fftHertzlist;
private bool m_Playing;
public int ID
{
get; set;
}
internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
{
if (uMsg == WaveNative.MM_WOM_DONE)
{
try
{
GCHandle h = (GCHandle)wavhdr.dwUser;
WaveOutBuffer buf = (WaveOutBuffer)h.Target;
buf.OnPlayCompleted();
}
catch(Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
}
}
}
public WaveOutBuffer(IntPtr waveOutHandle, int size, WaveFormat format)
{
m_WaveOut = waveOutHandle;
m_waveformat = format;
m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned);
m_Header.dwUser = (IntPtr)GCHandle.Alloc(this);
m_HeaderData = new byte[size];
m_HeaderDataHandle = GCHandle.Alloc(m_HeaderData, GCHandleType.Pinned);
m_Header.lpData = m_HeaderDataHandle.AddrOfPinnedObject();
m_Header.dwBufferLength = size;
m_buffersize = size;
m_samples = new byte[m_buffersize];
WaveOutHelper.Try(WaveNative.waveOutPrepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)));
}
~WaveOutBuffer()
{
Dispose();
}
public int Size
{
get { return m_Header.dwBufferLength; }
}
public IntPtr Data
{
get { return m_Header.lpData; }
}
public void Dispose()
{
if (m_Header.lpData != IntPtr.Zero)
{
WaveNative.waveOutUnprepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header));
m_HeaderHandle.Free();
m_Header.lpData = IntPtr.Zero;
}
m_PlayEvent.Close();
if (m_HeaderDataHandle.IsAllocated)
m_HeaderDataHandle.Free();
}
public bool Play()
{
lock(this) // works, but has to be fine tuned... (to do)
{
m_PlayEvent.Reset();
m_Playing = WaveNative.waveOutWrite(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)) == WaveNative.MMSYSERR_NOERROR;
if (!m_Playing)
throw new Exception("test exception");
return m_Playing;
}
}
public void WaitForMe()
{
Console.WriteLine(this.ID + " WaitFor()");
if (m_Playing)
{
m_Playing = m_PlayEvent.WaitOne();
}
else
{
m_Playing = false;
}
}
public void OnPlayCompleted()
{
Console.WriteLine(this.ID + " OnCompleted()");
m_PlayEvent.Set();
m_Playing = false;
}
}
public class WaveOutPlayer : IDisposable
{
private IntPtr m_WaveOut;
private WaveOutBuffer[] m_bufferlist;
private Thread m_Thread;
private BufferFillEventHandler m_FillProc;
private bool m_Finished;
private byte m_zero;
private int m_buffercount = 0;
private int m_buffersize = 0;
private WaveFormat m_waveformat;
private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc);
public static int DeviceCount
{
get { return WaveNative.waveOutGetNumDevs(); }
}
public WaveOutPlayer(int device, WaveFormat format, int bufferSize, BufferFillEventHandler fillProc)
{
m_zero = format.wBitsPerSample == 8 ? (byte)128 : (byte)0;
m_FillProc = fillProc;
m_buffercount = 2;
m_buffersize = bufferSize;
m_waveformat = format;
WaveOutHelper.Try(WaveNative.waveOutOpen(out m_WaveOut, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
AllocateBuffers(bufferSize, m_buffercount, format);
m_Thread = new Thread(new ThreadStart(ThreadProc));
m_Thread.Start();
}
~WaveOutPlayer()
{
Dispose();
}
public void Dispose()
{
if (m_Thread != null)
{
try
{
m_Finished = true;
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutReset(m_WaveOut);
m_Thread.Join();
m_FillProc = null;
FreeBuffers();
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutClose(m_WaveOut);
}
finally
{
m_Thread = null;
m_WaveOut = IntPtr.Zero;
}
}
}
private void ThreadProc()
{
WaveOutBuffer b0 = m_bufferlist[0];
WaveOutBuffer b1 = m_bufferlist[1];
MainForm form = Program.getUI();
bool s = true;
m_FillProc(b0.Data, b0.Size);
while (!m_Finished)
{
if (s)
{
Console.WriteLine("-------------------------");
Console.WriteLine("Playing b0, filling b1");
b0.Play();
m_FillProc(b1.Data, b1.Size);
form.paintEqualizer(b0);
Console.WriteLine("callng waitFor on b0");
b0.WaitForMe();
}
else
{
Console.WriteLine("-------------------------");
Console.WriteLine("Playing b1, filling b0");
b1.Play();
m_FillProc(b0.Data, b0.Size);
form.paintEqualizer(b1);
Console.WriteLine("callng waitFor on b1");
b1.WaitForMe();
}
s = !s;
}
}
private void AllocateBuffers(int bufferSize, int bufferCount, WaveFormat format)
{
FreeBuffers();
m_bufferlist = new WaveOutBuffer[m_buffercount];
if (bufferCount > 0)
{
for (int i = 0; i < m_buffercount; i++)
{
m_bufferlist[i] = new WaveOutBuffer(m_WaveOut, bufferSize, format);
m_bufferlist[i].ID = i;
}
}
}
private void FreeBuffers()
{
if (m_bufferlist != null)
{
foreach (WaveOutBuffer currentBuffer in m_bufferlist)
{
if (currentBuffer != null)
{
currentBuffer.Dispose();
}
}
}
}
}
}
How do I check user is inactive?
I have this:
class UserActivity : IMessageFilter
{
private double afk_time = 0.1;//minutes
private DateTime last_activity = DateTime.Now;
public static bool inactive = false;
private int WM_LBUTTONDOWN = 0x0201;
private int WM_MBUTTONDOWN = 0x0207;
private int WM_RBUTTONDOWN = 0x0204;
private int WM_MOUSEWHEEL = 0x020A;
private int WM_MOUSEMOVE = 0x0200;
private int WM_KEYDOWN = 0x0100;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
{
this.last_activity = DateTime.Now;
inactive = false;
}
if (DateTime.Now.AddMinutes(-afk_time) > last_activity)
inactive = true;
return false;
}
}
But I must run it in Program.cs
Application.AddMessageFilter(new UserActivity());
How can I do that I can run the checking of user inactivity by my self. I'll check some checkbox and it will start checking.
And I want check global user activity - in all system not only in app.
I don't want use of cpu unnecessary. Or should I use another solution?
I found this and it works perfect !
So if another one have problem with it here is solution:
[StructLayout(LayoutKind.Sequential)]
public struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public static TimeSpan? GetInactiveTime()
{
LASTINPUTINFO info = new LASTINPUTINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
if (GetLastInputInfo(ref info))
return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime);
else
return null;
}
I have tried to build a class base on previous answer, I have test it and it work properly.
It is async but i have not use async key. If someone finds some problem or amelioration so welcome.
public class User
{
[StructLayout(LayoutKind.Sequential)]
public struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public static TimeSpan? GetInactiveTime()
{
LASTINPUTINFO info = new LASTINPUTINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
if (GetLastInputInfo(ref info))
return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime);
else
return null;
}
private TimeSpan? LastTime;
private DispatcherTimer timer = new DispatcherTimer();
public void RequestUserActivity()
{
LastTime = GetInactiveTime();
timer.Interval = TimeSpan.FromMilliseconds(500);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
TimeSpan? tmpTime = GetInactiveTime();
if (LastTime.HasValue && tmpTime.HasValue && tmpTime < LastTime)
{
timer.Stop();
UserAtivited(this, new EventArgs());
}
else if (!LastTime.HasValue || !tmpTime.HasValue)
{
timer.Stop();
throw new Exception();
}
}
public event EventHandler UserAtivited;
}
Now In your window create a new instance of User, register to UserActivated event and laugth RequestUserActivity(). I expert it will be helpfull.
Please, do not have regards on my poor english. I'm french speaker.
How do I check the connection between PPC and a web service on the server? I work on FW3.5 C#
I can't remember offhand if this is available in .Net CF or not:
System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged
Another option is to just attempt to use the web service, and handle exceptions. I usually follow this pattern, is there a reason it doesn't work for your case?
Edit:
Connection Monitor class:
public static class ConnectionMonitor
{
public static event EventHandler IsConnectedChanged;
private static SystemState _connectionState = null,
//_cellState = null,
_gprsState = null;
private static int _connectionCount = 0;
//_cellCount = 0;
private static bool _gprs = false;
private static bool _isConnected = true;
private static string _phoneCarrier = SystemState.PhoneOperatorName;
private const int POWER_FLAGS = 0x00000001; // default
private const string AXIM_WIFI_ADAPTER = "{98C5250D-C29A-4985-AE5F-AFE5367E5006}\\TIACXWLN1";
public static bool IsPhone
{
get { return !string.IsNullOrEmpty(_phoneCarrier); }
}
public static bool IsGPRSConnected
{
get { return _gprs; }
}
public static bool IsConnected
{
get { return _isConnected; }
set
{
if (_isConnected != value)
{
_isConnected = value;
if (IsConnectedChanged != null)
{
IsConnectedChanged(null, EventArgs.Empty);
}
if (!_isConnected && !IsPhone)
{
WifiOn();
}
}
}
}
private static void WifiOn()
{
Win32.CEDEVICE_POWER_STATE state = new Win32.CEDEVICE_POWER_STATE();
if (Win32.GetDevicePower(AXIM_WIFI_ADAPTER, POWER_FLAGS, ref state) == 0)
{
if (state != Win32.CEDEVICE_POWER_STATE.D0)
{
Win32.DevicePowerNotify(AXIM_WIFI_ADAPTER, Win32.CEDEVICE_POWER_STATE.D4, POWER_FLAGS);
Win32.SetDevicePower(AXIM_WIFI_ADAPTER, POWER_FLAGS, Win32.CEDEVICE_POWER_STATE.D0);
}
}
}
public static void Init()
{
if (_connectionState == null)
{
_connectionState = new SystemState(SystemProperty.ConnectionsCount);
_connectionCount = SystemState.ConnectionsCount;
_connectionState.Changed += new ChangeEventHandler(_state_Changed);
}
//if (_cellState == null)
//{
// _cellState = new SystemState(SystemProperty.ConnectionsCellularCount);
// _cellCount = SystemState.ConnectionsCellularCount;
// _cellState.Changed += new ChangeEventHandler(_state_Changed);
//}
if (_gprsState == null)
{
_gprsState = new SystemState(SystemProperty.PhoneGprsCoverage);
_gprs = SystemState.PhoneGprsCoverage;
_gprsState.Changed += new ChangeEventHandler(_state_Changed);
}
IsConnected = _connectionCount > 0 || _gprs;
}
private static void _state_Changed(object sender, ChangeEventArgs args)
{
//_cellCount = SystemState.ConnectionsCellularCount;
_connectionCount = SystemState.ConnectionsCount;
_gprs = SystemState.PhoneGprsCoverage;
IsConnected = _connectionCount > 0 || _gprs;
}
public static void Dispose()
{
if (_connectionState != null)
{
_connectionState.Changed -= new ChangeEventHandler(_state_Changed);
_connectionState.Dispose();
_connectionState = null;
}
//if (_cellState != null)
//{
// _cellState.Changed -= new ChangeEventHandler(_state_Changed);
// _cellState.Dispose();
// _cellState = null;
//}
if (_gprsState != null)
{
_gprsState.Changed -= new ChangeEventHandler(_state_Changed);
_gprsState.Dispose();
_gprsState = null;
}
}
}
My Win32 static class had a lot of calls (unrelated to your needs) in it. Here are all the ones I think you need:
public enum CEDEVICE_POWER_STATE : int
{
PwrDeviceUnspecified = -1,
D0 = 0, // Full On: full power, full functionality
D1 = 1, // Low Power On: fully functional at low power/performance
D2 = 2, // Standby: partially powered with automatic wake
D3 = 3, // Sleep: partially powered with device initiated wake
D4 = 4, // Off: unpowered
PwrDeviceMaximum = 5
}
[DllImport("coredll.dll", SetLastError = true)]
public static extern int DevicePowerNotify(string name, CEDEVICE_POWER_STATE state, int flags);
[DllImport("coredll.dll", SetLastError = true)]
public static extern int SetDevicePower(string name, int flags, CEDEVICE_POWER_STATE state);
[DllImport("coredll.dll", SetLastError = true)]
public static extern int GetDevicePower(string name, int flags, ref CEDEVICE_POWER_STATE state);
If I missed any, look them up on pinvoke.net.