scrolbar.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 959 行 · 第 1/2 页
CPP
959 行
{
int thumbOld = m_thumbPos;
bool notify = false; // send an event about the change?
wxEventType scrollType;
// test for thumb move first as these events happen in quick succession
if ( action == wxACTION_SCROLL_THUMB_MOVE )
{
DoSetThumb(numArg);
// VS: we have to force redraw here, otherwise the thumb will lack
// behind mouse cursor
UpdateThumb();
scrollType = wxEVT_SCROLLWIN_THUMBTRACK;
}
else if ( action == wxACTION_SCROLL_LINE_UP )
{
scrollType = wxEVT_SCROLLWIN_LINEUP;
ScrollLines(-1);
}
else if ( action == wxACTION_SCROLL_LINE_DOWN )
{
scrollType = wxEVT_SCROLLWIN_LINEDOWN;
ScrollLines(1);
}
else if ( action == wxACTION_SCROLL_PAGE_UP )
{
scrollType = wxEVT_SCROLLWIN_PAGEUP;
ScrollPages(-1);
}
else if ( action == wxACTION_SCROLL_PAGE_DOWN )
{
scrollType = wxEVT_SCROLLWIN_PAGEDOWN;
ScrollPages(1);
}
else if ( action == wxACTION_SCROLL_START )
{
scrollType = wxEVT_SCROLLWIN_THUMBRELEASE; // anything better?
ScrollToStart();
}
else if ( action == wxACTION_SCROLL_END )
{
scrollType = wxEVT_SCROLLWIN_THUMBRELEASE; // anything better?
ScrollToEnd();
}
else if ( action == wxACTION_SCROLL_THUMB_DRAG )
{
// we won't use it but this line suppresses the compiler
// warning about "variable may be used without having been
// initialized"
scrollType = wxEVT_NULL;
}
else if ( action == wxACTION_SCROLL_THUMB_RELEASE )
{
// always notify about this
notify = true;
scrollType = wxEVT_SCROLLWIN_THUMBRELEASE;
}
else
return wxControl::PerformAction(action, numArg, strArg);
// has scrollbar position changed?
bool changed = m_thumbPos != thumbOld;
if ( notify || changed )
{
if ( IsStandalone() )
{
// we should generate EVT_SCROLL events for the standalone
// scrollbars and not the EVT_SCROLLWIN ones
//
// NB: we assume that scrollbar events are sequentially numbered
// but this should be ok as other code relies on this as well
scrollType += wxEVT_SCROLL_TOP - wxEVT_SCROLLWIN_TOP;
wxScrollEvent event(scrollType, this->GetId(), m_thumbPos,
IsVertical() ? wxVERTICAL : wxHORIZONTAL);
event.SetEventObject(this);
GetParent()->GetEventHandler()->ProcessEvent(event);
}
else // part of the window
{
wxScrollWinEvent event(scrollType, m_thumbPos,
IsVertical() ? wxVERTICAL : wxHORIZONTAL);
event.SetEventObject(this);
GetParent()->GetEventHandler()->ProcessEvent(event);
}
}
return true;
}
void wxScrollBar::ScrollToStart()
{
DoSetThumb(0);
}
void wxScrollBar::ScrollToEnd()
{
DoSetThumb(m_range - m_thumbSize);
}
bool wxScrollBar::ScrollLines(int nLines)
{
DoSetThumb(m_thumbPos + nLines);
return true;
}
bool wxScrollBar::ScrollPages(int nPages)
{
DoSetThumb(m_thumbPos + nPages*m_pageSize);
return true;
}
// ============================================================================
// scroll bar input handler
// ============================================================================
// ----------------------------------------------------------------------------
// wxScrollBarTimer
// ----------------------------------------------------------------------------
wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
const wxControlAction& action,
wxScrollBar *control)
{
m_handler = handler;
m_action = action;
m_control = control;
}
bool wxScrollBarTimer::DoNotify()
{
return m_handler->OnScrollTimer(m_control, m_action);
}
// ----------------------------------------------------------------------------
// wxStdScrollBarInputHandler
// ----------------------------------------------------------------------------
wxStdScrollBarInputHandler::wxStdScrollBarInputHandler(wxRenderer *renderer,
wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_renderer = renderer;
m_winCapture = NULL;
m_htLast = wxHT_NOWHERE;
m_timerScroll = NULL;
}
wxStdScrollBarInputHandler::~wxStdScrollBarInputHandler()
{
// normally, it's NULL by now but just in case the user somehow managed to
// keep the mouse captured until now...
delete m_timerScroll;
}
void wxStdScrollBarInputHandler::SetElementState(wxScrollBar *control,
int flag,
bool doIt)
{
if ( m_htLast > wxHT_SCROLLBAR_FIRST && m_htLast < wxHT_SCROLLBAR_LAST )
{
wxScrollBar::Element
elem = (wxScrollBar::Element)(m_htLast - wxHT_SCROLLBAR_FIRST - 1);
int flags = control->GetState(elem);
if ( doIt )
flags |= flag;
else
flags &= ~flag;
control->SetState(elem, flags);
}
}
bool wxStdScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
const wxControlAction& action)
{
int oldThumbPos = scrollbar->GetThumbPosition();
scrollbar->PerformAction(action);
if ( scrollbar->GetThumbPosition() != oldThumbPos )
return true;
// we scrolled till the end
m_timerScroll->Stop();
return false;
}
void wxStdScrollBarInputHandler::StopScrolling(wxScrollBar *control)
{
// return everything to the normal state
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
}
m_btnCapture = -1;
if ( m_timerScroll )
{
delete m_timerScroll;
m_timerScroll = NULL;
}
// unpress the arrow and highlight the current element
Press(control, false);
}
wxCoord
wxStdScrollBarInputHandler::GetMouseCoord(const wxScrollBar *scrollbar,
const wxMouseEvent& event) const
{
wxPoint pt = event.GetPosition();
return scrollbar->GetWindowStyle() & wxVERTICAL ? pt.y : pt.x;
}
void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar *scrollbar,
const wxMouseEvent& event)
{
int thumbPos = GetMouseCoord(scrollbar, event) - m_ofsMouse;
thumbPos = m_renderer->PixelToScrollbar(scrollbar, thumbPos);
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, thumbPos);
}
bool wxStdScrollBarInputHandler::HandleKey(wxInputConsumer *consumer,
const wxKeyEvent& event,
bool pressed)
{
// we only react to the key presses here
if ( pressed )
{
wxControlAction action;
switch ( event.GetKeyCode() )
{
case WXK_DOWN:
case WXK_RIGHT: action = wxACTION_SCROLL_LINE_DOWN; break;
case WXK_UP:
case WXK_LEFT: action = wxACTION_SCROLL_LINE_UP; break;
case WXK_HOME: action = wxACTION_SCROLL_START; break;
case WXK_END: action = wxACTION_SCROLL_END; break;
case WXK_PAGEUP:
case WXK_PRIOR: action = wxACTION_SCROLL_PAGE_UP; break;
case WXK_PAGEDOWN:
case WXK_NEXT: action = wxACTION_SCROLL_PAGE_DOWN; break;
}
if ( !action.IsEmpty() )
{
consumer->PerformAction(action);
return true;
}
}
return wxStdInputHandler::HandleKey(consumer, event, pressed);
}
bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer *consumer,
const wxMouseEvent& event)
{
// is this a click event from an acceptable button?
int btn = event.GetButton();
if ( (btn != -1) && IsAllowedButton(btn) )
{
// determine which part of the window mouse is in
wxScrollBar *scrollbar = wxStaticCast(consumer->GetInputWindow(), wxScrollBar);
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
// when the mouse is pressed on any scrollbar element, we capture it
// and hold capture until the same mouse button is released
if ( event.ButtonDown() || event.ButtonDClick() )
{
if ( !m_winCapture )
{
m_btnCapture = btn;
m_winCapture = consumer->GetInputWindow();
m_winCapture->CaptureMouse();
// generate the command
bool hasAction = true;
wxControlAction action;
switch ( ht )
{
case wxHT_SCROLLBAR_ARROW_LINE_1:
action = wxACTION_SCROLL_LINE_UP;
break;
case wxHT_SCROLLBAR_ARROW_LINE_2:
action = wxACTION_SCROLL_LINE_DOWN;
break;
case wxHT_SCROLLBAR_BAR_1:
action = wxACTION_SCROLL_PAGE_UP;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_BAR_2:
action = wxACTION_SCROLL_PAGE_DOWN;
m_ptStartScrolling = event.GetPosition();
break;
case wxHT_SCROLLBAR_THUMB:
consumer->PerformAction(wxACTION_SCROLL_THUMB_DRAG);
m_ofsMouse = GetMouseCoord(scrollbar, event) -
m_renderer->ScrollbarToPixel(scrollbar);
// fall through: there is no immediate action
default:
hasAction = false;
}
// remove highlighting
Highlight(scrollbar, false);
m_htLast = ht;
// and press the arrow or highlight thumb now instead
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
Highlight(scrollbar, true);
else
Press(scrollbar, true);
// start dragging
if ( hasAction )
{
m_timerScroll = new wxScrollBarTimer(this, action,
scrollbar);
m_timerScroll->StartAutoScroll();
}
//else: no (immediate) action
}
//else: mouse already captured, nothing to do
}
// release mouse if the *same* button went up
else if ( btn == m_btnCapture )
{
if ( m_winCapture )
{
StopScrolling(scrollbar);
// if we were dragging the thumb, send the last event
if ( m_htLast == wxHT_SCROLLBAR_THUMB )
{
scrollbar->PerformAction(wxACTION_SCROLL_THUMB_RELEASE);
}
m_htLast = ht;
Highlight(scrollbar, true);
}
else
{
// this is not supposed to happen as the button can't go up
// without going down previously and then we'd have
// m_winCapture by now
wxFAIL_MSG( _T("logic error in mouse capturing code") );
}
}
}
return wxStdInputHandler::HandleMouse(consumer, event);
}
bool wxStdScrollBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
const wxMouseEvent& event)
{
wxScrollBar *scrollbar = wxStaticCast(consumer->GetInputWindow(), wxScrollBar);
if ( m_winCapture )
{
if ( (m_htLast == wxHT_SCROLLBAR_THUMB) && event.Dragging() )
{
// make the thumb follow the mouse by keeping the same offset
// between the mouse position and the top/left of the thumb
HandleThumbMove(scrollbar, event);
return true;
}
// no other changes are possible while the mouse is captured
return false;
}
bool isArrow = scrollbar->GetArrows().HandleMouseMove(event);
if ( event.Dragging() )
{
wxHitTest ht = m_renderer->HitTestScrollbar
(
scrollbar,
event.GetPosition()
);
if ( ht == m_htLast )
{
// nothing changed
return false;
}
#ifdef DEBUG_MOUSE
wxLogDebug("Scrollbar::OnMouseMove: ht = %d", ht);
#endif // DEBUG_MOUSE
Highlight(scrollbar, false);
m_htLast = ht;
if ( !isArrow )
Highlight(scrollbar, true);
//else: already done by wxScrollArrows::HandleMouseMove
}
else if ( event.Leaving() )
{
if ( !isArrow )
Highlight(scrollbar, false);
m_htLast = wxHT_NOWHERE;
}
else // event.Entering()
{
// we don't process this event
return false;
}
// we did something
return true;
}
#endif // wxUSE_SCROLLBAR
// ----------------------------------------------------------------------------
// wxScrollTimer
// ----------------------------------------------------------------------------
wxScrollTimer::wxScrollTimer()
{
m_skipNext = false;
}
void wxScrollTimer::StartAutoScroll()
{
// start scrolling immediately
if ( !DoNotify() )
{
// ... and end it too
return;
}
// there is an initial delay before the scrollbar starts scrolling -
// implement it by ignoring the first timer expiration and only start
// scrolling from the second one
m_skipNext = true;
Start(200); // FIXME: hardcoded delay
}
void wxScrollTimer::Notify()
{
if ( m_skipNext )
{
// scroll normally now - reduce the delay
Stop();
Start(50); // FIXME: hardcoded delay
m_skipNext = false;
}
else
{
// if DoNotify() returns false, we're already deleted by the timer
// event handler, so don't do anything else here
(void)DoNotify();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?