C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

カーソルをラインで描く /555 (19/07/31(Wed) 22:50) #91767
Re[1]: カーソルをラインで描く /魔界の仮面弁士 (19/08/01(Thu) 09:46) #91769
Re[1]: カーソルをラインで描く /KOZ (19/08/01(Thu) 09:27) #91768
  └ Re[2]: カーソルをラインで描く /555 (19/08/01(Thu) 12:04) #91774
    ├ Re[3]: カーソルをラインで描く /魔界の仮面弁士 (19/08/01(Thu) 12:35) #91775
    └ Re[3]: カーソルをラインで描く /KOZ (19/08/01(Thu) 12:43) #91776
      └ Re[4]: カーソルをラインで描く /KOZ (19/08/01(Thu) 12:46) #91777
        └ Re[5]: カーソルをラインで描く /555 (19/08/01(Thu) 13:20) #91778
          └ Re[6]: カーソルをラインで描く /KOZ (19/08/01(Thu) 13:22) #91779
            └ Re[7]: カーソルをラインで描く /555 (19/08/01(Thu) 13:34) #91780
              └ Re[8]: カーソルをラインで描く /KOZ (19/08/01(Thu) 13:43) #91781
                └ Re[9]: カーソルをラインで描く /555 (19/08/08(Thu) 17:09) #91895
                  └ Re[10]: カーソルをラインで描く /KOZ (19/08/08(Thu) 17:33) #91896


親記事 / ▼[ 91769 ] ▼[ 91768 ]
■91767 / 親階層)  カーソルをラインで描く
□投稿者/ 555 (1回)-(2019/07/31(Wed) 22:50:52)

分類:[.NET 全般] 

VB.NETを使っています。

マウスカーソルを
任意サイズの丸や四角に変更したいのですが、
どのようにすれば良いですか?

画像から読み込む方法だと、それぞれのサイズの画像を用意し
いちいち再読み込みする必要があるため、
不便です。
GDI+を使って描画可能でしたら教えてください。

[ □ Tree ] 返信 編集キー/

▲[ 91767 ] / 返信無し
■91769 / 1階層)  Re[1]: カーソルをラインで描く
□投稿者/ 魔界の仮面弁士 (2270回)-(2019/08/01(Thu) 09:46:10)
2019/08/01(Thu) 09:58:34 編集(投稿者)

No91767 (555 さん) に返信
> マウスカーソルを
> 任意サイズの丸や四角に変更したいのですが、
> どのようにすれば良いですか?

マウスをドラッグして描画処理を行う…という話ではなく、
マウスカーソルそのものを変更したいのでしょうか?


> 画像から読み込む方法だと、それぞれのサイズの画像を用意し
> いちいち再読み込みする必要があるため、
> 不便です。
> GDI+を使って描画可能でしたら教えてください。

何処に描画したいのでしょうか?

一時的な描画に限れば、Graphics.FromHdc を使うことで
デスクトップ上に直接描画できなくもないですが、この場合、
カーソル移動時等の再描画の面倒は自分で見る必要がありますし、
プライマリモニタ以外には描けません。GDI+ ではなく GDI なら描けますが。

https://puarts.com/?pid=1146
https://dobon.net/vb/bbs/log3-25/14968.html
https://dobon.net/vb/bbs/log3-25/14985.html


画像の動的な生成が可能なら、.CUR フォーマットの画像を用意してやり、
それを New Cursor(…) でロードして、Cursor プロパティに割り当てるのが正攻法です。
※ホットスポットが指定できなくても良ければ、.ICO フォーマットで代用も可。

ただし、Cursor プロパティを使う方法は、Windows カーソルの
制限上、カーソルサイズに制限が生じます。

また、New Cursor(Stream) や New Cursor(String) のコンストラクタで
ロードする場合、モノクロカーソルが前提となります。
カラーカーソル(あるいは .ANI フォーマットのカーソル)が
必要な場合、New Cursor(IntPtr) のコンストラクタを使います。



任意のサイズにしたい場合には、本来のカーソルを非表示にしておき、
現在のマウス座標位置に対して、目的のアイコン画像を表示させた Form を
レイヤード ウィンドウにして WS_EX_TRANSPARENT を指定した上で、
TopMost = True 状態でマウス座標にを追従させるという手もあります。
これなら GDI+ による描画とも併用できるかと。

 ' Opacity あるいは TransparencyKey を設定した Form
 Protected Overrides ReadOnly Property CreateParams() As CreateParams
  Get
   Const WS_EX_TRANSPARENT As Integer = &H20
   Dim cp As CreateParams = MyBase.CreateParams
   cp.ExStyle = cp.ExStyle Or WS_EX_TRANSPARENT
   Return cp
  End Get
 End Property

マウス座標への追従は、Timer で定期的に監視する方法や、
DirectInput でイベント受信する方法などがあります。


あとは、Windows 10 May 2019 Update (1903) 以降でサポートされた
.SVG フォーマットのベクター画像を使う方法もありますが、
今回の目的にはそぐわないでしょうね。
[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91767 ] / ▼[ 91774 ]
■91768 / 1階層)  Re[1]: カーソルをラインで描く
□投稿者/ KOZ (12回)-(2019/08/01(Thu) 09:27:45)
No91767 (555 さん) に返信
> GDI+を使って描画可能でしたら教えてください。

来年はオリンピックですね。ということで

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Using bmp As New Bitmap(32, 32)
            Using g As Graphics = Graphics.FromImage(bmp)
                Dim es As New Size(10, 10)
                g.DrawEllipse(Pens.Blue, New Rectangle(New Point(0, 0), es))
                g.DrawEllipse(Pens.Yellow, New Rectangle(New Point(es.Width \ 2, es.Height \ 2), es))
                g.DrawEllipse(Pens.Black, New Rectangle(New Point(es.Width, 0), es))
                g.DrawEllipse(Pens.Green, New Rectangle(New Point(es.Width * 3 \ 2, es.Height \ 2), es))
                g.DrawEllipse(Pens.Red, New Rectangle(New Point(es.Width * 2, 0), es))
            End Using
            Cursor = New Cursor(bmp.GetHicon())
        End Using
    End Sub

End Class

黄色が目立たないなあ

[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91768 ] / ▼[ 91775 ] ▼[ 91776 ]
■91774 / 2階層)  Re[2]: カーソルをラインで描く
□投稿者/ 555 (2回)-(2019/08/01(Thu) 12:04:02)
ありがとうございます。


KOZさんの方法でうまくいきました。

> マウスをドラッグして描画処理を行う…という話ではなく、
> マウスカーソルそのものを変更したいのでしょうか?

そうです。
photoshopのようなお絵描きソフトを作成しており、
その描画位置が分かるようなカーソルにしたいと考えています。

あと、この方法だとホットスポットが画像の中心になってしまうのですが、
これを中心以外に設定したい場合、どのようにすれば良いですか?


[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91774 ] / 返信無し
■91775 / 3階層)  Re[3]: カーソルをラインで描く
□投稿者/ 魔界の仮面弁士 (2273回)-(2019/08/01(Thu) 12:35:48)
No91774 (555 さん) に返信
> あと、この方法だとホットスポットが画像の中心になってしまうのですが、
> これを中心以外に設定したい場合、どのようにすれば良いですか?

ホットスポットを指定するには、HICON ではなく HCURSOR が必要です。
代替案としては、より大きなカーソルを用意して描画座標をずらすとか。

Using bmp As New Bitmap(64, 64), g As Graphics = Graphics.FromImage(bmp)
 g.TranslateTransform(32.0F, 32.0F)
 Dim es As New Size(10, 10)
 g.DrawEllipse(Pens.Blue, New Rectangle(New Point(0, 0), es))
 g.DrawEllipse(Pens.Yellow, New Rectangle(New Point(es.Width \ 2, es.Height \ 2), es))
 g.DrawEllipse(Pens.Black, New Rectangle(New Point(es.Width, 0), es))
 g.DrawEllipse(Pens.Green, New Rectangle(New Point(es.Width * 3 \ 2, es.Height \ 2), es))
 g.DrawEllipse(Pens.Red, New Rectangle(New Point(es.Width * 2, 0), es))
 Cursor = New Cursor(bmp.GetHicon())
End Using
[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91774 ] / ▼[ 91777 ]
■91776 / 3階層)  Re[3]: カーソルをラインで描く
□投稿者/ KOZ (13回)-(2019/08/01(Thu) 12:43:58)
No91774 (555 さん) に返信
> あと、この方法だとホットスポットが画像の中心になってしまうのですが、
> これを中心以外に設定したい場合、どのようにすれば良いですか?

Stack Overflow にありました。
https://stackoverflow.com/questions/550918/change-cursor-hotspot-in-winforms-net

GetIconInfo で ICONINFO を取得して CreateIconIndirect すれば良いようです。

Imports System.Runtime.InteropServices

Public Class Form1

<StructLayout(LayoutKind.Sequential)>
Public Class ICONINFO
Public fIcon As Integer
Public xHotspot As Integer
Public yHotspot As Integer
Public hbmMask As IntPtr = IntPtr.Zero
Public hbmColor As IntPtr = IntPtr.Zero
End Class

<DllImport("user32.dll")>
Private Shared Function GetIconInfo(hicon As IntPtr, ByVal iconinfo As ICONINFO) As Boolean
End Function

<DllImport("user32.dll")>
Private Shared Function CreateIconIndirect(ByVal iconinfo As ICONINFO) As IntPtr
End Function

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim proxy = System.Net.WebRequest.GetSystemWebProxy()
Using bmp As New Bitmap(32, 32)
Using g As Graphics = Graphics.FromImage(bmp)
Dim es As New Size(10, 10)
g.DrawEllipse(Pens.Blue, New Rectangle(New Point(0, 0), es))
g.DrawEllipse(Pens.Yellow, New Rectangle(New Point(es.Width \ 2, es.Height \ 2), es))
g.DrawEllipse(Pens.Black, New Rectangle(New Point(es.Width, 0), es))
g.DrawEllipse(Pens.Green, New Rectangle(New Point(es.Width * 3 \ 2, es.Height \ 2), es))
g.DrawEllipse(Pens.Red, New Rectangle(New Point(es.Width * 2, 0), es))
End Using
Using tmpIcon As New Cursor(bmp.GetHicon())
Dim info As New ICONINFO()
GetIconInfo(tmpIcon.Handle, info)
info.xHotspot = 0
info.yHotspot = 0
info.fIcon = False
Dim newIcon As IntPtr = CreateIconIndirect(info)
Cursor = New Cursor(newIcon)
End Using
End Using
End Sub

End Class

[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91776 ] / ▼[ 91778 ]
■91777 / 4階層)  Re[4]: カーソルをラインで描く
□投稿者/ KOZ (14回)-(2019/08/01(Thu) 12:46:27)
> Dim proxy = System.Net.WebRequest.GetSystemWebProxy()
なんか変なの混じってるけど気にしないでください。
[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91777 ] / ▼[ 91779 ]
■91778 / 5階層)  Re[5]: カーソルをラインで描く
□投稿者/ 555 (4回)-(2019/08/01(Thu) 13:20:05)
ありがとうございます。

パーフェクトでした!!!!!

ちなみに、
Cursor = New Cursor(newIcon)
と直接代入してしまっていますが、
最後にdisposeしなくても大丈夫なのでしょうか?

[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91778 ] / ▼[ 91780 ]
■91779 / 6階層)  Re[6]: カーソルをラインで描く
□投稿者/ KOZ (15回)-(2019/08/01(Thu) 13:22:16)
No91778 (555 さん) に返信
> 最後にdisposeしなくても大丈夫なのでしょうか?
new したインスタンスは Form.Corsor プロパティが保持しているので、Dispose したらまずいですよ。
[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91779 ] / ▼[ 91781 ]
■91780 / 7階層)  Re[7]: カーソルをラインで描く
□投稿者/ 555 (5回)-(2019/08/01(Thu) 13:34:38)
> new したインスタンスは Form.Corsor プロパティが保持しているので、Dispose したらまずいですよ。

プログラム起動中ではなく
終了時に必要ですか、という意味です。

[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91780 ] / ▼[ 91895 ]
■91781 / 8階層)  Re[8]: カーソルをラインで描く
□投稿者/ KOZ (16回)-(2019/08/01(Thu) 13:43:02)
No91780 (555 さん) に返信
> プログラム起動中ではなく
> 終了時に必要ですか、という意味です。

もちろん、Dispose してから終了、というのが望ましい形ではありますが
Cursor の実装を見ると、デストラクタから Dispose(false) を呼び出しているので
放置しても問題ないと思います。

[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91781 ] / ▼[ 91896 ]
■91895 / 9階層)  Re[9]: カーソルをラインで描く
□投稿者/ 555 (6回)-(2019/08/08(Thu) 17:09:28)

ありがとうございます。

> Cursor の実装を見ると、デストラクタから Dispose(false) を呼び出しているので

これってどこを見れば分かりますか?

あと、PictureBox1.Cursorの場合も
自動でdisposeしてくれているのでしょうか?


[ 親 91767 / □ Tree ] 返信 編集キー/

▲[ 91895 ] / 返信無し
■91896 / 10階層)  Re[10]: カーソルをラインで描く
□投稿者/ KOZ (23回)-(2019/08/08(Thu) 17:33:32)
No91895 (555 さん) に返信
>>Cursor の実装を見ると、デストラクタから Dispose(false) を呼び出しているので
> これってどこを見れば分かりますか?

.NET のソースです。
https://referencesource.microsoft.com/
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Cursor.cs

> あと、PictureBox1.Cursorの場合も
> 自動でdisposeしてくれているのでしょうか?

上で言っているのは Cursor クラスのことで、プロパティは関係ありません。
デストラクタはコンストラクタの反対で GC がオブジェクトを回収するとき呼び出します。

[ 親 91767 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -