⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c13_6f.cpp

📁 C++Builder编程实例详解,用具体的例子阐明C++的一些基本操作,所有程序均在BC++上编译过.可靠,建议下载
💻 CPP
字号:
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "C13_6f.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; // 创建链表对象
    FileName = "Untiled.drw";
    Modify = false;
}
//---------------------------------------------------------------------------
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;
    }
    Form1->Modify = true;
}

__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;

    Form1->Modify = true; // 设置修改标志

    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::NewClick(TObject *Sender)
{
    delete Linker;
    Linker = new UnitLink;
    ClearDraw();
    FileName = "Untiled.drw";
    Modify = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenClick(TObject *Sender)
{
    if(Modify)
    { // 用户修改了图元数据
        switch(MessageBox(Form1->Handle, "是否保存修改?", "提示...",
                MB_YESNOCANCEL | MB_ICONQUESTION))
        {
            case ID_YES: // 选择保存文件
                SaveClick(Sender);
                break;
            case ID_CANCEL: // 取消操作
                return; // 放弃操作
        }
    }

    OpenDialog->Filter = "图形文件(*.drw)|*.drw";
    OpenDialog->Options << ofHideReadOnly;
    if(OpenDialog->Execute())
    {
        FileName = OpenDialog->FileName;
        TFileStream *fp = new TFileStream(FileName, fmOpenRead); // 打开文件
        delete Linker; // 清除原有数据
        Linker = new UnitLink; // 重建链表对象
        long i, j;
        while(fp->Read(&i, sizeof(long)))
        { // 读对象
          if(i == 1)
          { // 对象是直线
            UnitLine *p = new UnitLine;
            fp->Read(&j, sizeof(long));
            p->X1 = j;
            fp->Read(&j, sizeof(long));
            p->Y1 = j;
            fp->Read(&j, sizeof(long));
            p->X2 = j;
            fp->Read(&j, sizeof(long));
            p->Y2 = j;
            Linker->AddItem(p);
          }
          else
          { // 对象是矩形
            UnitRect *p = new UnitRect;
            fp->Read(&j, sizeof(long));
            p->X1 = j;
            fp->Read(&j, sizeof(long));
            p->Y1 = j;
            fp->Read(&j, sizeof(long));
            p->X2 = j;
            fp->Read(&j, sizeof(long));
            p->Y2 = j;
            Linker->AddItem(p);
          }
        }
        delete fp;
        ClearDraw(); // 清理画布
        Linker->Draw(PaintBox1->Canvas); // 画所有对象
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveClick(TObject *Sender)
{
    SaveDialog->Filter = "图形文件(*.drw)|*.drw"; // 设置类型选择列表
    SaveDialog->FileName = FileName; // 设置文件名
    SaveDialog->Options << ofHideReadOnly;
    if(SaveDialog->Execute())
    {
        FileName = SaveDialog->FileName;
        TFileStream *fp = new TFileStream(FileName, fmCreate);
        Modify = false;
        Unit *p;
        int i, j = Linker->GetNum();;
        for(i=0;i<j;i++)
        { // 写所有对象数据
            p = Linker->GetAt(i+1);
            fp->Write(&(p->type), sizeof(long));
            fp->Write(&(p->X1), sizeof(long));
            fp->Write(&(p->Y1), sizeof(long));
            fp->Write(&(p->X2), sizeof(long));
            fp->Write(&(p->Y2), sizeof(long));
        }
        delete fp; // 删除文件对象
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
    ClearDraw();
    Linker->Draw(PaintBox1->Canvas);	
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -