はじめに
pyautoguiでマウスカーソル形状で判定するためにwin32gui.GetCursorInfo()で状態を取得していましたが、返り値であるハンドルがどの形状を表しているのかいまいちわかっていなかったので調べてみました。
マウスカーソル形状の種類
そもそもWindows標準のマウスカーソル形状は以下のようなものがあるようです。
(画像引用元:https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/617changecursor/changecursor.html)

win32gui.GetCursorInfo()で得られる返り値
参考としたサイトから、win32con.IDC_*で設定される定数から、win32gui.LoadCursor(0, win32con.IDC_*)でハンドルが得られることがわかりました。
| 返り値 | win32con 定数名 |
win32con 定数値 |
意味 |
|---|---|---|---|
| 65561 | IDC_APPSTARTING | 32650 | 標準の矢印カーソルと小さい砂時計カーソル |
| 65539 | IDC_ARROW | 32512 | 標準の矢印カーソル |
| 65545 | IDC_CROSS | 32515 | 十字カーソル |
| 65567 | IDC_HAND | 32649 | Windows 2000:ハンドカーソル |
| 65563 | IDC_HELP | 32651 | 矢印と疑問符 |
| 65541 | IDC_IBEAM | 32513 | アイビーム( 縦線)カーソル |
| 0 | IDC_ICON | 32641 | 使われていない*。代わりにIDC_ARROWを使う。 |
| 65559 | IDC_NO | 32648 | 禁止カーソル( 円に左上から右下への斜線) |
| 0 | IDC_SIZE | 32640 | 使われていない*。代わりに IDC_SIZEALL を使う。 |
| 65557 | IDC_SIZEALL | 32646 | 4 方向の矢印カーソル |
| 65551 | IDC_SIZENESW | 32643 | 右上と左下を指す両方向矢印カーソル |
| 65555 | IDC_SIZENS | 32645 | 上下を指す両方向矢印カーソル |
| 65549 | IDC_SIZENWSE | 32642 | 左上と右下を指す両方向矢印カーソル |
| 65553 | IDC_SIZEWE | 32644 | 左右を指す両方向矢印カーソル |
| 65547 | IDC_UPARROW | 32516 | 上を指す垂直の矢印カーソル |
| 65543 | IDC_WAIT | 32514 | 砂時計カーソル |
* バージョンが 4.0 以降(Windows NT 4.0 以降)とマークされたアプリケーションにおいて
一覧は以下のコードから得られます(「意味」は参考サイトを引用)。
import win32con
from win32gui import LoadCursor
DEFAULT_CURSORS = {
win32con.IDC_APPSTARTING: 'appStarting',
win32con.IDC_ARROW: 'Arrow',
win32con.IDC_CROSS: 'Cross',
win32con.IDC_HAND: 'Hand',
win32con.IDC_HELP: 'Help',
win32con.IDC_IBEAM: 'IBeam',
win32con.IDC_ICON: 'ICon',
win32con.IDC_NO: 'No',
win32con.IDC_SIZE: 'Size',
win32con.IDC_SIZEALL: 'sizeAll',
win32con.IDC_SIZENESW: 'sizeNESW',
win32con.IDC_SIZENS: 'sizeNS',
win32con.IDC_SIZENWSE: 'sizeNWSE',
win32con.IDC_SIZEWE: 'sizeWE',
win32con.IDC_UPARROW: 'upArrow',
win32con.IDC_WAIT: 'Wait',
}
for key, value in DEFAULT_CURSORS.items():
print(f'{LoadCursor(0, key)}, {key}, {value}')
65561, 32650, appStarting
65539, 32512, Arrow
65545, 32515, Cross
65567, 32649, Hand
65563, 32651, Help
65541, 32513, IBeam
0, 32641, ICon
65559, 32648, No
0, 32640, Size
65557, 32646, sizeAll
65551, 32643, sizeNESW
65555, 32645, sizeNS
65549, 32642, sizeNWSE
65553, 32644, sizeWE
65547, 32516, upArrow
65543, 32514, Wait
pyautoguiでの使用例
というわけで、pyautoguiで判定する際には以下のような関数が、意図するところがわかりやすい気がしています。
import pyautogui
from win32con import IDC_APPSTARTING, IDC_WAIT
from win32gui import LoadCursor, GetCursorInfo
def wait_hourglass(**kwargs):
wait_limit = kwargs.pop('wait_limit', 60) * 5
hourglass = [LoadCursor(0, IDC_APPSTARTING), LoadCursor(0, IDC_WAIT)]
for _ in range(wait_limit):
pyautogui.failSafeCheck()
if GetCursorInfo()[1] not in hourglass:
return GetCursorInfo()[1]
sleep(0.2)
raise TimeoutError()
参考サイト