📄 grid.cpp
字号:
/*******************************************************************************
模 块: 网格.
功 能: 数据网格,能编辑,上下移动,并上下翻页.
程序员: 雷中南.
版 本: v1.1
时 间: 1999-05-18
*******************************************************************************/
#include <graphics.h>
#include <string.h>
#include "stdio.h"
#include "grid.h"
#include "fileio.h"
//求最小值的函数.
#ifdef __cplusplus
int min(int value1, int value2)
{
return ( (value1 < value2) ? value1 : value2);
}
#endif
/*============================================================================*/
//构造函数.
Grid::Grid(struct RECT R, int cols, int width[], char *title[])
:Object(R)
{
//循环变量.
int i;
//文件缓冲,用于保存临时数据.
DataFile = new FileIO();
//当前列.
Col = 0;
//总列数.
Cols = cols;
//列宽.
for(i=0; i<Cols; i++)
{
ColWidth[i] = width[i];
}
//一条记录的总长度.
DataLength = 0;
//当前行数据.
for(i=0; i<Cols; i++)
{
//给字符串数组分配内存.
Data[i] = new char[ColWidth[i]*2];
Title[i] = new char[ColWidth[i]*2];
strcpy(Title[i], title[i]);
DataLength = DataLength + ColWidth[i]*2;
}
//给文件读写缓冲分配内存.
Buffer = new char[DataLength + 1];
//只读标记.L_YES表示编辑模式.L_NO表示只读模式.
ReadOnlyFlag = L_NO;
//总行数.
Rows = 0;
//当前行.
Row = 0;
//页首行.
FirstRow = 0;
//头尾的高度.
HeadHeight = 20;
TailHeight = 20;
//可见行数.
VisibleRow = (Rect.Height - HeadHeight - TailHeight) / 20;
//行高度.
LineHeight = 20;
//设置允许刷新.
IsRefresh();
}
//析构函数.
Grid::~Grid()
{
int i;
delete DataFile;
delete Buffer;
for(i=0; i<Cols; i++)
{
delete []Data[i];
}
}
/*============================================================================*/
//全部重画.
void
Grid::Draw()
{
//如果不允许刷新则返回.
if(Refable == L_NO)
{
return;
}
int i=0, j=0, temp=0;
//按行画有数据列.
for(i=FirstRow; i<=min(Rows - 1, FirstRow + VisibleRow); i++)
{
ItemDraw(i);
}
//画无数据列.
for(j=min(Rows - 1, FirstRow + VisibleRow) + 1; j<FirstRow + VisibleRow; j++)
{
setcolor(7);
temp = 0;
for(i=0; i<Cols; i++)
{
temp = temp + ColWidth[i]*8 + 1;
//设定视口.
setviewport(0, 0, 639, 479, 1);
setviewport(Rect.Left + temp - ColWidth[i]*8 + 1,
Rect.Top + LineHeight + (j - FirstRow) * LineHeight +2,
Rect.Left + temp - 1,
Rect.Top + LineHeight + (j + 1 - FirstRow) * LineHeight - 1, 1);
//清除视口.
clearviewport();
}
}
}
//画网格.
void
Grid::InitDraw()
{
int i, sum;
setcolor(15);
//画大框.
rectangle(0, 0, Rect.Width, Rect.Height);
//画题头.
setviewport(0, 0, 639, 479, 1);
setviewport(Rect.Left, Rect.Top, Rect.Left + Rect.Width,
Rect.Top + HeadHeight, 1);
//设定题头的颜色和模式.
setfillstyle(SOLID_FILL, 8);
bar(0, 0, Rect.Width, HeadHeight);
rectangle(0, 0, Rect.Width, HeadHeight);
//写题头文字.
sum = 0;
han.Color = 7;
setcolor(7);//设置题头分割线的颜色.
for(i=0; i<Cols; i++)
{
//画列线.
han.Out(sum + 2, 2, Title[i]);
//累加列宽.
sum = sum + 8*ColWidth[i] + 1;
//画列线.
line(sum, 1, sum, TailHeight - 1);
}
//恢复视口.
setviewport(0, 0, 639, 479, 1);
setviewport(Rect.Left, Rect.Top, Rect.Left + Rect.Width,
Rect.Top + Rect.Height, 1);
//画尾.
setfillstyle(SOLID_FILL, 8);
bar(0, Rect.Height - TailHeight, Rect.Width, Rect.Height);
setcolor(15);
rectangle(0, Rect.Height - TailHeight, Rect.Width, Rect.Height);
setcolor(8);
sum=0;
for(i=0; i<=Cols; i++)
{
//累加列宽.
sum = sum + 8*ColWidth[i] + 1;
//画列线.
line(sum, HeadHeight + 1, sum, Rect.Height - TailHeight - 1);
}
}
//画一行数据.
void
Grid::ItemDraw(int ID)
{
//如果不允许刷新则返回.
if(Refable == L_NO)
{
return;
}
//如果此行在可视范围内的话.
if(ID >= FirstRow && ID < FirstRow + VisibleRow)
{
int i=0, temp=0;
//读取指定行.
Read(ID);
for(i=0; i<Cols; i++)
{
//累加获取列位置.
temp = temp + ColWidth[i]*8 + 1;
//设定视口.
setviewport(0, 0, 639, 479, 1);
setviewport(Rect.Left + temp - ColWidth[i]*8 + 1,
Rect.Top + LineHeight + (ID - FirstRow) * LineHeight +2,
Rect.Left + temp - 1,
Rect.Top + LineHeight + (ID + 1 - FirstRow) * LineHeight - 1, 1);
//清除视口.
clearviewport();
//输出字段.
han.Color = 15;
han.Out(0, 1, Data[i]);
}
}
}
//将对象画出来.
void
Grid::Show()
{
//如果object不具备可见属性则返回.
if(Visible==L_ERROR || Refable == L_NO) return;
//视口变化太多了,重定义视口是有必要.
setviewport(0,0,639,479,1);
setviewport(Rect.Left,Rect.Top,Rect.Left+Rect.Width,Rect.Top+Rect.Height,1);
clearviewport();
//画网格基础.
InitDraw();
//画对象.
Draw();
}
/*============================================================================*/
//往缓冲里写数据.
int
Grid::Write(long ID)
{
//临时字符串指针.
char *t = Buffer;
//将数据按列写入缓冲.
for(int i=0; i<Cols; i++)
{
strncpy(t, Data[i], ColWidth[i] * 2);
t += ColWidth[i] * 2;
}
//将数据写入文件.
return DataFile->Write(Buffer, ID * DataLength, DataLength);
}
//从缓冲读数据.
int
Grid::Read(long ID)
{
//从缓冲文件读数据.
if(DataFile->Read(Buffer, ID * DataLength, DataLength) == L_OK)
{
//产生临时字符串指针.
char *t = Buffer;
//将缓冲中的数据赋给字段.
for(int i=0; i<Cols; i++)
{
strncpy(Data[i], t, ColWidth[i] * 2);
t += ColWidth[i] * 2;
}
return L_OK;
}
else
{
return L_ERROR;
}
}
//插入一行.
void
Grid::InsertRow(char *data[])
{
//将数据赋给对应字段.
for(int i=0; i<Cols; i++)
{
strcpy(Data[i],data[i]);
}
//改变行号.
Row=Rows;
//行数加一.
Rows++;
//将数据保存到文件.
Write(Row);
//超出显示范围,滚动显示.
if(Rows > FirstRow + VisibleRow)
{
//翻页并重画.
FirstRow = FirstRow + VisibleRow - 1;
//如果行数大于总行数,当前行等于总行数.
if(FirstRow > Rows - 1)
{
FirstRow = Rows - 1;
}
Show();
}
else
{
//将插入行画出来.
ItemDraw(Row);
}
}
//删除一行.
void
Grid::Delete(int ID)
{
//要删除的前提条件是行数大于1.
if(Rows >= 1)
{
//如果只有一行.
if(Rows == 1)
{
//用空字符串覆盖所有字段.
for(int i=0; i<Cols; i++)
{
strcpy(Data[i],"");
}
//将空字段写入文件.
Write(Row);
}
//如果网格多于一条记录.
for(int i=ID; i<Rows; i++)
{
//将数据前移一行.
Read(i + 1);
Write(i);
}
//行数减一.
Rows--;
//重画
Draw();
}
}
//全部删除.
void
Grid::DeleteAll()
{
//行数为一.
Rows = 1;
//当前行为零.
Row = 0;
//页首行为0.
FirstRow = 0;
//写空数据行.
for(int i=0; i<Cols; i++)
{
strcpy(Data[i],"");
}
//写入数据文件.
Write(Row);
//显示.
Show();
}
//插入新行.
void
Grid::AddNew()
{
//将数据字段置为空.
for(int i=0; i<Cols; i++)
{
strcpy(Data[i],"");
}
//将数据写入文件.
Write(Rows);
//改变当前行.
Row = Rows;
//行数加一.
Rows++;
//如果在可视范围内.
if(Row - FirstRow < VisibleRow)
{
//画一行.
ItemDraw(Row);
}
else
{
//翻页并重画.
FirstRow = FirstRow + VisibleRow - 1;
//如果行数大于总行数,当前行等于总行数.
if(FirstRow > Rows - 1)
{
FirstRow = Rows - 1;
}
Draw();
}
}
//修改一行.
void
Grid::Update()
{
//将现有数据保存到文件.
Write(Row);
//重画修改行.
ItemDraw(Row);
}
//下一行.
void
Grid::MoveNext()
{
//如果小于总行数, 行数加一.
if(Row < Rows - 1)
{
Row++;
}
//如果超出可视范围.
if(Row-FirstRow >= VisibleRow)
{
//向下翻页.
FirstRow = FirstRow + VisibleRow - 1;
//如果行数大于总行数,当前行等于总行数.
if(FirstRow > Rows - 1)
{
FirstRow = Rows - 1;
}
//重画.
Draw();
}
}
//上一行.
void
Grid::MovePrev()
{
//如果当前行大于0,行数减一.
if(Row > 0)
{
Row--;
}
//如果行在页首,重画网格.
if(Row - FirstRow < 0)
{
FirstRow = Row;
Draw();
}
}
//上一页.
void
Grid::PageUp()
{
//如果当前行大于0,行数减一.
if(Row > 0)
{
Row = Row - VisibleRow + 1;
}
if(Row < 0)
{
Row = 0;
}
//如果行在页首,重画网格.
FirstRow = Row;
Draw();
}
//下一页.
void
Grid::PageDown()
{
//行数下翻一页.
Row = Row + VisibleRow - 1;
//如果大于总行数.
if(Row > Rows - 1)
{
//当前行为最末行.
Row = Rows - 1;
}
//如果总行数大于可见行数.
if(Rows >= VisibleRow)
{
FirstRow = Row - VisibleRow + 1;
}
else
{
FirstRow = 0;
}
//重画.
Draw();
}
/*============================================================================*/
//设置为不可刷新状态.
void
Grid::IsFreeze()
{
Refable = L_NO;
}
//设置为可刷新状态.
void
Grid::IsRefresh()
{
Refable = L_YES;
Show();
}
/*============================================================================*/
//编辑焦点.
void
Grid::DoIt()
{
unsigned int Event, i;
//行编辑.
for(;;)
{
Read(Row);
Line= new LineGrid(
CreateRect(Rect.Left, Rect.Top + HeadHeight + (Row - FirstRow) * LineHeight,
Rect.Width, LineHeight), Data, ColWidth, Cols, ReadOnlyFlag);
Line->Col = Col;
Line->Show();
Line->Run();
for(i=0; i<Cols; i++)
{
strcpy(Data[i], Line->Data[i]);
}
Line->Hide();
delete Line;
GetEvent(Event);
switch(Event)
{
case EV_NEXT:
MoveNext();
PutEvent(Event);
return;
case EV_PREV:
MovePrev();
PutEvent(Event);
return;
case KEY_PGUP:
PageUp();
PutEvent(Event);
return;
case KEY_PGDWN:
PageDown();
PutEvent(Event);
return;
default:
PutEvent(Event);
return;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -