After more searching, I found there is a function in user32.dll called ClipCursor that does exactly what I want.
Here is an example of a sample app that traps the mouse cursor. When clicking Button1, the cursor will be constrained in a rectangle at (10,10,500,500). When pressing Button2 (or closing the app), the cursor will be free again.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,41,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" />
</Grid>
</Window>
CS:
[DllImport("user32.dll")]
static extern void ClipCursor(ref System.Drawing.Rectangle rect);
[DllImport("user32.dll")]
static extern void ClipCursor(IntPtr rect);
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
System.Drawing.Rectangle r = new System.Drawing.Rectangle(10, 10, 500, 500);
ClipCursor(ref r);
}
private void button2_Click(object sender, RoutedEventArgs e)
{
ClipCursor(IntPtr.Zero);
}