diff --git a/src/System.Windows.Forms.Primitives/tests/UnitTests/Interop/Mocks/MockCursor.cs b/src/System.Windows.Forms.Primitives/tests/UnitTests/Interop/Mocks/MockCursor.cs
index 2e2e9dd50f1..618ef825740 100644
--- a/src/System.Windows.Forms.Primitives/tests/UnitTests/Interop/Mocks/MockCursor.cs
+++ b/src/System.Windows.Forms.Primitives/tests/UnitTests/Interop/Mocks/MockCursor.cs
@@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.ComponentModel;
using System.Drawing;
+using System.Runtime.InteropServices;
namespace System.Windows.Forms.Primitives.Tests.Interop.Mocks
{
@@ -18,37 +20,23 @@ internal MockCursor(PCWSTR nResourceId)
_ownHandle = false;
_resourceId = nResourceId;
_handle = PInvoke.LoadCursor(HINSTANCE.Null, nResourceId);
+ if (_handle.IsNull)
+ {
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
}
public void Dispose()
{
- if (!_handle.IsNull)
+ if (!_handle.IsNull && _ownHandle)
{
- if (_ownHandle)
- {
- PInvoke.DestroyCursor(_handle);
- }
-
+ PInvoke.DestroyCursor(_handle);
_handle = HCURSOR.Null;
}
}
- internal HCURSOR Handle
- {
- get
- {
- if (_handle.IsNull)
- {
- throw new ObjectDisposedException(nameof(MockCursor));
- }
-
- return _handle;
- }
- }
+ internal HCURSOR Handle => _handle.IsNull ? throw new ObjectDisposedException(nameof(MockCursor)) : _handle;
- public Size Size
- {
- get => SystemInformation.CursorSize;
- }
+ public Size Size => SystemInformation.CursorSize;
}
}
diff --git a/src/System.Windows.Forms/src/Resources/SR.resx b/src/System.Windows.Forms/src/Resources/SR.resx
index ef0874fa370..716535574f5 100644
--- a/src/System.Windows.Forms/src/Resources/SR.resx
+++ b/src/System.Windows.Forms/src/Resources/SR.resx
@@ -6961,4 +6961,7 @@ Stack trace where the illegal operation occurred was:
Argument '{0}' must be of type '{1}'.
+
+ Failed to load cursor. Error '{1}'.
+
\ No newline at end of file
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf
index 05180451eef..bb2a0ad2415 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf
@@ -5021,6 +5021,11 @@ Pokud kliknete na Pokračovat, aplikace bude tuto chybu ignorovat a pokusí se p
Určuje, zda dialogové okno zajišťuje, že názvy souborů neobsahují neplatné znaky nebo posloupnosti.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Určuje, jestli se má soubor, který se otevírá nebo ukládá, přidat do seznamu posledních souborů.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf
index a2eaf7b8fba..34459e9fbe0 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf
@@ -5021,6 +5021,11 @@ Wenn Sie auf "Weiter" klicken, ignoriert die Anwendung den Fehler und setzt den
Steuert, ob das Dialogfeld sicherstellt, dass Dateinamen keine ungültigen Zeichen oder Sequenzen enthalten.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Steuert, ob die Datei, die geöffnet oder gespeichert wird, zur Liste zuletzt verwendeten Elemente hinzugefügt wird.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf
index e972a42b1d8..41be70b3be7 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf
@@ -5021,6 +5021,11 @@ Si hace clic en Continuar, la aplicación pasará por alto este error e intentar
Controla si el cuadro de diálogo comprueba que los nombres de archivo no contienen caracteres o secuencias no válidas.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Controla si se va a agregar el archivo que se va a abrir o guardar en la lista reciente.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf
index ab9bc0ee5ac..2de87108bdf 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf
@@ -5021,6 +5021,11 @@ Si vous cliquez sur Continuer, l'application va ignorer cette erreur et tenter d
Contrôle si la boîte de dialogue s'assure que les noms de fichiers ne contiennent pas de caractères ou de séquences non valides.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Contrôle s'il faut ajouter le fichier en cours d'ouverture ou d'enregistrement à la liste récente.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf
index 071f0e3da7d..8e0e20377ad 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf
@@ -5021,6 +5021,11 @@ Se si sceglie Continua, l'errore verrà ignorato e l'applicazione proverà a con
Determina se la finestra di dialogo ha il compito di verificare che i nomi di file non contengano caratteri o sequenze non valide.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Controlla se aggiungere il file aperto o salvato nell'elenco degli elementi recenti.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf
index 9255b6946f9..a63d9ed61b3 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf
@@ -5021,6 +5021,11 @@ If you click Continue, the application will ignore this error and attempt to con
無効な文字やシーケンスがファイル名に含まれていないことをダイアログ ボックスが確認するかどうかを設定します。
+
+
+ Failed to load cursor. Error '{1}'.
+
+ 開いているファイルを追加するか、最近使用したリストに保存するかを制御します。
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf
index c79cc8b3db4..4990a37135d 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf
@@ -5021,6 +5021,11 @@ If you click Continue, the application will ignore this error and attempt to con
대화 상자에서 파일 이름에 잘못된 문자나 시퀀스가 없는지 확인할지 여부를 제어합니다.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ 연 파일 또는 저장한 파일을 최근 목록에 추가할지를 제어합니다.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf
index 23158017a94..1eb7e8b2db3 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf
@@ -5021,6 +5021,11 @@ Jeśli klikniesz pozycję Kontynuuj, aplikacja zignoruje ten błąd i będzie pr
Kontroluje, czy w oknie dialogowym nazwy plików nie zawierają nieprawidłowych znaków ani sekwencji.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Określa, czy dodać otwierany lub zapisywany plik do listy ostatnio używanych.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf
index 027be9a27c6..5dcc95af440 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf
@@ -5021,6 +5021,11 @@ Se você clicar em Continuar, o aplicativo ignorará esse erro e tentará contin
Controla se a caixa de diálogo assegura que os nomes de arquivos não contém cadeias ou caracteres inválidos.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Controla se o arquivo que está sendo aberto ou salvo na lista recente deve ser adicionado.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf
index dd972040721..da9ff7d64ff 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf
@@ -5022,6 +5022,11 @@ If you click Continue, the application will ignore this error and attempt to con
Определяет, проверяет ли диалоговое окно имена файлов на наличие недопустимых символов или последовательностей.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Определяет, следует ли добавлять открываемый или сохраненный файл в список "Последние".
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf
index 153f31728b6..88eb2cebcaa 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf
@@ -5021,6 +5021,11 @@ Devam'a tıkladığınızda uygulama bu hatayı yoksayar ve işlemi sürdürmeye
İletişim kutusunun dosya adlarında geçersiz karakterler ve sıralar içermediğinden emin olup olmayacağını denetler.
+
+
+ Failed to load cursor. Error '{1}'.
+
+ Açılmakta olan veya kaydedilen dosyanın son listeye eklenip eklenmeyeceğini kontrol eder.
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf
index e9bd42be763..66b160073f3 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf
@@ -5021,6 +5021,11 @@ If you click Continue, the application will ignore this error and attempt to con
控制对话框是否确保文件名中不包含无效的字符或序列。
+
+
+ Failed to load cursor. Error '{1}'.
+
+ 控制是否将打开或保存的文件添加到最近使用项列表中。
diff --git a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf
index ee07d32baa2..42918d30856 100644
--- a/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf
+++ b/src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf
@@ -5021,6 +5021,11 @@ If you click Continue, the application will ignore this error and attempt to con
控制對話方塊是否要確認檔名並未包含無效的字元或逸出字元。
+
+
+ Failed to load cursor. Error '{1}'.
+
+ 控制是否新增開啟或儲存至最近使用之清單的檔案。
diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs
index 4cd0b7a81bf..bed16cdd109 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/Cursor.cs
@@ -39,6 +39,10 @@ internal unsafe Cursor(PCWSTR nResourceId)
_ownHandle = false;
_resourceId = nResourceId;
_handle = PInvoke.LoadCursor((HINSTANCE)0, nResourceId);
+ if (_handle.IsNull)
+ {
+ throw new Win32Exception(string.Format(SR.FailedToLoadCursor, Marshal.GetLastWin32Error()));
+ }
}
///
@@ -222,13 +226,9 @@ public void Dispose()
private void Dispose(bool disposing)
{
- if (!_handle.IsNull)
+ if (!_handle.IsNull && _ownHandle)
{
- if (_ownHandle)
- {
- PInvoke.DestroyCursor(_handle);
- }
-
+ PInvoke.DestroyCursor(_handle);
_handle = HCURSOR.Null;
}
}
@@ -430,6 +430,11 @@ private unsafe void LoadPicture(IStream.Interface stream, string paramName)
picSize.Height,
IMAGE_FLAGS.LR_DEFAULTCOLOR).Value;
+ if (_handle.IsNull)
+ {
+ throw new Win32Exception(string.Format(SR.FailedToLoadCursor, Marshal.GetLastWin32Error()));
+ }
+
_ownHandle = true;
}
else
@@ -461,6 +466,8 @@ internal unsafe byte[] GetData()
return (byte[])_cursorData.Clone();
}
+ internal bool IsValid() => _handle != IntPtr.Zero;
+
///
/// Displays the cursor. For every call to Cursor.show() there must have been
/// a previous call to Cursor.hide().
diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Cursors.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Cursors.cs
index b12b52770de..28412c34048 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/Cursors.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/Cursors.cs
@@ -65,33 +65,37 @@ public static class Cursors
public static Cursor WaitCursor => s_wait ??= new Cursor(PInvoke.IDC_WAIT);
public static Cursor Help => s_help ??= new Cursor(PInvoke.IDC_HELP);
+ public static Cursor Hand => s_hand ??= new Cursor(PInvoke.IDC_HAND);
- public static Cursor HSplit => s_hSplit ??= new Cursor(typeof(Cursor), "hsplit.cur");
+ public static Cursor HSplit => GetCursor(ref s_hSplit, "hsplit.cur");
- public static Cursor VSplit => s_vSplit ??= new Cursor(typeof(Cursor), "vsplit.cur");
+ public static Cursor VSplit => GetCursor(ref s_vSplit, "vsplit.cur");
- public static Cursor NoMove2D => s_noMove2D ??= new Cursor(typeof(Cursor), "nomove2d.cur");
+ public static Cursor NoMove2D => GetCursor(ref s_noMove2D, "nomove2d.cur");
- public static Cursor NoMoveHoriz => s_noMoveHoriz ??= new Cursor(typeof(Cursor), "nomoveh.cur");
+ public static Cursor NoMoveHoriz => GetCursor(ref s_noMoveHoriz, "nomoveh.cur");
- public static Cursor NoMoveVert => s_noMoveVert ??= new Cursor(typeof(Cursor), "nomovev.cur");
+ public static Cursor NoMoveVert => GetCursor(ref s_noMoveVert, "nomovev.cur");
- public static Cursor PanEast => s_panEast ??= new Cursor(typeof(Cursor), "east.cur");
+ public static Cursor PanEast => GetCursor(ref s_panEast, "east.cur");
- public static Cursor PanNE => s_panNE ??= new Cursor(typeof(Cursor), "ne.cur");
+ public static Cursor PanNE => GetCursor(ref s_panNE, "ne.cur");
- public static Cursor PanNorth => s_panNorth ??= new Cursor(typeof(Cursor), "north.cur");
+ public static Cursor PanNorth => GetCursor(ref s_panNorth, "north.cur");
- public static Cursor PanNW => s_panNW ??= new Cursor(typeof(Cursor), "nw.cur");
+ public static Cursor PanNW => GetCursor(ref s_panNW, "nw.cur");
- public static Cursor PanSE => s_panSE ??= new Cursor(typeof(Cursor), "se.cur");
+ public static Cursor PanSE => GetCursor(ref s_panSE, "se.cur");
- public static Cursor PanSouth => s_panSouth ??= new Cursor(typeof(Cursor), "south.cur");
+ public static Cursor PanSouth => GetCursor(ref s_panSouth, "south.cur");
- public static Cursor PanSW => s_panSW ??= new Cursor(typeof(Cursor), "sw.cur");
+ public static Cursor PanSW => GetCursor(ref s_panSW, "sw.cur");
- public static Cursor PanWest => s_panWest ??= new Cursor(typeof(Cursor), "west.cur");
+ public static Cursor PanWest => GetCursor(ref s_panWest, "west.cur");
- public static Cursor Hand => s_hand ??= new Cursor(PInvoke.IDC_HAND);
+ private static Cursor GetCursor(ref Cursor? cursor, string resource)
+ => cursor is not null && cursor.IsValid()
+ ? cursor
+ : cursor = new Cursor(typeof(Cursor), resource);
}
}
diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CursorTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CursorTests.cs
index 9539573623c..f34b0c2e582 100644
--- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CursorTests.cs
+++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CursorTests.cs
@@ -358,12 +358,8 @@ public void Cursor_Dispose_InvokeNotOwned_Success()
var cursor = new Cursor(2);
cursor.Dispose();
- Assert.Throws(() => cursor.Handle);
- Assert.Throws(() => cursor.HotSpot);
-
- cursor.Dispose();
- Assert.Throws(() => cursor.Handle);
- Assert.Throws(() => cursor.HotSpot);
+ // Cursors not owned should not be disposed.
+ Assert.NotEqual(IntPtr.Zero, cursor.Handle);
}
public static IEnumerable