#pragma once;
#include <iostream>
using namespace std;
#include <windows.h>
#include <atlstr.h>
#include <cstring>
enum Direction {LEFT, RIGHT, UP, DOWN};
class Shape
{
public:
Shape();
virtual ~Shape() = 0;
virtual double square() = 0;
virtual void draw() = 0;
virtual void move(Direction, int) = 0;
virtual int IsInside(int x, int y) = 0;
protected:
HWND hwnd;
HDC hdc;
COLORREF color;
int left, top, right, bottom;
CString str;
};
Рисование геометрических фигур в консольном приложении (vs2005)
shape.h
Код:
shape.cpp
Код:
#include <iostream>
using namespace std;
#include <conio.h>
#include "shape.h"
Shape::Shape()
{
hwnd = 0;
SetConsoleTitle((LPCWSTR) L"Shape");
if ((hwnd = FindWindow(NULL, (LPCWSTR) L"Shape")) == 0)
{
cout<<"Window not found!!!"<<endl;
return;
}
if ((hdc = GetDC(hwnd)) == 0)
{
cout<<"O6ibka!!!"<<endl;
return;
}
}
/////////////////////////////////////////////////////////
Shape::~Shape()
{
ReleaseDC(hwnd,hdc);
}
using namespace std;
#include <conio.h>
#include "shape.h"
Shape::Shape()
{
hwnd = 0;
SetConsoleTitle((LPCWSTR) L"Shape");
if ((hwnd = FindWindow(NULL, (LPCWSTR) L"Shape")) == 0)
{
cout<<"Window not found!!!"<<endl;
return;
}
if ((hdc = GetDC(hwnd)) == 0)
{
cout<<"O6ibka!!!"<<endl;
return;
}
}
/////////////////////////////////////////////////////////
Shape::~Shape()
{
ReleaseDC(hwnd,hdc);
}
circle.h
Код:
#pragma once;
#include "shape.h"
class Circle : public Shape
{
private:
int cx, cy, radius;
public:
Circle(int x = 0, int y = 0, int r = 0, COLORREF c = RGB(0,0,0));
void draw();
void move(Direction, int);
double square();
int IsInside(int x, int y);
};
#include "shape.h"
class Circle : public Shape
{
private:
int cx, cy, radius;
public:
Circle(int x = 0, int y = 0, int r = 0, COLORREF c = RGB(0,0,0));
void draw();
void move(Direction, int);
double square();
int IsInside(int x, int y);
};
circle.cpp
Код:
#include "circle.h"
#include <conio.h>
Circle::Circle(int x, int y, int r, COLORREF c) : Shape()
{
cx = x; cy = y; radius = r;
color = c;
left = cx - radius; top = cy - radius;
right = cx + radius; bottom = cy + radius;
}
void Circle::draw()
{
HPEN pen;
HBRUSH brush;
pen = CreatePen(PS_SOLID, 2, RGB(0,150,0));
brush = CreateSolidBrush(color);
SelectObject(hdc, pen); SelectObject(hdc, brush);
Ellipse(hdc, cx - radius, cy - radius, cx + radius, cy + radius);
DeleteObject(pen); DeleteObject(brush);
}
int Circle::IsInside(int x, int y)
{return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= radius * radius;}
double Circle::square()
{return 3.1415926536 * radius * radius;}
void Circle::move(Direction way, int distance)
{
InvalidateRect(hwnd, NULL, 1);
switch(way)
{
case LEFT:
str = " Влево";
cx -= distance;
break;
case RIGHT:
str = "Вправо";
cx += distance;
break;
case UP:
str = "Вверх";
cy -= distance;
break;
case DOWN:
str = "Вниз";
cy += distance;
break;
default:break;
}
TextOut(hdc,200,1,str,20);
}
#include <conio.h>
Circle::Circle(int x, int y, int r, COLORREF c) : Shape()
{
cx = x; cy = y; radius = r;
color = c;
left = cx - radius; top = cy - radius;
right = cx + radius; bottom = cy + radius;
}
void Circle::draw()
{
HPEN pen;
HBRUSH brush;
pen = CreatePen(PS_SOLID, 2, RGB(0,150,0));
brush = CreateSolidBrush(color);
SelectObject(hdc, pen); SelectObject(hdc, brush);
Ellipse(hdc, cx - radius, cy - radius, cx + radius, cy + radius);
DeleteObject(pen); DeleteObject(brush);
}
int Circle::IsInside(int x, int y)
{return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= radius * radius;}
double Circle::square()
{return 3.1415926536 * radius * radius;}
void Circle::move(Direction way, int distance)
{
InvalidateRect(hwnd, NULL, 1);
switch(way)
{
case LEFT:
str = " Влево";
cx -= distance;
break;
case RIGHT:
str = "Вправо";
cx += distance;
break;
case UP:
str = "Вверх";
cy -= distance;
break;
case DOWN:
str = "Вниз";
cy += distance;
break;
default:break;
}
TextOut(hdc,200,1,str,20);
}
triangle.h
Код:
#pragma once;
#include "shape.h"
#include <cmath>
class Triangle : public Shape
{
protected:
int x1, y1, x2, y2, x3, y3;
public:
Triangle(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0, int x3 = 0, int y3 = 0, COLORREF c = RGB(0,0,0));
void draw();
void move(Direction, int);
double square();
int IsInside(int x, int y);
};
#include "shape.h"
#include <cmath>
class Triangle : public Shape
{
protected:
int x1, y1, x2, y2, x3, y3;
public:
Triangle(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0, int x3 = 0, int y3 = 0, COLORREF c = RGB(0,0,0));
void draw();
void move(Direction, int);
double square();
int IsInside(int x, int y);
};
triangle.cpp
Код:
#include "triangle.h"
Triangle::Triangle(int x1, int y1, int x2, int y2, int x3, int y3, COLORREF c)
{
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
this->y2 = y2;
this->x3 = x3;
this->y3 = y3;
color = c;
left = min(x1, x2, x3);
top = min(y1, y2, y3);
right = max(x1, x2, x3);
bottom = max(y1, y2, y3);
}
void Triangle::draw()
{
HPEN pen;
HBRUSH brush;
POINT points[] = {{x1, y1}, {x2, y2}, {x3, y3}};
pen = CreatePen(PS_SOLID, 3, RGB(0,0,150));
brush = CreateSolidBrush(color);
SelectObject(hdc, pen); SelectObject(hdc, brush);
Polygon(hdc, points, 3);
DeleteObject(pen); DeleteObject(brush);
}
int Triangle::IsInside(int x, int y)
{
Triangle
t1(x1, y1, x2, y2, x, y),
t2(x1, y1, x3, y3, x, y),
t3(x2, y2, x3, y3, x, y);
if (fabs(square() - t1.square() - t2.square() - t3.square()) < 0.001)
return 1;
else
return 0;
}
double Triangle::square()
{return fabs((double)((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1))) / 2;}
void Triangle::move(Direction way, int distance)
{
InvalidateRect(hwnd, NULL, 1);
switch(way)
{
case LEFT:
str = "Влево";
x1 -= distance;
x2 -= distance;
x3 -= distance;
break;
case RIGHT:
str = "Вправо";
x1 += distance;
x2 += distance;
x3 += distance;
break;
case UP:
str = "Вверх";
y1 -= distance;
y2 -= distance;
y3 -= distance;
break;
case DOWN:
str = "Вниз";
y1 += distance;
y2 += distance;
y3 += distance;
break;
default:break;
}
TextOut(hdc,200,1,str,20);
}
Triangle::Triangle(int x1, int y1, int x2, int y2, int x3, int y3, COLORREF c)
{
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
this->y2 = y2;
this->x3 = x3;
this->y3 = y3;
color = c;
left = min(x1, x2, x3);
top = min(y1, y2, y3);
right = max(x1, x2, x3);
bottom = max(y1, y2, y3);
}
void Triangle::draw()
{
HPEN pen;
HBRUSH brush;
POINT points[] = {{x1, y1}, {x2, y2}, {x3, y3}};
pen = CreatePen(PS_SOLID, 3, RGB(0,0,150));
brush = CreateSolidBrush(color);
SelectObject(hdc, pen); SelectObject(hdc, brush);
Polygon(hdc, points, 3);
DeleteObject(pen); DeleteObject(brush);
}
int Triangle::IsInside(int x, int y)
{
Triangle
t1(x1, y1, x2, y2, x, y),
t2(x1, y1, x3, y3, x, y),
t3(x2, y2, x3, y3, x, y);
if (fabs(square() - t1.square() - t2.square() - t3.square()) < 0.001)
return 1;
else
return 0;
}
double Triangle::square()
{return fabs((double)((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1))) / 2;}
void Triangle::move(Direction way, int distance)
{
InvalidateRect(hwnd, NULL, 1);
switch(way)
{
case LEFT:
str = "Влево";
x1 -= distance;
x2 -= distance;
x3 -= distance;
break;
case RIGHT:
str = "Вправо";
x1 += distance;
x2 += distance;
x3 += distance;
break;
case UP:
str = "Вверх";
y1 -= distance;
y2 -= distance;
y3 -= distance;
break;
case DOWN:
str = "Вниз";
y1 += distance;
y2 += distance;
y3 += distance;
break;
default:break;
}
TextOut(hdc,200,1,str,20);
}
driver.cpp
Код:
#include <conio.h>
#include "circle.h"
#include "triangle.h"
void main()
{
Shape *myShape[2] = {
new Circle(300,100,50, RGB(100,0,200)),
new Triangle(150,100,100,200,200,200, RGB(200,40,10))
};
Shape *WShape = myShape[0];
myShape[0]->draw();
myShape[1]->draw();
while(1)
{
int c;
//int x = 0;
c = getch();
//c = getch();
switch(c)
{
case 49: //1
//x = 0;
WShape = myShape[0];
break;
case 50: //2
//x = 1;
WShape = myShape[1];
break;
case 75: //Влево
WShape->move(LEFT, 10);
break;
case 77: //Вправо
WShape->move(RIGHT, 10);
break;
case 72: //Вверх
WShape->move(UP, 10);
break;
case 80: //Вниз
WShape->move(DOWN, 10);
break;
}
WShape->draw();
}
}
#include "circle.h"
#include "triangle.h"
void main()
{
Shape *myShape[2] = {
new Circle(300,100,50, RGB(100,0,200)),
new Triangle(150,100,100,200,200,200, RGB(200,40,10))
};
Shape *WShape = myShape[0];
myShape[0]->draw();
myShape[1]->draw();
while(1)
{
int c;
//int x = 0;
c = getch();
//c = getch();
switch(c)
{
case 49: //1
//x = 0;
WShape = myShape[0];
break;
case 50: //2
//x = 1;
WShape = myShape[1];
break;
case 75: //Влево
WShape->move(LEFT, 10);
break;
case 77: //Вправо
WShape->move(RIGHT, 10);
break;
case 72: //Вверх
WShape->move(UP, 10);
break;
case 80: //Вниз
WShape->move(DOWN, 10);
break;
}
WShape->draw();
}
}
Программа работает, при нажатии на клавиши 1 и 2 происходит переключение между кругом и треугольником, после чего можно перемещать по окну.
Вот некоторые появившиеся вопросы:
1) Не найдя никакой функции для очистки экрана, я попробовал использовать InvalidateRect(hwnd, NULL, 1);, и на удивление заработало. Что делает эта функция?
2) Как сделать так, чтобы при переключении на другую фигуру первая не исчезала, а оставалась?
3) Как запретить перемещение фигуры за границы окна?
4) Я пробовал реализовать изменение цвета при нажатии на клавишу +, сделал функцию изменения цвета, которая получает 3 переменные int, но не знаю как изменить данные в типе COLORREF.
5) В одном примере я видел следующий код:
Код:
case ID_CIRCLE:
if (DialogBox(hInst, (LPCTSTR)IDD_NEWCIRCLE, hWnd, (DLGPROC)NewCircle) == IDOK)
{...создание и прорисовка круга...}
if (DialogBox(hInst, (LPCTSTR)IDD_NEWCIRCLE, hWnd, (DLGPROC)NewCircle) == IDOK)
{...создание и прорисовка круга...}
Как работает данная конструкция?
6) Почему функция TextOut выводит после нужной надписи множество символов "Ъ"?
7) Можно ли создать надпись с информацией о площади фигуры без использования преобразования числа в строку и функции TextOut?
8) На лекции в примере нажатие клавиш получали 2 функции getch() подряд, потому что здесь специальная обработка какая-то, но оно работает и с одной функцией, нужна ли 2 функция?
1) Читай msdn
2) в driver.cpp ты вызываешь WShape->draw(); т.е. прорисовку только одного объекта! вызови прорисовку второго и будет тебе счастье ;)
3) mfc не помню, но границы окна точно можно узнать без проблем ;) так что msdn
4) на сколько я помню - colorref это всего-то 4х байтное число... так что чтобы получить значение делаешь (r << 16) | (g << 8) | b
5) И снова тебе путь в msdn
6) а ты какие параметры передаешь ей? TextOut(hdc,200,1,str,20)... последний параметр это случайно не длина строки?
7) в mfc - нет
8) не нужна
3)тут я даже не знаю что писать для поиска, поэтому пока просто не буду вылазить за пределы
5) Я в этой строчке каждый параметр не понял, так что от мсдн никакой помощи
6) Последний параметр это длина строки, но если небольшое число, то обрезает, а если много то заполняет лишними символами