2012-02-09 11 views
7

Mam problem z niestandardowymi kursorami w aplikacji WPF. Używam następujący kod do tworzenia Cursor obiekty:SafeFileHandle.Close zgłasza wyjątek, ale uchwyt jest ważny i działa

[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; 
} 

Kiedy zamykam moje podanie i GC zaczyna zbierając śmieci, zgłasza wyjątek:

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: 

zrobiłem kilka dalszych badań przez umieszczenie punkt przerwania na if (handle.IsClosed) i użycie bezpośredniego okna do wywołania handle.Close(). Niektóre z SafeFileHandle zamykają się dobrze, inne rzucają ten sam wyjątek — natychmiast po utworzeniu uchwytu.

I tylko po to, aby sprawić przyjemność, same uchwyty działają bez zarzutu. IsInvalid jest fałszywe, IsClosed jest fałszywe i pojawiają się kursory. Po prostu niektóre z uchwytów nigdy nie mogą być zamknięte.

Ponieważ nigdy nie zamierzam ręcznie zamykać uchwytów i będą one zamykane tylko podczas zamykania obiektów Cursor, gdy aplikacja się zamknie, być może będę mógł je zignorować. Nie próbowałem wersji Release poza VS2010 i nie wiem, czy spowoduje to pojawienie się okna dialogowego awarii. Ale nawet jeśli mogę je zignorować, nadal jest brudny.

Po prostu szukam informacji na temat tego, co może być nie tak, gdzie szukać, aby to sprawdzić ... wszystko wydaje się być w natywnym kodzie lub GC i nie mogę debugować żadnego z nich .

Odpowiedz

15

Ty owijania HICON wrócił z CreateIconIndirect w SafeFileHandle która na zwolnieniu, połączenia CloseHandle na HICON zamiast potrzebnej DestroyIcon. Nie zawijać HICON w SafeFileHandle lecz w naszej własnej produkcji, specjalizuje 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); 
    } 
} 
+0

Dzięki! Jestem całkiem nowy w WPF, nigdy nie robiłem WinForms, i to jest mój pierwszy kontakt z natywnym kodem. I dziękuję za usunięcie komentarza i zrobienie tego jako odpowiedź. :) –

+1

@RyanP Nie ma za co. Takie rzeczy można łatwo przeoczyć, zwłaszcza jeśli wszystko wydaje się działać na pierwszy rzut oka. – ordag

+0

Dzięki za to rozwiązanie! – Kai

Powiązane problemy