Шаг 19 - Сдвиг графического изображения

Создание проекта

Дополняем наш проект. Мы создадим метод, с помощью которого будет передвигать изображение. Нажал мышку и потащил. Нам надо методу указанным в Шаге 16 создать класс CScreenPos.

19_1.gif (2193 b)

Создаем код

Изменить описание класса CScreenPos.

#endif //_MSC_VER > 1000
#include "afxwin.h"
class CScreenPos
{
public:
CScreenPos();
virtual ~CScreenPos();
CPoint GetPoint(); // получить текущею точку
void MovePoint(CPoint cp); // переместить точку
private:
CPoint cpXY; // переменная для хранения точки
};
#endif // !defined(AFX_SCREENPOS_H__4ACEB32D_6D4C_11D5_B617_C3FF8A155D47__INCLUDED_)

Реализация функций.

// ScreenPos.cpp: implementation of the CScreenPos class.
//
//////////////////////////////////////////////////////////////////////

#include "ScreenPos.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CScreenPos::CScreenPos()
{
cpXY=CPoint(0,0); // начальные установки
}
CScreenPos::~CScreenPos()
{
}
CPoint CScreenPos::GetPoint()
{
return cpXY; // вернуть координату
}
void CScreenPos::MovePoint(CPoint cp)
{
cpXY+=cp; // изменить координату
}

Добавляем объявление нашего класса к основному модулю.

.........
#include "MyClip.h" // описание нашего класса
#include "ScreenPos.h" // класс координаты
#define IDC_MYBUTTON 100 // Идентификатор кнопки
........

Изменения в классе рамки окна добавляем события нажатия и отпускания левой кнопки мыши, объект класса котрый создали и дополнительные переменные.

class CMainWnd : public CFrameWnd
{
public:
...........
afx_msg void OnKeyDown( UINT, UINT, UINT ); // виртуальная процедура ответа на клавишу
afx_msg void OnLButtonUp( UINT, CPoint cp); // кнопка мыши вверх
afx_msg void OnLButtonDown( UINT, CPoint cp); // кнопка мыши вниз

int OnCreate(LPCREATESTRUCT lpCreateStruct); // эта функция вызывается при создании окна
...................
CMyClip clip; // Это класс буфера обмена
CScreenPos position; // Это класс координат
BOOL blFlagMove; // Это флаг перемещения
CPoint TempPoint; // Временная переменная

DECLARE_MESSAGE_MAP(); // таблица откликов
};

Изменение в конструкторе рамки окна.

CMainWnd::CMainWnd()
{
blFlagMove=FALSE; // начальное состояние, мышь не перемещаеться
blMenu=FALSE; // инициализация TRUE соответствует IDR_MENU
.............
}

Изменения в таблице откликов для реакции на нажатие и отпускания клавиш мыши.

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd) 	       // таблица откликов на сообщения 
..............
ON_WM_RBUTTONDBLCLK() // реакция на нажатие правой кнопки мышки
ON_WM_LBUTTONDOWN() // кто то нажал на левую кнопку мыши
ON_WM_LBUTTONUP() // кто то отпустил левую кнопку мыши

ON_WM_KEYDOWN() // реакция на нажатие клавиши
...........
END_MESSAGE_MAP()

Реализация объявленных функций.

void CMainWnd::OnLButtonDown( UINT, CPoint cp)
{
blFlagMove=true; // мышка нажата, установить флаг
TempPoint=cp; // запомнить точку
}
void CMainWnd::OnLButtonUp( UINT, CPoint cp)
{
if (blFlagMove) // если флаг установлен
{
position.MovePoint(cp-TempPoint); // менять позицию
Invalidate(TRUE); // перерисовывать экран
my_ToolBar.Invalidate(TRUE); // панель инструментов
}
blFlagMove=false; // отменить флаг
}

Изменение функции перерисовки экрана.

void CMainWnd::OnPaint()
{
CMyPaintDC dc(this); // наш класс
dc.SetViewportOrg(position.GetPoint()); // поменять точку координат
CPen MyPen(PS_DASHDOT,1,RGB(0,255,0)); // настраиваем перо
........
}

Можно запускать.

19_2.gif (8564 b)

Описание

Мы локализовали данные по координатам начала экрана в отдельном класса CScreenPos. Это удобно и я думаю правильно. В классе рамки окна и так много данных и кода. Реализация его очень простая. В конструкторе устанавливаются координаты по нулям. Возврат точки, для получения координат и перемещение точки. В классе CPoint перегружены многие функции +,-,=,== и т.д. Этим я и воспользовался. cpXY+=cp; это тоже самое, что и cpXY=cpXY+cp;. Вообще C++ обладает возможностью сделать код совершенно нечитаемым, из за многих сокращений, но это дело привычки. Вероятно это хорошая привычка, раз мы пишем на C++.

Раз мы создали класс в отдельном модуле тому кто будет его использовать необходимо объявить о его наличии. Это мы делаем с помощью #include "ScreenPos.h". Далее мы создали статический объект этого класса в классе рамки окна. Так мы делали вроде часто.

Дальше идея в следующем. Когда нажимается левая кнопка мыши (вниз) происходит событие ON_WM_LBUTTONDOWN() для этого события и описана функция OnLButtonUp. Аналогично и при поднятии кнопки (вверх). При нажатии на кнопку мы выставляем флаг нажатия и запоминаем текущее положение мыши. При отпускании вычисляем разность (смешение) и изменяем данные в классе CScreenPos. Вызываем перерисовку экрана с помощью Invalidate(TRUE); и снимаем флаг. После вызова функции Invalidate совершится перерисовка экрана, которая реализована в функции OnPaint. В ней то мы и устанавливаем положение экрана с помощью функции SetViewportOrg.

У Вас должны остаться крестики от старых уроков. Потаскайте за них. Они будут следовать за курсором.

Шпаргалка

Координаты изображения устанавливаются в OnPaint

Установка производится функцией SetViewportOrg.

Если координаты меняются за пределами OnPaint , обновите экран функцией Invalidate(TRUE);


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем.