00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "FdmApp.h"
00008 #include "WndSplitter.h"
00009
00010 #ifdef _DEBUG
00011 #undef THIS_FILE
00012 static char THIS_FILE[]=__FILE__;
00013 #define new DEBUG_NEW
00014 #endif
00015
00016 CWndSplitter::CWndSplitter()
00017 {
00018 m_ratio = 0.5;
00019 m_dim = 5;
00020 m_startDrag = -1;
00021 m_dim1min = m_dim2min = 3;
00022 m_bDragging = FALSE;
00023 }
00024
00025 CWndSplitter::~CWndSplitter()
00026 {
00027
00028 }
00029
00030 BOOL CWndSplitter::Create(HINSTANCE hInst, HWND hWndParent, WndSplitterType enType)
00031 {
00032 m_type = enType;
00033 m_wndParent = hWndParent;
00034 LPCSTR pszClassName = m_type == WST_VERTICAL ? "WndSplitter_Vertical" : "WndSplitter_Horizontal";
00035
00036 WNDCLASS wc = {
00037 0, _wndProc, 0, 0, hInst, NULL, LoadCursor (NULL, m_type == WST_VERTICAL ? IDC_SIZEWE : IDC_SIZENS),
00038 (HBRUSH) (COLOR_3DFACE+1), NULL, pszClassName
00039 };
00040
00041 RegisterClass (&wc);
00042
00043 m_wndSplitter = CreateWindow (pszClassName, NULL, WS_CHILD|WS_VISIBLE, 0, 0, 5, 5, hWndParent,
00044 NULL, hInst, 0);
00045
00046 SetWindowLong (m_wndSplitter, GWL_USERDATA, (LONG) this);
00047
00048 return TRUE;
00049 }
00050
00051 LRESULT CALLBACK CWndSplitter::_wndProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp)
00052 {
00053 CWndSplitter *pThis = (CWndSplitter*) GetWindowLong (hWnd, GWL_USERDATA);
00054
00055 switch (uMsg)
00056 {
00057 case WM_PAINT:
00058 pThis->OnPaint ();
00059 return 0;
00060
00061 case WM_LBUTTONDOWN:
00062 pThis->OnLButtonDown ();
00063 break;
00064
00065 case WM_MOUSEMOVE:
00066 if (wp & MK_LBUTTON)
00067 pThis->OnMouseDrag (MAKEPOINTS (lp));
00068 return 0;
00069
00070 case WM_LBUTTONUP:
00071 pThis->OnLButtonUp (MAKEPOINTS (lp));
00072 return 0;
00073
00074 case WM_CAPTURECHANGED:
00075 pThis->OnCaptureChanged ();
00076 return 0;
00077 }
00078
00079 return DefWindowProc (hWnd, uMsg, wp, lp);
00080 }
00081
00082 void CWndSplitter::SetWnd1(HWND hWnd)
00083 {
00084 m_wnd1 = hWnd;
00085 }
00086
00087 void CWndSplitter::SetWnd2(HWND hWnd)
00088 {
00089 m_wnd2 = hWnd;
00090 }
00091
00092 void CWndSplitter::ApplyRatio()
00093 {
00094 RECT rcParent, rcWnd1, rcWnd2, rcSplit;
00095
00096 GetClientRect (m_wndParent, &rcParent);
00097
00098 rcWnd1.top = rcWnd1.left = 0;
00099 rcWnd2.right = rcParent.right; rcWnd2.bottom = rcParent.bottom;
00100
00101 switch (m_type)
00102 {
00103 case WST_VERTICAL:
00104 rcWnd1.right = (LONG)(rcParent.right * m_ratio + 0.5f) - m_dim / 2;
00105 rcWnd1.bottom = rcParent.bottom+1;
00106 rcWnd2.left = rcWnd1.right + m_dim + 1;
00107 rcWnd2.top = 0;
00108 rcSplit.top = 0; rcSplit.left = rcWnd1.right;
00109 rcSplit.right = rcWnd2.left; rcSplit.bottom = rcParent.bottom;
00110 break;
00111
00112 case WST_HORIZONTAL:
00113 rcWnd1.right = rcParent.right+1;
00114 rcWnd1.bottom = (LONG)(rcParent.bottom * m_ratio + 0.5f) - m_dim / 2;
00115 rcWnd2.top = rcWnd1.bottom + m_dim + 1;
00116 rcWnd2.left = 0;
00117 rcSplit.top = rcWnd1.bottom; rcSplit.left = 0;
00118 rcSplit.right = rcParent.right; rcSplit.bottom = rcWnd2.top;
00119 break;
00120
00121 default:
00122 return;
00123 }
00124
00125 MoveWindow (m_wnd1, rcWnd1.left, rcWnd1.top, rcWnd1.right - rcWnd1.left,
00126 rcWnd1.bottom - rcWnd1.top, TRUE);
00127
00128 MoveWindow (m_wnd2, rcWnd2.left, rcWnd2.top, rcWnd2.right - rcWnd2.left,
00129 rcWnd2.bottom - rcWnd2.top, TRUE);
00130
00131 MoveWindow (m_wndSplitter, rcSplit.left, rcSplit.top, rcSplit.right - rcSplit.left,
00132 rcSplit.bottom - rcSplit.top, TRUE);
00133 }
00134
00135 void CWndSplitter::OnPaint()
00136 {
00137 PAINTSTRUCT ps;
00138 HDC hdc;
00139 RECT rc;
00140
00141 GetClientRect (m_wndSplitter, &rc);
00142
00143 hdc = BeginPaint (m_wndSplitter, &ps);
00144
00145 if (m_type == WST_VERTICAL)
00146 DrawVerticalFrame (hdc, 0, rc.right-1, 0, rc.bottom);
00147 else
00148 DrawHorizontalFrame (hdc, 0, rc.bottom-1, 0, rc.right);
00149
00150 EndPaint (m_wndSplitter, &ps);
00151 }
00152
00153 void CWndSplitter::OnLButtonDown()
00154 {
00155
00156 SetCapture (m_wndSplitter);
00157
00158 m_bDragging = TRUE;
00159
00160 RECT rc;
00161 GetWindowRect (m_wndSplitter, &rc);
00162
00163 if (m_type == WST_VERTICAL)
00164 m_drag = rc.left + m_dim / 2;
00165 else
00166 m_drag = rc.top + m_dim / 2;
00167
00168 m_startDrag = m_drag;
00169
00170 DrawSizingFrame ();
00171 }
00172
00173 void CWndSplitter::DrawSizingFrame()
00174 {
00175 HDC hdc = GetDC (m_wndParent);
00176 RECT rc;
00177
00178 GetWindowRect (m_wndSplitter, &rc);
00179
00180 if (m_type == WST_VERTICAL)
00181 {
00182 rc.left = m_drag - m_dim / 2 + 2;
00183 rc.right = rc.left + m_dim - 2;
00184 }
00185 else
00186 {
00187 rc.top = m_drag - m_dim / 2 + 2;
00188 rc.bottom = m_drag + m_dim - 2;
00189 }
00190
00191 ScreenToClient (m_wndParent, (LPPOINT) &rc);
00192 ScreenToClient (m_wndParent, ((LPPOINT) &rc)+1);
00193
00194 SetROP2 (hdc, R2_NOTXORPEN);
00195
00196 HPEN hPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_3DSHADOW));
00197 HBRUSH hbr = CreateSolidBrush (GetSysColor (COLOR_3DSHADOW));
00198 HGDIOBJ hOldPen, hOldBr;
00199
00200 hOldPen = SelectObject (hdc, hPen);
00201 hOldBr = SelectObject (hdc, hbr);
00202
00203 Rectangle (hdc, rc.left, rc.top, rc.right, rc.bottom);
00204
00205 SelectObject (hdc, hOldPen);
00206 SelectObject (hdc, hOldBr);
00207
00208 DeleteObject (hPen);
00209 DeleteObject (hbr);
00210
00211 ReleaseDC (m_wndParent, hdc);
00212 }
00213
00214 void CWndSplitter::OnMouseDrag(POINTS pt)
00215 {
00216 if (m_startDrag == -1)
00217 return;
00218
00219 POINT Pt;
00220
00221 Pt.x = pt.x;
00222 Pt.y = pt.y;
00223
00224 RECT rcParent;
00225
00226 GetWindowRect (m_wndParent, &rcParent);
00227 ClientToScreen (m_wndSplitter, &Pt);
00228
00229 if (m_type == WST_VERTICAL)
00230 {
00231
00232 if (Pt.x < rcParent.left + m_dim1min || Pt.x > rcParent.right - m_dim2min)
00233 return;
00234
00235 DrawSizingFrame ();
00236 m_drag = Pt.x;
00237 }
00238 else
00239 {
00240 if (Pt.y < rcParent.top + m_dim1min || Pt.y > rcParent.bottom - m_dim2min )
00241 return;
00242
00243 DrawSizingFrame ();
00244 m_drag = Pt.y;
00245 }
00246
00247 DrawSizingFrame ();
00248 }
00249
00250 void CWndSplitter::OnLButtonUp(POINTS )
00251 {
00252 if (m_bDragging == FALSE)
00253 return;
00254
00255 m_bDragging = FALSE;
00256
00257 DrawSizingFrame ();
00258
00259 RECT rcParent;
00260 GetClientRect (m_wndParent, &rcParent);
00261
00262 float parentDim = m_type == WST_VERTICAL ? (FLOAT) rcParent.right : (FLOAT) rcParent.bottom;
00263
00264 float dRatio = (m_drag - m_startDrag) / parentDim;
00265
00266 m_ratio += dRatio;
00267
00268 if (m_ratio < 0)
00269 m_ratio = 0;
00270 else if (m_ratio > 1)
00271 m_ratio = 1;
00272
00273 ApplyRatio ();
00274
00275 m_startDrag = -1;
00276
00277 ReleaseCapture ();
00278
00279 InvalidateRect (m_wndSplitter, NULL, FALSE);
00280 }
00281
00282 void CWndSplitter::OnCaptureChanged()
00283 {
00284 if (m_startDrag != -1)
00285 {
00286
00287 DrawSizingFrame ();
00288 m_startDrag = -1;
00289 InvalidateRect (m_wndSplitter, NULL, FALSE);
00290 }
00291 }
00292
00293 void CWndSplitter::SetMinDimensions(int wnd1, int wnd2)
00294 {
00295 m_dim1min = wnd1;
00296 m_dim2min = wnd2;
00297 }
00298
00299 void CWndSplitter::SetRatio(float fRatio)
00300 {
00301 m_ratio = fRatio;
00302 }
00303
00304 void CWndSplitter::RecalRatio(BOOL bWnd1MustNotResize)
00305 {
00306 RECT rcWnd, rcParent;
00307 HWND hWnd = bWnd1MustNotResize ? m_wnd1 : m_wnd2;
00308
00309 GetWindowRect (hWnd, &rcWnd);
00310 GetClientRect (m_wndParent, &rcParent);
00311
00312 int wndDim = m_type == WST_VERTICAL ? rcWnd.right-rcWnd.left : rcWnd.bottom-rcWnd.top;
00313 int parentDim = m_type == WST_VERTICAL ? rcParent.right : rcParent.bottom;
00314
00315 wndDim += m_dim / 2;
00316
00317 if (bWnd1MustNotResize)
00318 m_ratio = (FLOAT) wndDim / parentDim;
00319 else
00320 m_ratio = 1.0f - ((FLOAT) wndDim / parentDim);
00321 }
00322
00323 float CWndSplitter::GetRatio()
00324 {
00325 return m_ratio;
00326 }