43. マウス入力¶
マウスによる入力を処理する方法を学びます。
43.1 マウスカーソルの座標¶
- マウスカーソルの座標は
Cursor::Pos()を使うとPoint型で取得できます - シーンが実ウィンドウサイズと異なる(チュートリアル 44 参照)場合、
Cursor::PosF()を使うと、小数点以下も含むVec2型で座標を取得できます Cursor::Pos()で取得できるマウスカーソル座標は、最後のSystem::Update()の呼び出し時点での座標です- 実際に画面に見える最新のマウスカーソルの位置に比べて若干遅れがあることに注意してください

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
while (System::Update())
{
ClearPrint();
Print << Cursor::Pos();
Print << Cursor::PosF();
Circle{ Cursor::PosF(), 50 }.draw(ColorF{ 0.2 });
}
}
43.2 マウスカーソルの移動量¶
- 1 フレーム前のマウスカーソル座標は
Cursor::PreviousPos()/Cursor::PreviousPosF()で取得できます - 1 フレーム前からのマウスカーソルの移動量は
Cursor::Delta()/Cursor::DeltaF()で取得できます Cursor::Delta() == (Cursor::Pos() - Cursor::PreviousPos())です

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
// 円をつかんでいるか
bool grab = false;
Circle circle{ 400, 300, 50 };
while (System::Update())
{
if (grab)
{
// 移動量分だけ円を移動させる
circle.moveBy(Cursor::Delta());
}
if (circle.leftClicked()) // 円を左クリックしたら
{
grab = true;
}
else if (MouseL.up()) // マウスの左ボタンが離されたら
{
grab = false;
}
if (grab || circle.mouseOver())
{
Cursor::RequestStyle(CursorStyle::Hand);
}
circle.draw(ColorF{ 0.2 });
}
}
43.3 マウスカーソルのスクリーン座標¶
- マウスカーソルの座標を、スクリーン座標基準で取得するには
Cursor::ScreenPos()を使います
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
// スクリーン座標におけるマウスカーソル座標
Print << Cursor::ScreenPos();
}
}
43.4 マウスのボタンの入力状態¶
- マウスのボタンには、以下の
Input型の定数が割り当てられています
| 定数 | 対応するボタン |
|---|---|
| MouseL | 左ボタン |
| MouseR | 右ボタン |
| MouseM | 中央ボタン |
| MouseX1 | 拡張ボタン 1 |
| MouseX2 | 拡張ボタン 2 |
| MouseX3 | 拡張ボタン 3 |
| MouseX4 | 拡張ボタン 4 |
| MouseX5 | 拡張ボタン 5 |
- チュートリアル 42 のキーボードと同様に、
Input型のメンバ関数をとおして、ボタンの入力状態を調べることができます
| コード | 押していないとき | 押した瞬間 | 押し続けている | 離した瞬間 | 離し続けている |
|---|---|---|---|---|---|
.down() |
false | ✔ true | false | false | false |
.pressed() |
false | ✔ true | ✔ true | false | false |
.up() |
false | false | false | ✔ true | false |
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << MouseL.pressed();
Print << MouseM.pressed();
Print << MouseR.pressed();
}
}
43.5 マウスのボタン入力のキャンセル¶
- 現在のフレーム内で、以降のマウスのボタンの入力を無効にするには、
Inputのメンバ関数.clearInput()を呼びます - 画面上でボタンなどの UI が重なっているとき、背後に隠れた UI に入力が貫通しないようにするために使います
MouseLとMouseRを同時にキャンセルする場合はMouse::ClearLRInput()が使えます

# include <Siv3D.hpp>
class MyButton
{
public:
MyButton() = default;
explicit MyButton(const Rect& rect)
: m_rect{ rect } {
}
bool update() const
{
if (m_rect.leftClicked())
{
MouseL.clearInput();
return true;
}
return false;
}
void draw() const
{
if (m_rect.mouseOver())
{
Cursor::RequestStyle(CursorStyle::Hand);
}
m_rect.draw().drawFrame(1, 0, Palette::Black);
}
private:
Rect m_rect{ 0, 0, 0, 0 };
};
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
const MyButton button0{ Rect{ 100, 100, 200, 100 } };
const MyButton button1{ Rect{ 150, 150, 200, 100 } };
while (System::Update())
{
if (button0.update())
{
Print << U"button0";
}
if (button1.update())
{
Print << U"button1";
}
button1.draw();
button0.draw();
}
}
43.6 ボタンが押されていた時間¶
Inputの.pressedDuration()は、その入力が押され続けている時間をDuration型で返します.pressedDuration()は、そのキーの.up()がtrueと判定されるフレームまで有効です
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << MouseL.pressedDuration();
Print << MouseM.pressedDuration();
Print << MouseR.pressedDuration();
}
}
43.7 ダブルクリック判定¶
- 次のようなクラスを作成して、ダブルクリックを判定できます
# include <Siv3D.hpp>
class DoubleClick
{
public:
void update()
{
if (m_step == 3)
{
m_step = 0;
}
if (MouseL.down())
{
if (m_step == 0)
{
m_step = 1;
}
else if (m_step == 2)
{
if (const uint64 d = (Time::GetMillisec() - m_previousTimeMillisec);
d < DoubleClickThresholdMillisec)
{
m_step = 3;
}
else
{
m_step = 1;
}
}
}
if (m_step == 0)
{
return;
}
if (not Cursor::Delta().isZero())
{
m_step = 0;
}
if ((m_step == 1) && MouseL.up())
{
if (MouseL.pressedDuration() < Milliseconds{ MaxClickTimeMillisec })
{
m_step = 2;
m_previousTimeMillisec = Time::GetMillisec();
}
else
{
m_step = 0;
}
}
}
[[nodiscard]]
bool doubleClicked() const noexcept
{
return (m_step == 3);
}
private:
// 1 回目のクリックの長さ(ミリ秒)
static constexpr int32 MaxClickTimeMillisec = 500;
// 1 回目のクリックと 2 回目のクリックの最大間隔(ミリ秒)
static constexpr int32 DoubleClickThresholdMillisec = 500;
int32 m_step = 0;
int64 m_previousTimeMillisec = 0;
};
void Main()
{
DoubleClick dc;
while (System::Update())
{
// 毎フレーム 1 回必ず呼ぶ
dc.update();
// ダブルクリックされたら
if (dc.doubleClicked())
{
Print << U"double click";
}
}
}
43.8 マウスボタンの名前¶
Inputの.name()は、そのキーの名前をString型で返します
# include <Siv3D.hpp>
void Main()
{
Print << MouseL.name();
Print << MouseR.name();
Print << MouseM.name();
Print << MouseX1.name();
Print << MouseX2.name();
while (System::Update())
{
}
}
43.9 すべてのマウスボタン入力の取得¶
Mouse::GetAllInputs()は、現在のフレームで.down(),.pressed(),.up()のいずれかがtrueになっている、アクティブなマウスボタンの一覧をArray<Input>で返します
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
// down() / pressed() / up() のいずれかが true になっているマウスボタン一覧を取得
const Array<Input> buttons = Mouse::GetAllInputs();
for (const auto& button : buttons)
{
Print << button.name() << (button.pressed() ? U" pressed" : U" up");
}
}
}
43.10 マウスホイールの回転量¶
Mouse::Wheel()は、直前のフレームからのマウスホイールのスクロール量をdouble型で返しますMouse::WheelH()は、直前のフレームからのマウスの水平ホイールのスクロール量をdouble型で返します- マウスホイールのスクロール量はフレームレートに依存しないため、
Scene::DeltaTime()で調整する必要はありません

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
Vec2 pos{ 400, 300 };
while (System::Update())
{
ClearPrint();
// マウスホイールのスクロール量
Print << Mouse::Wheel();
// マウスの水平ホイールのスクロール量
Print << Mouse::WheelH();
pos.y -= (Mouse::Wheel() * 10);
pos.x += (Mouse::WheelH() * 10);
RectF{ Arg::center = pos, 100 }.draw(ColorF{ 0.2 });
}
}
43.11 マウスカーソルがクライアント領域上にあるか調べる¶
Cursor::OnClientRect()は、マウスカーソルがウィンドウのクライアント領域(シーン)上にあるかをbool型で返します
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
// マウスカーソルがウィンドウのクライアント領域上にあるかを表示
Print << Cursor::OnClientRect();
if (Cursor::OnClientRect())
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
}
else
{
Scene::SetBackground(ColorF{ 0.2 });
}
}
}
43.12 マウスカーソルの移動¶
- 指定した位置にマウスカーソルを移動させるには、
Cursor::SetPos(pos)を使います - シーンが実ウィンドウサイズと異なる(チュートリアル 44 参照)場合、± 1 ピクセルの誤差が生じることがあります
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << Cursor::Pos();
if (SimpleGUI::Button(U"center", Vec2{ 100, 20 }))
{
// マウスカーソルをシーンの中心に移動させる
Cursor::SetPos(Point{ 400, 300 });
}
}
}
43.13 マウスカーソルの移動制限(Windows)¶
- Windows 版では、
Cursor::ClipToWindow(true)を呼ぶと、マウスカーソルが移動できる領域をウィンドウのクライアント領域上に制限します - 制限を解除するには
Cursor::ClipToWindow(false)を呼びます
# include <Siv3D.hpp>
void Main()
{
bool clip = false;
while (System::Update())
{
ClearPrint();
Print << Cursor::Pos();
if (SimpleGUI::CheckBox(clip, U"clip", Vec2{ 100, 20 }))
{
if (clip)
{
// マウスカーソルの移動をウィンドウのクライアント領域上に制限
Cursor::ClipToWindow(true);
}
else
{
// 制限を解除
Cursor::ClipToWindow(false);
}
}
}
}
43.14 マウスカーソルのスタイル(標準スタイル)¶
Cursor::RequestStyle(style)によって、そのフレームにおけるマウスカーソルのスタイルを変更できますstyleには下記のCursorStyleのいずれかを指定します:
| コード | 説明 |
|---|---|
| CursorStyle::Arrow | 矢印(デフォルト) |
| CursorStyle::IBeam | I マーク |
| CursorStyle::Cross | 十字のマーク |
| CursorStyle::Hand | 手のアイコン |
| CursorStyle::NotAllowed | 禁止のマーク |
| CursorStyle::ResizeUpDown | 上下のリサイズ |
| CursorStyle::ResizeLeftRight | 左右のリサイズ |
| CursorStyle::ResizeNWSE | 左上 - 右下のリサイズ |
| CursorStyle::ResizeNESW | 右上 - 左下のリサイズ |
| CursorStyle::ResizeAll | 上下左右方向のリサイズ |
| CursorStyle::Hidden | 非表示 |
| CursorStyle::Default | Arrow と同じ |
Cursor::RequestStyle() はそのフレームのみの変更であり、次のフレームでは元のスタイルに戻ります。マウスカーソルのスタイルを継続的に変更したい場合は、毎フレーム Cursor::RequestStyle() を呼ぶ必要があります。

# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(Palette::White);
const ColorF buttonColor{ 0.2, 0.6, 1.0 };
const Circle button{ 400, 300, 60 };
Transition press{ 0.05s, 0.05s };
while (System::Update())
{
const bool mouseOver = button.mouseOver();
// 円の上にマウスカーソルがあれば
if (mouseOver)
{
// マウスカーソルを手の形にする
Cursor::RequestStyle(CursorStyle::Hand);
}
press.update(button.leftPressed());
const double t = press.value();
button.movedBy(Vec2{ 0, 0 }.lerp(Vec2{ 0, 4 }, t))
.drawShadow(Vec2{ 0, 6 }.lerp(Vec2{ 0, 1 }, t), (12 - t * 7), (5 - t * 4))
.draw(buttonColor);
}
}
43.15 マウスカーソルのスタイル(カスタム画像)¶
Imageクラス(チュートリアル 63)で作成した任意の画像を、マウスカーソルとして使うことができますCursor::RegisterCustomCursorStyle(name, image, hotSpot)で、画像をnameという名前で登録します- 名前が異なれば、複数のカスタムカーソルを登録できます
hotSpotには、画像中のクリック位置を指定します
- 登録したカスタムカーソルを現在のフレームに適用するには、
Cursor::RequestStyle(name)を呼びます

# include <Siv3D.hpp>
Image CreateCursorImage()
{
Image image{ 32, 32, Palette::White };
for (int32 y = 0; y < image.height(); ++y)
{
for (int32 x = 0; x < image.width(); ++x)
{
image[y][x] = ColorF{ (x / 31.0), (y / 31.0), 1.0 };
}
}
return image;
}
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
// カスタムカーソルを登録する。画像中の (0, 0) がクリック位置
Cursor::RegisterCustomCursorStyle(U"MyCursor", CreateCursorImage(), Point{ 0, 0 });
const Circle circle{ 400, 300, 100 };
while (System::Update())
{
Cursor::RequestStyle(U"MyCursor");
circle.draw(circle.mouseOver() ? Palette::Orange : Palette::White);
}
}