Применение Windows API - страница 32

Шрифт
Интервал

стр.

> _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);

> }

>}

Более сложной является обработка сообщений от мыши, хотя значительная часть этого кода довольно стандартна. Мы должны обработать перемещение мыши и нажатие кнопки.


стр.

Похожие книги