MFC基于对话框,在对话框上插入图像控件,在图像控件上,画一个绿 {MOD}的矩形,按键盘上下左右键,矩形在图像控件上移动移动。分别创建一个文本文件和一个二进制文件,对话框退出时,文档内写入保存退出前的矩形的位置的数据。退出对话框后,再次打开对话框通过读取文本文件或二进制文件的数据,矩形应该显示在上次退出之前的位置。
1.新建一个MFC基于对话框的工程,在对话框上插入图像控件。然后在图像控件上绘制一个绿 {MOD}的矩形。绘制矩形代码如下:
(1)dlg类添加成员变量 CRect类型的变量 m_rect此变量用来保存矩形的四个坐标点。在dlg类的构造函数中给矩形赋初值。
CfileoperatorDlg::CfileoperatorDlg(CWnd* pParent /*=NULL*/)
: CDialog(CfileoperatorDlg::IDD, pParent)
, m_string(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_rect.left=10;
m_rect.top=10;
m_rect.right=80;
m_rect.bottom=60;
}
(2)OnPaint()函数中来话矩形,代码如下
void CfileoperatorDlg::OnPaint()
{......
else
{
CDialog::OnPaint();
}
CDC * hDC =GetDlgItem(IDC_SHOW)->GetDC(); //得到图像控件相关的DC指针
hDC ->FillSolidRect(& m_rect,RGB(0,255,0)); //用DC类中的FillSoliRect函数画矩形。
return ture;
2.捕获键盘上的上下左右键并移动矩形(注意:矩形只能在图形控件上移动)
(1)重写dlg类的PreTranslateMessage函数,来接收键盘上下左右键消息,并对消息做相应的处理。
在dlg类中添加crect 类型的成员变量 m_rectctr,用来保存图像控件矩形的坐标点。代码如下:
BOOL CfileoperatorDlg::PreTranslateMessage(MSG* pMsg)
{
(GetDlgItem(IDC_SHOW))->GetClientRect(&m_rectctr); //得到对话框图像控件的窗口,然后通过GetClientRect将图像控件的坐标点
设置为原点
if(pMsg->message == WM_KEYDOWN) //接收的消息等于键盘按下的消息
{
switch(pMsg->wParam)
{
case VK_UP:
m_rect.top= m_rect.top-10; //按下上键,矩形向上移动10个位置,即上下坐标都要减10,左右下键如同
m_rect.bottom= m_rect.bottom-10;
if( m_rect.top<0) //矩形只能在图像控件上移动,如果当其顶点坐标小于0,就要将其设置为0,左右下如同
{
m_rect.top=0;
m_rect.bottom=50;
}
break;
case VK_DOWN:
m_rect.top= m_rect.top+10;
m_rect.bottom= m_rect.bottom+10;
if( m_rect.bottom>m_rectctr.bottom)
{
m_rect.top=m_rectctr.bottom-50;
m_rect.bottom=m_rectctr.bottom;
}
break;
case VK_LEFT:
m_rect.left=m_rect.left-10;
m_rect.right=m_rect.right-10;
if( m_rect.left{
m_rect.left=m_rectctr.left;
m_rect.right=m_rectctr.left+70;
}
break;
case VK_RIGHT:
m_rect.left=m_rect.left+10;
m_rect.right=m_rect.right+10;
if( m_rect.right>m_rectctr.right)
{
m_rect.right=m_rectctr.right;
m_rect.left=m_rectctr.right-70;
}
break;
}
Invalidate();
}
return CDialog::PreTranslateMessage(pMsg);
}
重写接收消息的函数,只是想针对我们想要的消息,上下左右键做特殊的处理。其他消息不改变,上面这个函数应该注意以下几点,(GetDlgItem(IDC_SHOW))->GetClientRect(&m_rectctr);这句话说明图像控件此时的坐标点m_rectctr.top,m_rectctr.left设置为0,在onpaint函数中,先得到图像控件的CDC指针,在用图像控件的指针画矩形,矩形的相对位置,是相对于图像控件的。在图像控件上上下左右移动矩形时,只要限定于矩形的四个坐标点在图像控件内,即与图像控件的坐标点比较即可。如上面加的向上移动,那么矩形顶点的坐标<0时,将顶点坐标设置为0,底部坐标-10,左右坐标值不变。左右键移动,如同。
3.创建button1按键,在button1里面添加创建文件文件,并写入当前矩形坐标点的数据,代码如下:
void CfileoperatorDlg::OnBnClickedButton1()
{
CFile file("D:/Rita/C point/C视频/78.txt",CFile::modeCreate|CFile::modeWrite)//在这个路径下创建一个文本文件,并写数据
//将矩形的四个坐标点写入到字串buf里面,四个坐标点的数据用空格隔开,方便后续读取数据,用stroke函数,将四个坐标点分离出来。
m_string.Format("%d %d %d %d", m_rect.left, m_rect.top,m_rect.bottom,m_rect.right);
file.Write(m_string,m_string.GetLength()); //将矩形的四个坐标点写入到文本文件中
}
4.添加一个按键button2用来读取文本文件的数据,代码如下
void CfileoperatorDlg::OnBnClickedButton2()
{ char *buf;
char* token;
int token_number = 0;
char * argv[32] = { 0 };
CFile file("D:/Rita/C point/C视频/78.txt",CFile::modeRead ); //读取数据
DWORD length=file.GetLength(); //得到文件的大小
buf=new char[length]; //创建文件大小的buf用来接收数据
file.Read(buf,length);
token = strtok(buf, " "); //通过这个函数经buf里面的数据分离出来
while (token != NULL)
{
argv[token_number] = token;
token_number++;
token = strtok(NULL, " "); //第二次调用时,将第一个参数设置为空,第二参数为上次调用返回的值
}
m_rect.left =atoi(argv[0]); // 分离出来的参数依次赋值给矩形的四个坐标
m_rect.top =atoi(argv[1]);
m_rect.bottom =atoi(argv[2]);
m_rect.right =atoi(argv[3]);
file.Close();
Invalidate(); //调用这个函数窗口重绘,重新绘制矩形
}
注意 strok函数的用法。上面只是对文本里面一行的数据进行读取,从code里面有个函数连续调用可以对多行数据进行读取。函数如下:
static int _GetLine(unsigned int fp, char * buf) //fp只的是文件句柄,buf指的是从文件中得到数据写入到此buf中
{
do
{
unsigned char ch;
if (fread(&ch, 1, 1, fp) == 0) //判断当前文件中是否有数据
{
return -1;
}
if ((ch == '
') || (ch == '
')) //当前读取文件中的数据是否为回车和换行
{
break;
}
*buf = ch; //将字符保存至buf中
buf++;
}
while(1);
do
{
unsigned char ch;
if (fread(&ch, 1, 1, fp) == 0)
{
break;
}
if ((ch == '
') || (ch == '
'))
{
/* do nothing */
}
else
{
seek(fp, -1, SEEK_CUR); // 将文件指针指向当前位置
break;
}
}
while(1);
*buf = '