Found a solution! (or at least a workaround)
Instead of using MouseUp or an API call (neither of which I now believe will logically work) I set up a Timer object. When the user clicks down on an object in the list the timer starts. Every 10th of a second it checks to see if the left mouse button has been released. If it has, and the mouse is outside the form, the item gets removed from the list.
The relevant code:
using System.Timers;
public class form1: Form
{
private System.Timers.Timer clickDetector;
private ListView listToRemoveFrom;
private ListViewItem itemBeingMoved;
public form1()
{
InitializeComponent();
//We create the timer, set it to go off every tenth of a second,
//and set the method to be done at each interval.
clickDetector = new System.Timers.Timer();
clickDetector.Interval = 100;
clickDetector.Elapsed += checkMouseState;
}
//This function checks whether the mouse button is no longer up (i.e. the mouseButton
//is property is "None") and if the mouse is outside the form. If so remove the item
//being dragged
public void checkMouseState(object source, ElapsedEventArgs e)
{
if(outsideOfForm() && Control.MouseButtons.ToString() == "None")
removeItemFromList();
}
//Is the mouse outside of the form?
public bool outsideOfForm()
{
if (MousePosition.X < this.Location.X || MousePosition.X > (this.Location.X + this.Width) ||
MousePosition.Y < this.Location.Y || MousePosition.Y > (this.Location.Y + this.Height))
{
return true;
}
return false;
}
public delegate void setRemoveItemFromList();
public void removeItemFromList()
{
/* The timer runs on a separate thread than the form, so we have to use
a bit of "delegate magic" to access a control on the form */
if (listToRemoveFrom.InvokeRequired)
{
setRemoveItemFromList remove = new setRemoveItemFromList(removeItemFromList);
this.Invoke(remove);
}
else
{
listToRemoveFrom.Items.Remove(itemBeingMoved);
//There's no point in having the timer run all the time
clickDetector.Stop();
}
}
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
//Start the timer only if the left mouse button has clicked on an item
//in the listView
if (e.Button != MouseButtons.Left)
{
return;
}
if (((ListView)sender).GetItemAt(e.X, e.Y) == null)
{
return;
}
clickDetector.Start();
listToRemoveFrom = (ListView)sender;
itemBeingMoved = ((ListView)sender).GetItemAt(e.X, e.Y);
}
}