xref: /MusicPlayer2/MusicPlayer2/HorizontalSplitter.cpp (revision a16f49f41a4ce867a3284a007493b8ef7d4e483f)
1 // HorizontalSpliter.cpp: 实现文件
2 //
3 
4 #include "stdafx.h"
5 #include "HorizontalSplitter.h"
6 
7 
8 // CHorizontalSpliter
9 
IMPLEMENT_DYNAMIC(CHorizontalSplitter,CStatic)10 IMPLEMENT_DYNAMIC(CHorizontalSplitter, CStatic)
11 
12 CHorizontalSplitter::CHorizontalSplitter()
13     :CStatic(), m_pParent(NULL), m_iLeftMin(100), m_iRightMin(100)
14 {
15 
16 }
17 
~CHorizontalSplitter()18 CHorizontalSplitter::~CHorizontalSplitter()
19 {
20 }
21 
SetMinWidth(int left,int right)22 void CHorizontalSplitter::SetMinWidth(int left, int right)
23 {
24     m_iLeftMin = left;
25     m_iRightMin = right;
26 }
27 
AttachCtrlAsLeftPane(DWORD idCtrl)28 BOOL CHorizontalSplitter::AttachCtrlAsLeftPane(DWORD idCtrl)
29 {
30     m_idLeft.Add(idCtrl);
31     return TRUE;
32 }
33 
AttachCtrlAsRightPane(DWORD idCtrl)34 BOOL CHorizontalSplitter::AttachCtrlAsRightPane(DWORD idCtrl)
35 {
36     m_idRight.Add(idCtrl);
37     return TRUE;
38 }
DetachAllPanes()39 BOOL CHorizontalSplitter::DetachAllPanes()
40 {
41     m_idLeft.RemoveAll();
42     m_idRight.RemoveAll();
43     return TRUE;
44 }
45 
AdjustLayout()46 void CHorizontalSplitter::AdjustLayout()
47 {
48     CWnd* pane;
49     RECT rcBar, rcPane;
50 
51     GetWindowRect(&rcBar);
52     m_pParent->ScreenToClient(&rcBar);
53 
54     int i;
55     DWORD id;
56 
57     for (i = 0; i < m_idLeft.GetSize(); i++)
58     {
59         id = m_idLeft.GetAt(i);
60         pane = m_pParent->GetDlgItem(id);
61         pane->GetWindowRect(&rcPane);
62         m_pParent->ScreenToClient(&rcPane);
63         rcPane.right = rcBar.left;
64         pane->MoveWindow(&rcPane, FALSE);
65     }
66 
67     for (i = 0; i < m_idRight.GetSize(); i++)
68     {
69         id = m_idRight.GetAt(i);
70         pane = m_pParent->GetDlgItem(id);
71         pane->GetWindowRect(&rcPane);
72         m_pParent->ScreenToClient(&rcPane);
73 
74         rcPane.left = rcBar.right;
75         pane->MoveWindow(&rcPane, FALSE);
76     }
77 
78     m_pParent->Invalidate();
79 }
80 
RegAdjustLayoutCallBack(pfAdjustLayout pFunc)81 void CHorizontalSplitter::RegAdjustLayoutCallBack(pfAdjustLayout pFunc)
82 {
83     m_pAdjLayoutFunc = pFunc;
84 }
85 
BEGIN_MESSAGE_MAP(CHorizontalSplitter,CStatic)86 BEGIN_MESSAGE_MAP(CHorizontalSplitter, CStatic)
87     ON_WM_SETCURSOR()
88     ON_WM_LBUTTONDOWN()
89     ON_WM_LBUTTONUP()
90     ON_WM_MOUSEMOVE()
91     ON_WM_PAINT()
92 END_MESSAGE_MAP()
93 
94 
95 // CHorizontalSpliter 消息处理程序
96 
97 
98 
99 BOOL CHorizontalSplitter::GetMouseClipRect(LPRECT rcClip, CPoint point)
100 {
101     CRect rcOrg, rcTarget, rcParent, rcPane;
102     DWORD id;
103 
104     GetWindowRect(&rcOrg);
105     m_pParent->GetClientRect(&rcParent);
106     m_pParent->ClientToScreen(&rcParent);
107     if (rcParent.Width() < m_iLeftMin + m_iRightMin + rcOrg.Width())        //如果父窗口的宽度小于两侧的最小宽度加上分割条的宽度,则说明分割条已经无法拖动了
108     {
109         TRACE(_T("No room to drag the x-splitter bar"));
110         return FALSE;
111     }
112 
113     rcTarget = rcOrg;
114     rcTarget.left = rcParent.left + m_iLeftMin;
115     for (int i = 0; i < m_idLeft.GetSize(); i++)
116     {
117         id = m_idLeft.GetAt(i);
118         m_pParent->GetDlgItem(id)->GetWindowRect(&rcPane);
119         if (rcTarget.left < rcPane.left + m_iLeftMin)
120         {
121             rcTarget.left = rcPane.left + m_iLeftMin;
122         }
123     }
124 
125     rcTarget.right = rcParent.right - m_iRightMin;
126     for (int i = 0; i < m_idRight.GetSize(); i++)
127     {
128         id = m_idRight.GetAt(i);
129         m_pParent->GetDlgItem(id)->GetWindowRect(&rcPane);
130         if (rcTarget.right > rcPane.right - m_iRightMin)
131         {
132             rcTarget.right = rcPane.right - m_iRightMin;
133         }
134     }
135 
136     if (rcTarget.left >= rcTarget.right)
137     {
138         TRACE(_T("No room to drag the x-splitter bar"));
139         return FALSE;
140     }
141 
142     //point指的是窗口的客户坐标,而不是屏幕坐标
143     rcClip->left = rcTarget.left + point.x;
144     rcClip->right = rcTarget.right - (rcOrg.right - rcOrg.left - point.x) + 1;
145     rcClip->top = rcOrg.top;
146     rcClip->bottom = rcOrg.bottom;
147 
148     return TRUE;
149 }
150 
151 
OnSetCursor(CWnd * pWnd,UINT nHitTest,UINT message)152 BOOL CHorizontalSplitter::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
153 {
154     //以下非常奇怪,用全局函数可以,但是用CStatic方法却不行
155     //if (GetCursor() == NULL)
156     // SetCursor(::LoadCursor(NULL, IDC_HELP));
157     ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
158     return TRUE;
159 }
160 
161 
OnLButtonDown(UINT nFlags,CPoint point)162 void CHorizontalSplitter::OnLButtonDown(UINT nFlags, CPoint point)
163 {
164 
165     //如果鼠标被别的程序捕获,不再处理此消息
166     if (::GetCapture() != NULL)
167         return;
168 
169     m_pParent = GetParent();
170     if (!m_pParent)
171         return;
172 
173     //ClipCursor限定鼠标移动范围
174     CRect rcMouseClip;
175     if (!GetMouseClipRect(rcMouseClip, point))
176         return;
177     ::ClipCursor(&rcMouseClip);
178 
179     m_pPointStart = point;
180 
181     SetCapture();
182     //捕获鼠标输入
183     GetWindowRect(m_rcOrgRect);
184     m_pParent->ScreenToClient(m_rcOrgRect);
185     CDC* pDrawDC = NULL;
186     pDrawDC = m_pParent->GetDC();
187 
188     pDrawDC->DrawDragRect(m_rcOrgRect, CSize(1, 1), NULL, CSize(1, 1));
189     m_rcOldRect = m_rcOrgRect;
190 
191     m_pParent->ReleaseDC(pDrawDC);
192 }
193 
194 
OnMouseMove(UINT nFlags,CPoint point)195 void CHorizontalSplitter::OnMouseMove(UINT nFlags, CPoint point)
196 {
197     if (GetCapture() == this)
198     {
199         CDC* pDrawDC = NULL;
200         pDrawDC = m_pParent->GetDC();
201 
202         CRect rcCur = m_rcOrgRect;
203         long xDiff = 0, yDiff = 0;
204         xDiff = point.x - m_pPointStart.x;
205         yDiff = point.y - m_pPointStart.y;
206         rcCur.OffsetRect(xDiff, 0);
207         pDrawDC->DrawDragRect(rcCur, CSize(1, 1), &m_rcOldRect, CSize(1, 1));
208         m_rcOldRect = rcCur;
209 
210         m_pParent->ReleaseDC(pDrawDC);
211     }
212 }
213 
214 
OnLButtonUp(UINT nFlags,CPoint point)215 void CHorizontalSplitter::OnLButtonUp(UINT nFlags, CPoint point)
216 {
217     if (GetCapture() == this)
218     {
219         CDC* pDrawDC = NULL;
220         pDrawDC = m_pParent->GetDC();   //获取DC
221 
222         //可以采用下列两种方式之一
223         //pDrawDC->DrawDragRect(m_rcOldRect, CSize(1, 1), NULL, CSize(1, 1));
224         pDrawDC->DrawDragRect(CRect(0, 0, 0, 0), CSize(1, 1), m_rcOldRect, CSize(1, 1));
225         m_pParent->ReleaseDC(pDrawDC);
226         ::ReleaseCapture();
227 
228         MoveWindow(m_rcOldRect);
229         if (m_pAdjLayoutFunc != nullptr)
230             m_pAdjLayoutFunc(m_rcOldRect);
231         else
232             AdjustLayout();
233     }
234     ::ClipCursor(NULL);
235 }
236 
237 
OnPaint()238 void CHorizontalSplitter::OnPaint()
239 {
240     CPaintDC dc(this); // device context for painting
241                        // TODO: 在此处添加消息处理程序代码
242                        // 不为绘图消息调用 CStatic::OnPaint()
243 
244     CRect rect;
245     ::GetClientRect(m_hWnd, rect);
246     // dc.FillSolidRect(rect, GetSysColor(COLOR_3DFACE));
247     dc.FillSolidRect(rect, GetSysColor(COLOR_WINDOW));  // 改为使用窗口背景色(白色)
248 }
249 
250 
PreSubclassWindow()251 void CHorizontalSplitter::PreSubclassWindow()
252 {
253     DWORD dwStyle = GetStyle();
254     ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);     //添加SS_NOTIFY样式
255 
256     CStatic::PreSubclassWindow();
257 }
258