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