> _rightWin.Move(xSplit+splitWidth, 0, cx-xSplit-splitWidth, cy);
> _splitter.ForceRepaint ();
>}
Обратите внимание на используемый здесь важный прием. Мы перемещаем расщепитель, но задерживаем его перерисовку до изменения его обоих подокон, расположенных слева и справа. Эта методика устраняет некоторое неприятное смазывание изображения.
Выше была представлена реализация клиентского кода. Теперь, я надеюсь, Вам будет интересно увидеть реализацию сплиттера.
Прежде всего нам приятно объединить зависимые функции в пространство имен. Вам видны вызовы Splitter::RegisterClass и Splitter::MakeWindow. Splitter в этих именах — это namespace.
>namespace Splitter {
> void RegisterClass(HINSTANCE hInst);
> void MakeWindow(HWnd& hwndSplitter /* out */, HWnd hwndParent, int childId);
>};
Ниже приводится реализация этих функций.
>LRESULT CALLBACK WndProcSplitter(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
>void Splitter::RegisterClass(HINSTANCE hInst) {
> WinClassMaker splitterClass(WndProcSplitter, "RsSplitterClass", hInst);
> splitterClass.SetSysCursor(IDC_SIZEWE);
> splitterClass.SetBgSysColor(COLOR_3DFACE);
> splitterClass.Register();
>}
>void Splitter::MakeWindow(HWnd& hwndSplitter, HWnd hwndParent, int childId) {
> ChildWinMaker splitterMaker("RsSplitterClass", hwndParent, childId);
> splitterMaker.Create(); hwndSplitter.Init(splitterMaker);
> splitterMaker.Show();
>}
Курсор мыши IDC_SIZEWE мы связываем с классом расщепителя — это стандартная, «направленная с запада на восток», двунаправленная стрелка. Мы также устанавливаем фоновую кисть к COLOR_3DFACE.
Оконная процедура расщепителя имеет дело с созданием/разрушением расщепителя, прорисовкой и перемещением мыши.
>LRESULT CALLBACK WndProcSplitter(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
> SplitController* pCtrl = GetWinLong(hwnd);
> switch (message) {
> case WM_CREATE:
> try {
> pCtrl = new SplitController(hwnd, reinterpret_cast(lParam));
> SetWinLong(hwnd, pCtrl);
> } catch (char const * msg) {
> MessageBox(hwnd, msg, "Initialization", MB_ICONEXCLAMATION | MB_OK);
> return -1;
> } catch (...) {
> MessageBox(hwnd, "Unknown Error", "Initialization", MB_ICONEXCLAMATION | MB_OK);
> return -1;
> }
> return 0;
> case WM_SIZE:
> pCtrl->Size(LOWORD(lParam), HIWORD(lParam));
> return 0;
> case WM_PAINT:
> pCtrl->Paint();
> return 0;
> case WM_LBUTTONDOWN:
> pCtrl->LButtonDown(MAKEPOINTS(lParam));
> return 0;
> case WM_LBUTTONUP:
> pCtrl->LButtonUp(MAKEPOINTS(lParam));
> return 0;
> case WM_MOUSEMOVE:
> if (wParam & MK_LBUTTON) pCtrl->LButtonDrag(MAKEPOINTS(lParam));
> return 0;
> case WM_CAPTURECHANGED:
> pCtrl->CaptureChanged();
> return 0;
> case WM_DESTROY:
> SetWinLong(hwnd, 0);
> delete pCtrl;
> return 0;
> }
> return ::DefWindowProc(hwnd, message, wParam, lParam);
>}
Это, в значительной степени, стандартный код. Подробности, как обычно, находятся в методах контроллера. Конструктор очень прост.
>SplitController::SplitController(HWND hwnd, CREATESTRUCT * pCreat) : _hwnd (hwnd), _hwndParent (pCreat->hwndParent) {}
Прорисовка более интересна. Мы должны имитировать эффекты 2.5-размерности Windows. Мы делаем это путем тщательного отбора перьев.
>class Pens3d {
>public:
> Pens3d();
> Pen& Hilight() { return _penHilight; }
> Pen& Light() { return _penLight; }
> Pen& Shadow() { return _penShadow; }
> Pen& DkShadow() { return _penDkShadow; }
>private:
> Pen _penHilight;
> Pen _penLight;
> Pen _penShadow;
> Pen _penDkShadow;
>};
>Pens3d::Pens3d() : _penLight(GetSysColor(COLOR_3DLIGHT)), _penHilight(GetSysColor(COLOR_3DHILIGHT)), _penShadow(GetSysColor(COLOR_3DSHADOW)), _penDkShadow(GetSysColor(COLOR_3DDKSHADOW)) {}
>void SplitController::Paint() {
> PaintCanvas canvas(_hwnd);
> {
> PenHolder pen(canvas, _pens.Light());
> canvas.Line(0, 0, 0, _cy - 1);
> }
> {
> PenHolder pen(canvas, _pens.Hilight());
> canvas.Line(1, 0, 1, _cy - 1);
> }
> {
> PenHolder pen(canvas, _pens.Shadow());
> canvas.Line(_cx - 2, 0, _cx - 2, _cy - 1);
> }
> {
> PenHolder pen(canvas, _pens.DkShadow());
> canvas.Line(_cx - 1, 0, _cx - 1, _cy - 1);
> }
>}
Более сложной является обработка сообщений от мыши, хотя значительная часть этого кода довольно стандартна. Мы должны обработать перемещение мыши и нажатие кнопки.