📄 c13_5f.cpp
字号:
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "C13_5f.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ExitClick(TObject *Sender)
{
Form1->Close(); // 关闭主窗体
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
UserAction = IC_ARROW;
Drawing = false;
Linker = new UnitLink;
PaintBox1->Canvas->Brush->Style = bsSolid;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ArrowClick(TObject *Sender)
{ // 用户选择“箭头”按钮
UserAction = IC_ARROW;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LineClick(TObject *Sender)
{
UserAction = IC_LINE; // 用户选择画直线
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RectClick(TObject *Sender)
{
UserAction = IC_RECTANGLE; // 用户选择画矩形
}
//---------------------------------------------------------------------------
// 定义直线类成员函数
bool UnitLine::IsMe(long x, long y)
{
if((x-X1)*(x-X2)<0 && (y-Y1)*(y-Y2)<0)
{ // 点在直线所在矩形内
if(X1==X2)
{ // X1==X2 时为垂直(Y轴的)线,
// 由于垂直线无斜率,必须单独处理
if(abs(x-X1)<DISTENCE)
return(true);
}
else
{ // 非垂直线,计算点到直线的距离
float k = (Y2-Y1)/(float)(X2-X1); // 计算斜率。由于坐标点为整数,
// 必须首先转换为浮点数。
// 否则,计算结果将取整
float A = (y-Y2)-(x-X2)*k;
float d = A*A/(1+k*k); // d 为距离的平方。
if(d < DISTENCE*DISTENCE)
return(true);
}
}
return(false);
}
void UnitLine::Draw(TCanvas *Canvas)
{
Canvas->MoveTo(X1, Y1); // 画直线
Canvas->LineTo(X2, Y2);
}
//---------------------------------------------------------------------------
// 定义矩形类成员函数
bool UnitRect::IsMe(long x, long y)
{
if(((x-X1)*(x-X2)<0 &&(abs(y-Y1)<DISTENCE || abs(y-Y2)<DISTENCE)) ||
((y-Y1)*(y-Y2)<0 && (abs(x-X1)<DISTENCE || abs(x-X2)<DISTENCE)))
{ // 判断输入点在矩形上
return(true);
}
return(false);
}
void UnitRect::Draw(TCanvas *Canvas)
{
Canvas->Rectangle(X1, Y1, X2, Y2); // 画矩形
}
//---------------------------------------------------------------------------
// 定义UnitLink对象成员函数
void UnitLink::AddItem(Unit *p)
{ // 在链表中增加成员
sUnit *p1 = new sUnit;
p1->p=p;
if(pHead)
{ // 如果链表非空
pHead->prev->next = p1; // 插入链表
p1->prev = pHead->prev;
p1->next = pHead;
pHead->prev = p1;
pHead = p1; // 修改链表头指针
}
else
{ // 链表空
pHead = p1;
pHead->next = p1;
pHead->prev = p1;
}
}
__fastcall UnitLink::~UnitLink()
{
if(!pHead)
return;
pHead->prev->next = NULL;
for(pHead = pHead->next ; pHead ; pHead = pHead->next)
{ // 遍历链表
delete pHead->prev; // 删除链表项。
// 系统将自动调用sUnit对象的析构函数
}
delete pHead; // 删除链表最后一项
}
//--------------------------------------------------------------------------
Unit* UnitLink::GetAt(int k)
{
sUnit* p = pHead;
int i;
if(k<1 && !pHead)
return(0);
for(i=0 ; i<k ; i++)
{ // 该循环从第一项开始遍历
p = p->prev;
}
return(p->p);
}
void UnitLink::Draw(TCanvas* Canvas)
{
sUnit* p = pHead;
int i;
if(!pHead)
return;
Canvas->Brush->Style = bsClear; // 设置刷
for(i = GetNum() ; i>0 ; i--)
{ // 从第一项开始遍历链表
p = p->prev; // 移动链表位置
p->p->Draw(Canvas); // 画对象
}
}
Unit* UnitLink::IsThis(long x, long y)
{
sUnit* p;
if(!pHead)
return(0);
for(p = pHead ; !p->p->IsMe(x, y) ; p = p->next)
{ // 从最后一项向前遍历链表,IsMe函数用于判断输入点是否在对象上。
if(p->next == pHead)
return(0);
}
return(p->p);
}
int UnitLink::GetNum()
{
sUnit* p = pHead;
int i;
if(!pHead)
return(0);
for(i=0 ; p->next != pHead ; i++)
// 该循环用于遍历链表
p = p->next;
return(i+1); // 返回链表项数
}
void UnitLink::DelItem(Unit* p1)
{
int i;
sUnit* p=pHead;
for(i=GetNum() ; i>0 ; i--)
{ // 该循环用于遍历链表
if(p->p == p1)
{ // 判断当前项
p->next->prev = p->prev; // 将p从链表中删除
p->prev->next = p->next; // 将p从链表中删除
if(p == pHead && p->next == pHead)
{ // p 是链表中的最后一项。
pHead = NULL;
delete p;
}
else if(p == pHead)
{ // p 是链表中的第一项。
pHead = p->next;
delete p;
}
else
{ // p 是链表中的普通项。
delete p;
}
return;
}
p = p->next;
}
}
//--------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
PaintBox1->Canvas->Pen->Mode = pmXor; // 设置异或线
PaintBox1->Canvas->Brush->Style = bsClear;
PaintBox1->Canvas->Pen->Color = BACKCOLOR;
CurrentX = X; // 鼠标当前点
CurrentY = Y;
switch(UserAction){
case IC_ARROW:
if(CurrentUnit = Linker->IsThis(X, Y))
{ // 判断鼠标是否指向图元
Drawing = true;
}
break;
case IC_LINE:
Drawing = true; // 开始拖动,该设置用于鼠标移动事件处理程序。
CurrentUnit = new UnitLine; // 创建新(线)对象
CurrentUnit->UpDate1(X, Y); // 设置对象数据成员
CurrentUnit->UpDate2(X, Y);
CurrentUnit->Draw(PaintBox1->Canvas); // 画对象
break;
case IC_RECTANGLE:
Drawing = true; // 开始拖动
CurrentUnit = new UnitRect; // 创建新(矩形)对象
CurrentUnit->UpDate1(X, Y);
CurrentUnit->UpDate2(X, Y);
CurrentUnit->Draw(PaintBox1->Canvas);
break;
default:
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
PaintBox1->Canvas->Pen->Mode = pmCopy; // 恢复设置
PaintBox1->Canvas->Pen->Color = FORECOLOR; // 前景色
if(Drawing)
{ // 开始拖动
switch(UserAction){
case IC_ARROW:
ClearDraw(); // 清屏
Linker->Draw(PaintBox1->Canvas); // 重画各图元
break;
case IC_LINE: // 处理直线图元
CurrentUnit->UpDate2(X, Y); // 修改位置
CurrentUnit->Draw(PaintBox1->Canvas); // 重画图元
Linker->AddItem(CurrentUnit); // 将新图元加入链表
break;
case IC_RECTANGLE: // 处理矩形图元
CurrentUnit->UpDate2(X, Y);
CurrentUnit->Draw(PaintBox1->Canvas);
Linker->AddItem(CurrentUnit);
break;
default: // 本程序中无其它项
break;
}
Drawing = false;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
if(Drawing)
switch(UserAction){
case IC_ARROW:
CurrentUnit->Draw(PaintBox1->Canvas); //清除图形
CurrentUnit->UpDate(X-CurrentX, Y-CurrentY); // 移动图元位置
CurrentUnit->Draw(PaintBox1->Canvas); // 重画图形
break;
case IC_LINE: // 由于使用了重载函数,
// 对于不同的图形对象(直线、矩形),
// 可以使用相同的语句(代码重用)。
case IC_RECTANGLE:
CurrentUnit->Draw(PaintBox1->Canvas); // 清除原图形
// 由于使用异或画法
// 重画即可清除原图形
CurrentUnit->UpDate2(X, Y); // 修改当前点
CurrentUnit->Draw(PaintBox1->Canvas); // 画新图形
break;
default:
break;
}
CurrentX = X; // 保存当前点位置
CurrentY = Y;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Linker; // 当程序退出(删除窗体)时,将删除 Linker 对象
// 当删除 Linker 时,C++ 自动调用析构函数
// (即:Linker::~Linker())
// ~Linker函数用于清除程序中申请的堆内存。
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClearDraw()
{
TBrushStyle RawFill = PaintBox1->Canvas->Brush->Style; // 保存原填充样式
PaintBox1->Canvas->Brush->Style = bsSolid;
PaintBox1->Canvas->FillRect(PaintBox1->Canvas->ClipRect);
PaintBox1->Canvas->Brush->Style = RawFill; // 恢复填充样式
}
//--------------------------------------------------------------------------
void __fastcall TForm1::DeleteClick(TObject *Sender)
{
ClearDraw(); // 清除绘图区
Linker->DelItem(CurrentUnit); // 删除当前图元
Linker->Draw(PaintBox1->Canvas); // 重画其它图元
CurrentUnit = Linker->GetAt(Linker->GetNum()); // 查找最后一个图元
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
ClearDraw();
Linker->Draw(PaintBox1->Canvas);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -