fixed crash of AboutDialog
[TortoiseGit.git] / src / TortoiseIDiff / NiceTrackbar.cpp
blob666828ee86eb0490d6cdf50fac835fe14b4d1640
1 // TortoiseIDiff - an image diff viewer in TortoiseSVN
3 // Copyright (C) 2006 - 2008, 2011 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "StdAfx.h"
20 #include "NiceTrackbar.h"
21 #include <tchar.h>
22 #include <CommCtrl.h>
23 #include <WindowsX.h>
26 LRESULT CALLBACK CNiceTrackbar::NiceTrackbarProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
28 CNiceTrackbar* self = (CNiceTrackbar*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
30 switch (message) {
31 case WM_LBUTTONDOWN:
32 self->m_Dragging = true;
33 self->m_DragChanged = false;
34 SetCapture(hwnd);
35 //SetFocus(hwnd);
36 if (self->SetThumb(lParam)) {
37 self->m_DragChanged = true;
38 self->PostMessageToParent(TB_THUMBTRACK);
40 return 0;
41 case WM_MOUSEMOVE:
42 if (self->m_Dragging)
44 if (self->SetThumb(lParam))
46 self->m_DragChanged = true;
47 self->PostMessageToParent(TB_THUMBTRACK);
49 return 0;
51 break;
52 case WM_LBUTTONUP:
53 if (self->m_Dragging)
55 self->m_Dragging = false;
56 ReleaseCapture();
57 if (self->SetThumb(lParam))
59 self->PostMessageToParent(TB_ENDTRACK);
60 self->m_DragChanged = true;
62 if (self->m_DragChanged)
64 self->PostMessageToParent(TB_THUMBPOSITION);
65 self->m_DragChanged = false;
67 return 0;
69 break;
70 case WM_CAPTURECHANGED:
71 if (self->m_Dragging)
73 self->m_Dragging = false;
74 return 0;
76 break;
77 case WM_DESTROY:
78 SetWindowLongPtr (hwnd, GWLP_WNDPROC, (LONG_PTR)self->m_OrigProc);
79 break;
81 return CallWindowProc (self->m_OrigProc, hwnd, message, wParam, lParam);
85 void CNiceTrackbar::ConvertTrackbarToNice( HWND window )
87 m_Window = window;
89 // setup this pointer
90 SetWindowLongPtr( window, GWLP_USERDATA, (LONG_PTR)this );
92 // subclass it
93 m_OrigProc = (WNDPROC)SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)NiceTrackbarProc );
97 bool CNiceTrackbar::SetThumb (LPARAM lparamPoint)
99 POINT point = { GET_X_LPARAM(lparamPoint), GET_Y_LPARAM(lparamPoint) };
100 const int nMin = (int)SendMessage(m_Window, TBM_GETRANGEMIN, 0, 0l);
101 const int nMax = (int)SendMessage(m_Window, TBM_GETRANGEMAX, 0, 0l);
102 RECT rc;
103 SendMessage(m_Window, TBM_GETCHANNELRECT, 0, (LPARAM)&rc);
104 double ratio;
105 if (GetWindowLong(m_Window, GWL_STYLE) & TBS_VERT)
107 // note: for vertical trackbar, it still returns the rectangle as if it was horizontal
108 ratio = (double)(point.y - rc.left)/(rc.right - rc.left);
110 else
112 ratio = (double)(point.x - rc.left)/(rc.right - rc.left);
115 int nNewPos = (int)(nMin + (nMax-nMin)*ratio + 0.5); // round the result to go to the nearest tick mark
117 const bool changed = (nNewPos != (int)SendMessage(m_Window, TBM_GETPOS, 0, 0));
118 if (changed)
120 SendMessage(m_Window, TBM_SETPOS, TRUE, nNewPos);
122 return changed;
126 void CNiceTrackbar::PostMessageToParent (int tbCode) const
128 HWND parent = GetParent(m_Window);
129 if (parent) {
130 int pos = (int)SendMessage(m_Window, TBM_GETPOS, 0, 0);
131 bool vert = (GetWindowLong(m_Window, GWL_STYLE) & TBS_VERT) != 0;
132 PostMessage( parent, vert ? WM_VSCROLL : WM_HSCROLL, (WPARAM)((pos << 16) | tbCode), (LPARAM)m_Window );