Применение Windows API - [25]
Без дальнейшей суеты приведем код WinMain, который осуществляет начальные установки.
>// Create top window class
>TopWinClassMaker topWinClass(WndProcMain, ID_MAIN, hInst, ID_MAIN);
>topWinClass.Register();
>// Create child pane classes
>WinClassMaker paneClass(WndProcPane, IDC_PANE, hInst);
>paneClass.SetSysCursor(IDC_IBEAM);
>paneClass.SetDblClicks();
>paneClass.Register();
>Splitter::RegisterClass(hInst);
>// Create top window
>ResString caption(hInst, ID_CAPTION);
>TopWinMaker topWin(caption, ID_MAIN, hInst);
>topWin.Create();
>topWin.Show(cmdShow);
В начале мы регистрируем классы. Верхний оконный класс связан с его оконной процедурой WndProcMain, которую мы рассмотрим через мгновение. Два дочерних подокна совместно используют тот же самый класс окна, связанный с WndProcPane. Затем регистрируется наш собственный класс сплиттера (мы скоро увидем его код). В заключение, создается и отображается верхнее окно. Дочерние окна создаются динамически во время инициализации родительского окна.
Приведем оконную процедуру верхнего окна.
>LRESULT CALLBACK WndProcMain(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
> Controller* pCtrl = GetWinLong
> switch (message) {
> case WM_CREATE:
> try {
> pCtrl = new Controller(hwnd, reinterpret_cast
> SetWinLong
> } 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 MSG_MOVESPLITTER:
> pCtrl->MoveSplitter(wParam);
> return 0;
> case WM_DESTROY:
> SetWinLong
> delete pCtrl;
> return 0;
> }
> return ::DefWindowProc(hwnd, message, wParam, lParam);
>}
Имеем обычную оконную процедуру за исключением одного сообщения: MSG_MOVESPLITTER. Это — наше собственное, определяемое пользователем сообщение, которое послано сплиттером его родительскому окну. Но сначала давайте взглянем на контроллер главного окна.
>class Controller {
>public:
> Controller(HWND hwnd, CREATESTRUCT* pCreat);
> ~Controller();
> void Size(int cx, int cy);
> void MoveSplitter(int x);
>private:
> enum { splitWidth = 8 }; // width of splitter
> // User Interface
> HWnd _hwnd;
> //Main controller window
> HWnd _leftWin;
> HWnd _rightWin;
> HWnd _splitter;
> int _splitRatio; // in per cent
> int _cx;
> int _cy;
>};
Контроллер содержит дескриптор своего окна, двух дочерних подокон, и окна сплиттера. Он также сохраняет текущий коэффициент разбиения, в процентах.
Конструктор контроллера отвечает за создание дочерних окон.
>Controller::Controller(HWND hwnd, CREATESTRUCT * pCreat) : _hwnd (hwnd), _leftWin (0), _rightWin (0), _splitter (0), _splitRatio (50) {
> // Create child windows
> {
> ChildWinMaker leftWinMaker(IDC_PANE, _hwnd, ID_LEFT_WINDOW);
> leftWinMaker.Create();
> _leftWin.Init(leftWinMaker);
> leftWinMaker.Show();
> }
> {
> ChildWinMaker rightWinMaker(IDC_PANE, _hwnd, ID_RIGHT_WINDOW);
> rightWinMaker.Create();
> _rightWin.Init(rightWinMaker);
> rightWinMaker.Show();
> }
> Splitter::MakeWindow(_splitter, _hwnd, ID_SPLITTER);
>}
Когда пользователь перемещает полоску расщепителя, родитель получает сообщение MSG_MOVESPLITTER . Параметр wParam содержит новое расстояние полосы расщепителя от левого края родительского окна. В ответ на такое сообщение, родитель должен также изменить размеры дочерних подокон и переместить расщепитель. Он делает это, вызывая метод Size.
>void Controller::MoveSplitter(int x) {
> _splitRatio = x * 100 / _cx;
> if (_splitRatio < 0) _splitRatio = 0;
> else if (_splitRatio > 100) _splitRatio = 100;
> Size(_cx, _cy);
>}
Вообще же, Size вызывается всякий раз, когда пользователь изменяет размеры основного окна, но тот код который вытолько что видели, мы вызываем также тогда, когда сплиттер перемещается.
>void Controller::Size(int cx, int cy) {
> _cx = cx;
> _cy = cy;
> int xSplit = (_cx * _splitRatio) / 100;
> if (xSplit < 0) xSplit = 0;
> if (xSplit + splitWidth >= _cx) xSplit = _cx - splitWidth;
> _splitter.MoveDelayPaint(xSplit, 0, splitWidth, cy);
> _leftWin.Move(0, 0, xSplit, cy);
> _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);
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.