MFC基于对话框,在对话框上插入图像控件,在图像控件上,画一个绿 {MOD}的矩形,按键盘上下左右键,矩形在图

2019-04-15 14:55发布



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 = '