]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/msw/scrolbar.cpp | |
3 | // Purpose: wxScrollBar | |
4 | // Author: Julian Smart | |
5 | // Modified by: | |
6 | // Created: 04/01/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Julian Smart | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // For compilers that support precompilation, includes "wx.h". | |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #if wxUSE_SCROLLBAR | |
20 | ||
21 | #include "wx/scrolbar.h" | |
22 | ||
23 | #ifndef WX_PRECOMP | |
24 | #include "wx/utils.h" | |
25 | #include "wx/settings.h" | |
26 | #endif | |
27 | ||
28 | #include "wx/msw/private.h" | |
29 | ||
30 | // Scrollbar | |
31 | bool wxScrollBar::Create(wxWindow *parent, wxWindowID id, | |
32 | const wxPoint& pos, | |
33 | const wxSize& size, long style, | |
34 | const wxValidator& validator, | |
35 | const wxString& name) | |
36 | { | |
37 | if ( !CreateControl(parent, id, pos, size, style, validator, name) ) | |
38 | return false; | |
39 | ||
40 | if (!MSWCreateControl(wxT("ScrollBar"), wxEmptyString, pos, size)) | |
41 | return false; | |
42 | ||
43 | SetScrollbar(0, 1, 2, 1, false); | |
44 | ||
45 | return true; | |
46 | } | |
47 | ||
48 | wxScrollBar::~wxScrollBar(void) | |
49 | { | |
50 | } | |
51 | ||
52 | bool wxScrollBar::MSWOnScroll(int WXUNUSED(orientation), WXWORD wParam, | |
53 | WXWORD WXUNUSED(pos), WXHWND WXUNUSED(control)) | |
54 | { | |
55 | // don't use pos parameter because it is limited to 16 bits, get the full | |
56 | // 32 bit position from the control itself instead | |
57 | WinStruct<SCROLLINFO> scrollInfo; | |
58 | scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_TRACKPOS; | |
59 | ||
60 | if ( !::GetScrollInfo(GetHwnd(), SB_CTL, &scrollInfo) ) | |
61 | { | |
62 | wxLogLastError(wxT("GetScrollInfo")); | |
63 | return false; | |
64 | } | |
65 | ||
66 | int maxPos = scrollInfo.nMax; | |
67 | ||
68 | // A page size greater than one has the effect of reducing the effective | |
69 | // range, therefore the range has already been boosted artificially - so | |
70 | // reduce it again. | |
71 | if ( m_pageSize > 1 ) | |
72 | maxPos -= (m_pageSize - 1); | |
73 | ||
74 | int position = scrollInfo.nPos; | |
75 | wxEventType scrollEvent = wxEVT_NULL; | |
76 | switch ( wParam ) | |
77 | { | |
78 | case SB_TOP: | |
79 | position = 0; | |
80 | scrollEvent = wxEVT_SCROLL_TOP; | |
81 | break; | |
82 | ||
83 | case SB_BOTTOM: | |
84 | position = maxPos; | |
85 | scrollEvent = wxEVT_SCROLL_BOTTOM; | |
86 | break; | |
87 | ||
88 | case SB_LINEUP: | |
89 | position--; | |
90 | scrollEvent = wxEVT_SCROLL_LINEUP; | |
91 | break; | |
92 | ||
93 | case SB_LINEDOWN: | |
94 | position++; | |
95 | scrollEvent = wxEVT_SCROLL_LINEDOWN; | |
96 | break; | |
97 | ||
98 | case SB_PAGEUP: | |
99 | position -= GetPageSize(); | |
100 | scrollEvent = wxEVT_SCROLL_PAGEUP; | |
101 | break; | |
102 | ||
103 | case SB_PAGEDOWN: | |
104 | position += GetPageSize(); | |
105 | scrollEvent = wxEVT_SCROLL_PAGEDOWN; | |
106 | break; | |
107 | ||
108 | case SB_THUMBPOSITION: | |
109 | case SB_THUMBTRACK: | |
110 | position = scrollInfo.nTrackPos; | |
111 | scrollEvent = wParam == SB_THUMBPOSITION ? wxEVT_SCROLL_THUMBRELEASE | |
112 | : wxEVT_SCROLL_THUMBTRACK; | |
113 | break; | |
114 | ||
115 | case SB_ENDSCROLL: | |
116 | scrollEvent = wxEVT_SCROLL_CHANGED; | |
117 | break; | |
118 | } | |
119 | ||
120 | if ( position != scrollInfo.nPos ) | |
121 | { | |
122 | if ( position < 0 ) | |
123 | position = 0; | |
124 | if ( position > maxPos ) | |
125 | position = maxPos; | |
126 | ||
127 | SetThumbPosition(position); | |
128 | } | |
129 | else if ( scrollEvent != wxEVT_SCROLL_THUMBRELEASE && | |
130 | scrollEvent != wxEVT_SCROLL_CHANGED ) | |
131 | { | |
132 | // don't process the event if there is no displacement, | |
133 | // unless this is a thumb release or end scroll event. | |
134 | return false; | |
135 | } | |
136 | ||
137 | wxScrollEvent event(scrollEvent, m_windowId); | |
138 | event.SetOrientation(IsVertical() ? wxVERTICAL : wxHORIZONTAL); | |
139 | event.SetPosition(position); | |
140 | event.SetEventObject( this ); | |
141 | ||
142 | return HandleWindowEvent(event); | |
143 | } | |
144 | ||
145 | void wxScrollBar::SetThumbPosition(int viewStart) | |
146 | { | |
147 | SCROLLINFO info; | |
148 | info.cbSize = sizeof(SCROLLINFO); | |
149 | info.nPage = 0; | |
150 | info.nMin = 0; | |
151 | info.nPos = viewStart; | |
152 | info.fMask = SIF_POS ; | |
153 | ||
154 | ::SetScrollInfo((HWND) GetHWND(), SB_CTL, &info, TRUE); | |
155 | } | |
156 | ||
157 | int wxScrollBar::GetThumbPosition(void) const | |
158 | { | |
159 | SCROLLINFO scrollInfo; | |
160 | wxZeroMemory(scrollInfo); | |
161 | scrollInfo.cbSize = sizeof(SCROLLINFO); | |
162 | scrollInfo.fMask = SIF_POS; | |
163 | ||
164 | if ( !::GetScrollInfo(GetHwnd(), SB_CTL, &scrollInfo) ) | |
165 | { | |
166 | wxLogLastError(wxT("GetScrollInfo")); | |
167 | } | |
168 | return scrollInfo.nPos; | |
169 | } | |
170 | ||
171 | void wxScrollBar::SetScrollbar(int position, int thumbSize, int range, int pageSize, | |
172 | bool refresh) | |
173 | { | |
174 | m_viewSize = pageSize; | |
175 | m_pageSize = thumbSize; | |
176 | m_objectSize = range; | |
177 | ||
178 | // The range (number of scroll steps) is the | |
179 | // object length minus the page size. | |
180 | int range1 = wxMax((m_objectSize - m_pageSize), 0) ; | |
181 | ||
182 | // Try to adjust the range to cope with page size > 1 | |
183 | // (see comment for SetPageLength) | |
184 | if ( m_pageSize > 1 ) | |
185 | { | |
186 | range1 += (m_pageSize - 1); | |
187 | } | |
188 | ||
189 | SCROLLINFO info; | |
190 | info.cbSize = sizeof(SCROLLINFO); | |
191 | info.nPage = m_pageSize; | |
192 | info.nMin = 0; | |
193 | info.nMax = range1; | |
194 | info.nPos = position; | |
195 | ||
196 | info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; | |
197 | ||
198 | ::SetScrollInfo((HWND) GetHWND(), SB_CTL, &info, refresh); | |
199 | } | |
200 | ||
201 | void wxScrollBar::Command(wxCommandEvent& event) | |
202 | { | |
203 | SetThumbPosition(event.GetInt()); | |
204 | ProcessCommand(event); | |
205 | } | |
206 | ||
207 | wxSize wxScrollBar::DoGetBestSize() const | |
208 | { | |
209 | int w = 100; | |
210 | int h = 100; | |
211 | ||
212 | if ( IsVertical() ) | |
213 | { | |
214 | w = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); | |
215 | } | |
216 | else | |
217 | { | |
218 | h = wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y); | |
219 | } | |
220 | ||
221 | wxSize best(w, h); | |
222 | CacheBestSize(best); | |
223 | return best; | |
224 | } | |
225 | ||
226 | WXDWORD wxScrollBar::MSWGetStyle(long style, WXDWORD *exstyle) const | |
227 | { | |
228 | // we never have an external border | |
229 | WXDWORD msStyle = wxControl::MSWGetStyle | |
230 | ( | |
231 | (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle | |
232 | ); | |
233 | ||
234 | // SBS_HORZ is 0 anyhow, but do mention it explicitly for clarity | |
235 | msStyle |= style & wxSB_HORIZONTAL ? SBS_HORZ : SBS_VERT; | |
236 | ||
237 | return msStyle; | |
238 | } | |
239 | ||
240 | WXHBRUSH wxScrollBar::MSWControlColor(WXHDC pDC, WXHWND hWnd) | |
241 | { | |
242 | // unless we have an explicitly set bg colour, use default (gradient under | |
243 | // XP) brush instead of GetBackgroundColour() one as the base class would | |
244 | // | |
245 | // note that fg colour isn't used for a scrollbar | |
246 | return UseBgCol() ? wxControl::MSWControlColor(pDC, hWnd) : NULL; | |
247 | } | |
248 | ||
249 | #endif // wxUSE_SCROLLBAR |