その他のマウス操作
前のセクションでは、マウスのクリックとマウスの動きについて説明しました。 マウスで実行できるその他の操作を次に示します。
UI 要素のドラッグ
UI で UI 要素のドラッグがサポートされている場合は、マウスダウン メッセージ ハンドラーで呼び出す必要があるもう 1 つの関数 DragDetect があります。 ドラッグと解釈する必要があるマウス ジェスチャをユーザーが開始した場合、 DragDetect 関数は TRUE を 返します。 次のコードは、この関数の使用方法を示しています。
case WM_LBUTTONDOWN:
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (DragDetect(m_hwnd, pt))
{
// Start dragging.
}
}
return 0;
アイデアは次のとおりです。プログラムがドラッグ アンド ドロップをサポートしている場合、すべてのマウス クリックをドラッグとして解釈する必要はありません。 それ以外の場合、ユーザーは、単にクリックする場合 (たとえば、選択する場合) に、誤って何かをドラッグする可能性があります。 しかし、マウスが特に敏感な場合は、クリック中にマウスを完全に維持するのは難しい場合があります。 したがって、Windows では、数ピクセルのドラッグしきい値が定義されています。 ユーザーがマウス ボタンを押すと、マウスがこのしきい値を超えない限り、ドラッグとは見なされません。 DragDetect 関数は、このしきい値に達したかどうかをテストします。 関数が TRUE を返す場合は、マウス クリックをドラッグとして解釈できます。 それ以外の場合は、しないでください。
注意
DragDetect がFALSE を返す場合、ユーザーがマウス ボタンを離したときに、WM_LBUTTONUP メッセージが抑制されます。 したがって、プログラムが現在ドラッグをサポートするモードでない限り、 DragDetect を呼び出さないでください。 (たとえば、ドラッグ可能な UI 要素が既に選択されている場合など)。このモジュールの最後には、 DragDetect 関数を使用するより長いコード例が表示されます。
カーソルの閉じ込め
クライアント領域またはクライアント領域の一部にカーソルを制限したい場合があります。 ClipCursor 関数は、カーソルの移動を指定した四角形に制限します。 この四角形はクライアント座標ではなく画面座標で指定されるため、ポイント (0,0) は画面の左上隅を意味します。 クライアント座標を画面座標に変換するには、 ClientToScreen 関数を呼び出します。
次のコードは、カーソルをウィンドウのクライアント領域に限定します。
// Get the window client area.
RECT rc;
GetClientRect(m_hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(m_hwnd, &pt);
ClientToScreen(m_hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
// Confine the cursor.
ClipCursor(&rc);
ClipCursor は RECT 構造体を受け取りますが、 ClientToScreen は POINT 構造体を受け取ります。 四角形は、左上と右下の点で定義されます。 ウィンドウの外側の領域を含め、任意の四角形の領域にカーソルを閉じ込めることができますが、カーソルをクライアント領域に限定することは、関数を使用する一般的な方法です。 ウィンドウの外側の領域にカーソルを完全に閉じ込めるのは通常とは異なるものであり、ユーザーはおそらくそれをバグとして認識します。
制限を解除するには、値 NULL を指定して ClipCursor を呼び出します。
ClipCursor(NULL);
マウス追跡イベント: ホバーして離れる
他の 2 つのマウス メッセージは既定で無効になっていますが、一部のアプリケーションで役立つ場合があります。
- WM_MOUSEHOVER: カーソルが一定期間クライアント領域の上にカーソルを置いています。
- WM_MOUSELEAVE: カーソルがクライアント領域を離れた。
これらのメッセージを有効にするには、 TrackMouseEvent 関数を呼び出します。
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
TRACKMOUSEEVENT 構造体には、関数のパラメーターが含まれています。 構造体の dwFlags メンバーには、関心のある追跡メッセージを指定するビット フラグが含まれています。 次に示すように、 WM_MOUSEHOVER と WM_MOUSELEAVEの両方を取得するか、2 つのうちの 1 つだけを取得することを選択できます。 dwHoverTime メンバーは、システムがホバー メッセージを生成するまでにマウスをポイントする必要がある時間を指定します。 この値はミリ秒単位で指定されます。 定数 HOVER_DEFAULT は、システムの既定値を使用することを意味します。
要求したメッセージの 1 つを取得すると、 TrackMouseEvent 関数がリセットされます。 もう一度呼び出して、別の追跡メッセージを取得する必要があります。 ただし、次のマウス移動メッセージが表示されるまで待ってから、 TrackMouseEvent を再度呼び出す必要があります。 そうしないと、ウィンドウに追跡メッセージが殺到する可能性があります。 たとえば、マウスがホバーしている場合、システムはマウスが静止している間 もWM_MOUSEHOVER メッセージのストリームを生成し続けます。 マウスが別の場所に移動してもう一度ポイントするまで、実際には別の WM_MOUSEHOVER メッセージは必要ありません。
マウス追跡イベントの管理に使用できる小さなヘルパー クラスを次に示します。
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false)
{
}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
次の例では、ウィンドウ プロシージャでこのクラスを使用する方法を示します。
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
mouseTrack.OnMouseMove(m_hwnd); // Start tracking.
// TODO: Handle the mouse-move message.
return 0;
case WM_MOUSELEAVE:
// TODO: Handle the mouse-leave message.
mouseTrack.Reset(m_hwnd);
return 0;
case WM_MOUSEHOVER:
// TODO: Handle the mouse-hover message.
mouseTrack.Reset(m_hwnd);
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
マウス追跡イベントはシステムによる追加の処理を必要とするため、不要な場合は無効のままにします。
完全のために、既定のホバー タイムアウトについてシステムにクエリを実行する関数を次に示します。
UINT GetMouseHoverTime()
{
UINT msec;
if (SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &msec, 0))
{
return msec;
}
else
{
return 0;
}
}
マウス ホイール
次の関数は、マウス ホイールが存在するかどうかを確認します。
BOOL IsMouseWheelPresent()
{
return (GetSystemMetrics(SM_MOUSEWHEELPRESENT) != 0);
}
ユーザーがマウス ホイールを回転させると、フォーカスのあるウィンドウに WM_MOUSEWHEEL メッセージが表示されます。 このメッセージの wParam パラメーターには、ホイールが回転した距離を測定する デルタ と呼ばれる整数値が含まれています。 デルタでは任意の単位が使用されます。120 単位は、1 つの "アクション" を実行するために必要な回転として定義されます。もちろん、アクションの定義はプログラムによって異なります。 たとえば、マウス ホイールを使用してテキストをスクロールする場合、120 単位の回転ごとに 1 行のテキストがスクロールされます。
デルタの符号は、回転の方向を示します。
- 正: ユーザーから離れて前方に回転します。
- 負の値: ユーザーに向かって後方に回転します。
デルタの値は、いくつかの追加フラグと共に wParam に配置されます。 デルタの値を取得するには、 GET_WHEEL_DELTA_WPARAM マクロを使用します。
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
マウス ホイールの解像度が高い場合、差分の絶対値が 120 未満になる可能性があります。 その場合、アクションが少しずつ発生するのが理にかなっている場合は、これを行うことができます。 たとえば、テキストは 1 行未満の増分でスクロールできます。 それ以外の場合は、アクションを実行するのに十分なホイールが回転するまで、合計デルタを累積します。 未使用のデルタを変数に格納し、120 単位 (正または負のいずれか) が蓄積された場合は、アクションを実行します。
次へ