我在WPF应用程序中遇到自定义游标的问题.我使用以下代码来创建Cursor对象:
[DllImport("user32.dll")]
private static extern IntPtr CreateIconIndirect(ref IconInfo icon);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
private static Cursor CreateCursor(string cursorName, System.Drawing.Bitmap bmp,
int xHotspot, int yHotspot, out SafeFileHandle handle)
{
IconInfo tmp = new IconInfo();
GetIconInfo(bmp.GetHicon(), ref tmp);
tmp.xHotspot = xHotspot;
tmp.yHotspot = yHotspot;
tmp.fIcon = false;
IntPtr ptr = CreateIconIndirect(ref tmp);
handle = new SafeFileHandle(ptr, true);
if (handle.IsClosed)
{
return null;
}
Cursor cur = CursorInteropHelper.Create(handle);
return cur;
}
Run Code Online (Sandbox Code Playgroud)
当我关闭我的应用程序并且GC开始拾取垃圾时,它会引发异常:
System.Runtime.InteropServices.SEHException was unhandled
Message=External component has thrown an exception.
Source=mscorlib
ErrorCode=-2147467259
StackTrace:
at Microsoft.Win32.Win32Native.CloseHandle(IntPtr handle)
at Microsoft.Win32.SafeHandles.SafeFileHandle.ReleaseHandle()
at System.Runtime.InteropServices.SafeHandle.InternalDispose()
at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
at System.Runtime.InteropServices.SafeHandle.Dispose()
at System.Windows.Input.Cursor.Finalize()
InnerException:
Run Code Online (Sandbox Code Playgroud)
我通过在断点上设置断点if (handle.IsClosed)并使用即时窗口来进行进一步调查handle.Close().一些SafeFileHandle关闭就好了,其他人抛出相同的异常 - 在创建句柄后立即生效.
只是为了让事情变得有趣,手柄本身也很好用.IsInvalid是假的,IsClosed是假的,游标出现了.只是有些句柄永远不会被关闭.
正如我从来没有打算手动关闭手柄,他们将只定稿期间被关闭Cursor,当应用程序关闭的对象,我也许可以不理会他们.我没有在VS2010之外尝试过Release版本,我不知道是否会导致出现崩溃对话框.但即使我可以忽略它们,它仍然是凌乱的.
所以基本上我正在寻找的任何信息上什么可能在这里走错了,到哪里尝试和调试这......似乎一切都在本机代码或GC,我不能调试任何它.
ord*_*dag 16
你的包裹HICON从返回CreateIconIndirect在SafeFileHandle其上发布,呼吁CloseHandle对HICON,而不是需要的DestroyIcon.不要包装HICON,SafeFileHandle而是专注于自己的SafeHandle:
class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DestroyIcon(
[In] IntPtr hIcon);
private SafeIconHandle()
: base(true)
{
}
public SafeIconHandle(IntPtr hIcon)
: base(true)
{
this.SetHandle(hIcon);
}
protected override bool ReleaseHandle()
{
return DestroyIcon(this.handle);
}
}
Run Code Online (Sandbox Code Playgroud)