/// <summary> /// グローバルのカーソルの情報を取得する /// </summary> /// <exception cref="PlatformInvokeException"> /// Win32Apiの処理「DLL:user32.dll、メソッド:GetCursorInfo」の呼び出しに失敗した場合に発生 /// </exception> /// <exception cref="Win32OperateException"> /// Win32Apiの処理「DLL:user32.dll、メソッド:GetCursorInfo」の処理に失敗した場合に発生 /// </exception> /// <returns>取得したカーソル情報</returns> private static Cursor.CURSORINFO GetCursorInfo() { // Win32Apiの実行処理 // Win32ApiのWindou共通の呼び出し機能を用いて、グローバルのカーソルの情報を取得処理を呼び出す Win32ApiResult Function() { Cursor.CURSORINFO info = new Cursor.CURSORINFO { StructureSize = Marshal.SizeOf(typeof(Cursor.CURSORINFO)), }; bool win32Result = Win32Api.GetCursorInfo(ref info); int win32ErrorCode = Marshal.GetLastWin32Error(); return(new Win32ApiResult(info, win32Result, win32ErrorCode)); } // 実行 string dllName = "user32.dll"; string methodName = nameof(Win32Api.GetCursorInfo); Win32ApiResult result = Win32ApiCommon.Run(Function, dllName, methodName); // 正常終了したかチェック if (!result.Result && result.ErrorCode != (int)ErrorCode.NO_ERROR) { throw Win32ApiCommon.GetWin32OperateException(dllName, methodName, result.ErrorCode); } // 取得したカーソル情報を返却 return((Cursor.CURSORINFO)result.ReturnValue); }
/// <summary> /// 現在のカーソルをキャプチャする(画像、座標情報を取得) /// </summary> /// <param name="backgroundImage"> /// Iビームカーソル等の背景に応じで色が変化するカーソルを、 /// 正確に描画するために使用するカーソルの下にある背景画像 /// (NULLを指定した場合、白一色の背景としてカーソルをキャプチャする) /// </param> /// <param name="backgroundImageScreenPoint"> /// 背景画像の画面上の座標(画像の左上の絶対座標) /// </param> /// <exception cref="PlatformInvokeException"> /// Win32Apiの下記の処理の呼び出しに失敗した場合に発生 /// ・「DLL:user32.dll、メソッド:GetCursorInfo」 /// ・「DLL:user32.dll、メソッド:CopyIcon」 /// ・「DLL:user32.dll、メソッド:GetIconInfo」 /// ・「DLL:gdi32.dll、メソッド:CreateCompatibleDC」 /// ・「DLL:gdi32.dll、メソッド:SelectObject」 /// ・「DLL:gdi32.dll、メソッド:BitBlt」 /// ・「DLL:gdi32.dll、メソッド:DeleteObject」 /// ・「DLL:gdi32.dll、メソッド:DeleteDC」 /// ・「DLL:user32.dll、メソッド:DestroyIcon」 /// </exception> /// <exception cref="Win32OperateException"> /// Win32Apiの下記の処理に失敗した場合に発生 /// ・「DLL:user32.dll、メソッド:GetCursorInfo」 /// ・「DLL:user32.dll、メソッド:CopyIcon」 /// ・「DLL:user32.dll、メソッド:GetIconInfo」 /// ・「DLL:gdi32.dll、メソッド:CreateCompatibleDC」 /// ・「DLL:gdi32.dll、メソッド:SelectObject」 /// ・「DLL:gdi32.dll、メソッド:BitBlt」 /// ・「DLL:gdi32.dll、メソッド:DeleteObject」 /// ・「DLL:gdi32.dll、メソッド:DeleteDC」 /// ・「DLL:user32.dll、メソッド:DestroyIcon」 /// </exception> /// <returns> /// 現在のカーソルの画像、座標情報 /// (カーソルが取得できない場合はNULLを返却する) /// </returns> public static CursorInfo CaptureCurrentCursor( Bitmap backgroundImage, Point backgroundImageScreenPoint) { // カーソル情報を取得 Cursor.CURSORINFO cursorInfo = GetCursorInfo(); if (cursorInfo.Flag != (int)Cursor.State.CURSOR_SHOWING) { // カーソルを表示していない場合、NULL を返却する return(null); } // アイコン用のハンドルを宣言 SafeCopyIconHandle iconHandle = null; IconInfo.ICONINFO iconInfo = default; try { // システムからアイコンのハンドルをコピーしておく iconHandle = CopyIcon(cursorInfo.CursorHandle); // アイコン情報を取得 iconInfo = GetIconInfo(iconHandle); // 取得したアイコン情報がカーソルでない場合、NULL を返却する if (iconInfo.IsIcon) { return(null); } // カーソルの座標を取得 // 絶対座標(カーソルのホットスポットの分値を補正する) Point screenPoint = new Point( x: cursorInfo.ScreenPosition.X - iconInfo.HotspotX, y: cursorInfo.ScreenPosition.Y - iconInfo.HotspotY); // 背景画像からの相対座標 Point imagePoint = new Point( x: screenPoint.X - backgroundImageScreenPoint.X, y: screenPoint.Y - backgroundImageScreenPoint.Y); // カーソルの画像を取得 Bitmap cursorImage; if (backgroundImage != null) { cursorImage = GetCursorImage(iconHandle, iconInfo, backgroundImage, imagePoint); } else { cursorImage = GetCursorImage(iconHandle, iconInfo); } // カーソルの画像が取得できない場合は NULL を返す if (cursorImage == null) { return(null); } // カーソル情報を生成して返す return(new CursorInfo(cursorImage, screenPoint, imagePoint)); } finally { try { // アイコン情報のマスクと画像情報を破棄する if (!iconInfo.Equals(default(IconInfo.ICONINFO))) { DeleteObject(iconInfo.MaskBitmapHandle); DeleteObject(iconInfo.ColorBitmapHandle); } } finally { // アイコンを破棄する iconHandle?.Dispose(); } } }