--- nono/wx/wxscrollbar.cpp 2026/04/29 17:05:08 1.1 +++ nono/wx/wxscrollbar.cpp 2026/04/29 17:05:16 1.1.1.2 @@ -76,6 +76,7 @@ wxDEFINE_EVENT(NONO_EVT_SCROLL, wxScroll wxBEGIN_EVENT_TABLE(WXScrollBar, inherited) EVT_SIZE(WXScrollBar::OnSize) EVT_MOUSE_EVENTS(WXScrollBar::OnMouse) + EVT_TIMER(wxID_ANY, WXScrollBar::OnTimer) wxEND_EVENT_TABLE() // コンストラクタ @@ -84,11 +85,13 @@ wxEND_EVENT_TABLE() // 本家の wxScrollBar は style のデフォルトが wxSB_HORIZONTAL だが、 // うちではデフォルト引数にはしない。 WXScrollBar::WXScrollBar(wxWindow *parent, wxWindowID id, long style) - : inherited(parent, id, wxSize(16, 16), 0) + : inherited(parent, id, wxDefaultPosition, wxSize(16, 16), 0) { if (style == wxSB_VERTICAL) { is_vertical = true; } + + timer.SetOwner(this); } // デストラクタ @@ -227,10 +230,17 @@ WXScrollBar::OnSize(wxSizeEvent& event) void WXScrollBar::OnMouse(wxMouseEvent& event) { - wxPoint pos = event.GetPosition(); - event.Skip(); + // 現在位置 + wxPoint pos = event.GetPosition(); + if (is_vertical) { + mouse_px = pos.y; + } else { + mouse_px = pos.x; + } + DPRINTF("OnMouse: mouse_px=%d\n", mouse_px); + int wheel = event.GetWheelRotation(); if (wheel != 0) { DPRINTF("OnMouse: wheel=%d\n", wheel); @@ -241,37 +251,37 @@ WXScrollBar::OnMouse(wxMouseEvent& event MoveThumb(thumbpos - wheel / 40); } + if (event.LeftUp()) { + left_click = false; + } + if (event.LeftDown() || event.LeftDClick()) { + left_click = true; + // 左クリック。間隔が速いとダブルクリックになる。 // ダブルクリックは LeftDown, LeftUp, LeftDClick, LeftUp の順で来る // ので、LeftDown と LeftDClick を同列で扱っておく。 - int r = PosCmp(pos); + int r = PosCmp(); if (r == 0) { // つまみ内左クリックでは何も起きないが、 // ドラッグ用に左クリック開始時点の位置を保存。 start_thumb = thumbpos; - if (is_vertical) { - start_px = pos.y; - } else { - start_px = pos.x; - } - DPRINTF("OnMouse: LeftDown start_pos=%d px=%d\n", + start_px = mouse_px; + DPRINTF("OnMouse: LeftDown thumbpos=%d start_px=%d\n", start_thumb, start_px); } else { // つまみ外の下地部分ならページアップ、ページダウン DPRINTF("OnMouse: LeftDown cmp=%d\n", r); MoveThumb(thumbpos + r * pagesize); } + + // 押しっぱなし判定のためタイマーを開始。 + timer.Start(500); } if (event.Dragging()) { // ドラッグ開始時からの差分を求めて.. - int delta; - if (is_vertical) { - delta = pos.y - start_px; - } else { - delta = pos.x - start_px; - } + int delta = mouse_px - start_px; DPRINTF("OnMouse: Dragging delta=%d\n", delta); // ピクセルでの移動量を変換 @@ -279,22 +289,31 @@ WXScrollBar::OnMouse(wxMouseEvent& event } } -// pt がつまみ内なら 0 を、つまみより上(左)なら -1、下(右)なら 1 を返す。 -int -WXScrollBar::PosCmp(const wxPoint& pt) const +// タイマーイベント +void +WXScrollBar::OnTimer(wxTimerEvent& event) { - int p; + int r = PosCmp(); + if (left_click && r != 0) { + // つまみ外で左クリックが続いていたらもう1回動かす + MoveThumb(thumbpos + r * pagesize); - if (is_vertical) { - p = pt.y; + // キーリピートと同じ要領で2回目以降は短くする。 + timer.Start(100); } else { - p = pt.x; + // つまみ内か左クリックが終わっていたら終了 + timer.Stop(); } +} - if (p < p1) { +// mouse_px がつまみ内なら 0 を、つまみより上(左)なら -1、下(右)なら 1 を返す。 +int +WXScrollBar::PosCmp() const +{ + if (mouse_px < p1) { return -1; } - if (p >= p2) { + if (mouse_px > p2) { return 1; } return 0;