SplitterControl.cpp
上传用户:seeker_wen
上传日期:2016-05-23
资源大小:2084k
文件大小:7k
源码类别:

ICQ/即时通讯

开发平台:

Visual C++

  1. // SplitterControl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "SplitterControl.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CSplitterControl
  12. // hCursor1 is for vertiacal one
  13. // and hCursor2 is for horizontal one
  14. static HCURSOR SplitterControl_hCursor1 = NULL;
  15. static HCURSOR SplitterControl_hCursor2 = NULL;
  16. CSplitterControl::CSplitterControl()
  17. {
  18. // Mouse is pressed down or not ?
  19. m_bIsPressed = FALSE;
  20. // Min and Max range of the splitter.
  21. m_nMin = m_nMax = -1;
  22. }
  23. CSplitterControl::~CSplitterControl()
  24. {
  25. }
  26. BEGIN_MESSAGE_MAP(CSplitterControl, CStatic)
  27. //{{AFX_MSG_MAP(CSplitterControl)
  28. ON_WM_PAINT()
  29. ON_WM_MOUSEMOVE()
  30. ON_WM_SETCURSOR()
  31. ON_WM_LBUTTONDOWN()
  32. ON_WM_LBUTTONUP()
  33. //}}AFX_MSG_MAP
  34. END_MESSAGE_MAP()
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CSplitterControl message handlers
  37. /****************************************************
  38. * Create(DWORD dwStyle, const CRect& rect, CWnd* pParent, nID)
  39. * Use this function instead of the CStatic::Create function
  40. * Parameters: No need to explain (see MSDN (:-) )
  41. *
  42. ****************************************************/
  43. void CSplitterControl::Create(DWORD dwStyle, const CRect &rect, CWnd *pParent, UINT nID)
  44. {
  45. CRect rc = rect;
  46. dwStyle |= SS_NOTIFY;
  47. // Determine default type base on it's size.
  48. m_nType = (rc.Width() < rc.Height())?
  49. SPS_VERTICAL:
  50. SPS_HORIZONTAL;
  51. if (m_nType == SPS_VERTICAL)
  52. rc.right = rc.left + 5;
  53. else // SPS_HORIZONTAL
  54. rc.bottom = rc.top + 5;
  55. CStatic::Create("", dwStyle, rc, pParent, nID);
  56. if (!SplitterControl_hCursor1)
  57. {
  58. SplitterControl_hCursor1 = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
  59. SplitterControl_hCursor2 = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);
  60. }
  61. // force the splitter not to be splited.
  62. SetRange(0, 0);
  63. }
  64. // Set style for splitter control
  65. // nStyle = SPS_VERTICAL or SPS_HORIZONTAL
  66. int CSplitterControl::SetStyle(int nStyle)
  67. {
  68. int m_nOldStyle = m_nType;
  69. m_nType = nStyle;
  70. return m_nOldStyle;
  71. }
  72. int CSplitterControl::GetStyle()
  73. {
  74. return m_nType;
  75. }
  76. void CSplitterControl::OnPaint() 
  77. {
  78. CPaintDC dc(this); // device context for painting
  79. CRect rcClient;
  80. GetClientRect(rcClient);
  81. CBrush br, *pOB;
  82. CPen pen, *pOP;
  83. dc.Draw3dRect(rcClient, RGB(255, 255, 255), RGB(255, 255, 255));
  84. rcClient.DeflateRect(1,1,1,1);
  85. pen.CreatePen(0, 1, RGB(255, 255, 255));
  86. br.CreateSolidBrush(RGB(255, 255, 255));
  87. pOB = dc.SelectObject(&br);
  88. pOP = dc.SelectObject(&pen);
  89. dc.Rectangle(rcClient);
  90. // Restore pen and brush
  91. DeleteObject(dc.SelectObject(pOB));
  92. DeleteObject(dc.SelectObject(pOP));
  93. }
  94. void CSplitterControl::OnMouseMove(UINT nFlags, CPoint point) 
  95. {
  96. if (m_bIsPressed)
  97. {
  98. CWindowDC dc(NULL);
  99. DrawLine(&dc, m_nX, m_nY);
  100. CPoint pt = point;
  101. ClientToScreen(&pt);
  102. GetParent()->ScreenToClient(&pt);
  103. //CWnd* pParent = pWnd->GetParent();
  104. if (pt.x < m_nMin)
  105. pt.x = m_nMin;
  106. if (pt.y < m_nMin)
  107. pt.y = m_nMin;
  108. if (pt.x > m_nMax)
  109. pt.x = m_nMax;
  110. if (pt.y > m_nMax)
  111. pt.y = m_nMax;
  112. GetParent()->ClientToScreen(&pt);
  113. m_nX = pt.x;
  114. m_nY = pt.y;
  115. DrawLine(&dc, m_nX, m_nY);
  116. }
  117. CStatic::OnMouseMove(nFlags, point);
  118. }
  119. BOOL CSplitterControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  120. {
  121. if (nHitTest == HTCLIENT)
  122. {
  123. (m_nType == SPS_VERTICAL)?(::SetCursor(SplitterControl_hCursor1))
  124. :(::SetCursor(SplitterControl_hCursor2));
  125. return 0;
  126. }
  127. else
  128. return CStatic::OnSetCursor(pWnd, nHitTest, message);
  129. }
  130. void CSplitterControl::OnLButtonDown(UINT nFlags, CPoint point) 
  131. {
  132. CStatic::OnLButtonDown(nFlags, point);
  133. m_bIsPressed = TRUE;
  134. SetCapture();
  135. CRect rcWnd;
  136. GetWindowRect(rcWnd);
  137. if (m_nType == SPS_VERTICAL)
  138. m_nX = rcWnd.left + rcWnd.Width() / 2;
  139. else
  140. m_nY = rcWnd.top  + rcWnd.Height() / 2;
  141. if (m_nType == SPS_VERTICAL)
  142. m_nSavePos = m_nX;
  143. else
  144. m_nSavePos = m_nY;
  145. CWindowDC dc(NULL);
  146. DrawLine(&dc, m_nX, m_nY);
  147. }
  148. void CSplitterControl::OnLButtonUp(UINT nFlags, CPoint point) 
  149. {
  150. if (m_bIsPressed)
  151. {
  152. ClientToScreen(&point);
  153. CWindowDC dc(NULL);
  154. DrawLine(&dc, m_nX, m_nY);
  155. CPoint pt(m_nX, m_nY);
  156. m_bIsPressed = FALSE;
  157. CWnd *pOwner = GetOwner();
  158. if (pOwner && IsWindow(pOwner->m_hWnd))
  159. {
  160. CRect rc;
  161. int delta;
  162. pOwner->GetClientRect(rc);
  163. pOwner->ScreenToClient(&pt);
  164. MoveWindowTo(pt);
  165. if (m_nType == SPS_VERTICAL)
  166. delta = m_nX - m_nSavePos;
  167. else
  168. delta = m_nY - m_nSavePos;
  169. SPC_NMHDR nmsp;
  170. nmsp.hdr.hwndFrom = m_hWnd;
  171. nmsp.hdr.idFrom   = GetDlgCtrlID();
  172. nmsp.hdr.code     = SPN_SIZED;
  173. nmsp.delta = delta;
  174. pOwner->SendMessage(WM_NOTIFY, nmsp.hdr.idFrom, (LPARAM)&nmsp);
  175. }
  176. }
  177. CStatic::OnLButtonUp(nFlags, point);
  178. ReleaseCapture();
  179. }
  180. void CSplitterControl::DrawLine(CDC* pDC, int x, int y)
  181. {
  182. int nRop = pDC->SetROP2(R2_NOTXORPEN);
  183. CRect rcWnd;
  184. int d = 1;
  185. GetWindowRect(rcWnd);
  186. CPen  pen;
  187. pen.CreatePen(0, 1, RGB(20, 20, 20));
  188. CPen *pOP = pDC->SelectObject(&pen);
  189. if (m_nType == SPS_VERTICAL)
  190. {
  191. pDC->MoveTo(m_nX - d, rcWnd.top);
  192. pDC->LineTo(m_nX - d, rcWnd.bottom);
  193. pDC->MoveTo(m_nX + d, rcWnd.top);
  194. pDC->LineTo(m_nX + d, rcWnd.bottom);
  195. }
  196. else // m_nType == SPS_HORIZONTAL
  197. {
  198. pDC->MoveTo(rcWnd.left, m_nY - d);
  199. pDC->LineTo(rcWnd.right, m_nY - d);
  200. pDC->MoveTo(rcWnd.left, m_nY + d);
  201. pDC->LineTo(rcWnd.right, m_nY + d);
  202. }
  203. pDC->SetROP2(nRop);
  204. pDC->SelectObject(pOP);
  205. }
  206. void CSplitterControl::MoveWindowTo(CPoint pt)
  207. {
  208. CRect rc;
  209. GetWindowRect(rc);
  210. CWnd* pParent;
  211. pParent = GetParent();
  212. if (!pParent || !::IsWindow(pParent->m_hWnd))
  213. return;
  214. pParent->ScreenToClient(rc);
  215. if (m_nType == SPS_VERTICAL)
  216. {
  217. int nMidX = (rc.left + rc.right) / 2;
  218. int dx = pt.x - nMidX;
  219. rc.OffsetRect(dx, 0);
  220. }
  221. else
  222. {
  223. int nMidY = (rc.top + rc.bottom) / 2;
  224. int dy = pt.y - nMidY;
  225. rc.OffsetRect(0, dy);
  226. }
  227. MoveWindow(rc);
  228. }
  229. void CSplitterControl::ChangeWidth(CWnd *pWnd, int dx, DWORD dwFlag)
  230. {
  231. CWnd* pParent = pWnd->GetParent();
  232. if (pParent && ::IsWindow(pParent->m_hWnd))
  233. {
  234. CRect rcWnd;
  235. pWnd->GetWindowRect(rcWnd);
  236. pParent->ScreenToClient(rcWnd);
  237. if (dwFlag == CW_LEFTALIGN)
  238. rcWnd.right += dx;
  239. else if (dwFlag == CW_RIGHTALIGN)
  240. rcWnd.left -= dx;
  241. pWnd->MoveWindow(rcWnd);
  242. }
  243. }
  244. void CSplitterControl::ChangeHeight(CWnd *pWnd, int dy, DWORD dwFlag)
  245. {
  246. CWnd* pParent = pWnd->GetParent();
  247. if (pParent && ::IsWindow(pParent->m_hWnd))
  248. {
  249. CRect rcWnd;
  250. pWnd->GetWindowRect(rcWnd);
  251. pParent->ScreenToClient(rcWnd);
  252. if (dwFlag == CW_TOPALIGN)
  253. rcWnd.bottom += dy;
  254. else if (dwFlag == CW_BOTTOMALIGN)
  255. rcWnd.top -= dy;
  256. pWnd->MoveWindow(rcWnd);
  257. }
  258. }
  259. void CSplitterControl::ChangePos(CWnd* pWnd, int dx, int dy)
  260. {
  261. CWnd* pParent = pWnd->GetParent();
  262. if (pParent && ::IsWindow(pParent->m_hWnd))
  263. {
  264. CRect rcWnd;
  265. pWnd->GetWindowRect(rcWnd);
  266. pParent->ScreenToClient(rcWnd);
  267. rcWnd.OffsetRect(-dx, dy);
  268. pWnd->MoveWindow(rcWnd);
  269. }
  270. }
  271. void CSplitterControl::SetRange(int nMin, int nMax)
  272. {
  273. m_nMin = nMin;
  274. m_nMax = nMax;
  275. }