MFC文件操作Word文档格式.docx
《MFC文件操作Word文档格式.docx》由会员分享,可在线阅读,更多相关《MFC文件操作Word文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
![MFC文件操作Word文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/10/714b0fe7-90fb-434d-83a3-d04ed77b187b/714b0fe7-90fb-434d-83a3-d04ed77b187b1.gif)
只要启动客户操作记录软件后,不管输入焦点是否在本软件上,按键都会被记录下来。
我们需要的是键盘的系统监控,只要本软件在运行,无论当前计算机在做什么,都能监测到用户按键的行为并做出反应,这就要用到Hook技术。
Hook技术在很多特殊软件中广泛应用,如,金山词霸的“取词”功能,就用到了Hook计技术。
钩子的本质是一段用以处理系统消息的程序,通过系统调用,将其挂入系统。
钩子的种类很多,每种钩子可以截获并处理相应的消息,每当特定的消息发出,在到达目的窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。
此时在钩子函数中就可以对截获的消息进行加工处理,甚至可以强制结束消息的传递。
从钩子的本质来看,可以优先截获操作系统的各种消息进行处理,所以它几乎无所不能,因为windows的应用程序都是基于消息驱动的,应用程序的操作都依赖于它所得到的消息的类型及内容。
如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就补齐作用;
如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对系统进行监控。
根据需要,我们采用的是在DLL中实现Hook的方式。
(应用程序exe?
和DLL的区别所在)
文本文件存储管理
字符被计算机处理时都是以二进制代码的形式出现的,即一个字符对应一个8位二进制数,这种二进制码的集合就是所谓的ASCII码。
基本的ASCII码有128个,最高位都是0,对应的十进制数是0-127。
键盘上的字符,如英文字母、数字和一些常用符号,使用基本ASCII部分。
如数字“0”的ASCII码用二进制数表示就是00110000(即十进制数48)。
扩展的ASCII码有128个,最高位是1,对应的十进制数是128-255。
一些制表符和其他符号使用扩展的ASCII码部分。
为解决汉字的存储和显示问题,我国制定了国际GB2312。
据此规定,一个汉字由2个扩展的ASCII码组成,这种高位为1的双字节汉字编码就是汉字的机内码,简称为内码。
例如,汉字“学”的机内码用二进制数表示就是1101000110100111(即十进制数206和167),用十进制表示就是53671(206*256+167)。
对于字符,文本文件存储的是它的ASCII码,对于汉字,文本文件存储的是它的内码,即两位ASCII码,如字符串“0学0”,在文本文件中存储的内容是00110000110100011010011100110000
正确的文本文件读写过程
1.定义文件变量;
2.打开指定的文件;
3.向从文本文件中写入信息;
4.从文本文件中读取信息;
5.关闭文件
1、定义文件变量
定义文件变量格式:
CStdioFile文件变量;
例如,定义一个名称为f1的文件变量,语句如下:
CStdioFilef1;
2、打开指定文件
可以直接通过CStdioFile的构造函数来打开磁盘文件,同时可以用标志位指定打开方式(只读、只写、读写等):
CStdioFile(LPCTSTRlpszFileName,UINTnOpenFlags);
其中,lpszFileName表示要打开的文件名,可以是相对路径或绝对路径
nOpenFlags设置文件打开方式标志位,可以指定用“|”连接多个标志位。
下面是常用的打开标志:
CFile:
:
typeText:
以文本文件的形式打开文件
typeBinary:
以二进制文件的形式打开文件
modeCreate:
如果指定文件名的文件不存在,则新建文件;
如果文件存在并且没有设置CFile:
modeNoTruncate标志,则清空文件。
modeNoTruncate:
如果文件存在,不把它的长度删除为0(即不清空文件中的数据)。
modeRead:
以只读方式打开文件
modeReadWrite:
以可读可写方式打开文件
modeWrite:
以只写方式打开文件
shareDenyNone:
文件打开后,不禁止其他进程对文件的读写操作
shareExclusive:
文件打开后,禁止其他进程对文件的读写操作
shareDenyRead:
文件打开后,禁止其他进程对文件的读操作
shareDenyWrite:
文件打开后,禁止其他进程对文件的写操作
此外,可以不在构造函数中打开文件,而仅仅调用空的构造函数CStidoFile(),然后用CStdioFile:
Open()打开文件。
Open函数的前两个参数和非空构造函数的参数相同,其声明如下:
BOOLOpen(LPCTSTRlpszFileName,UINTnOpenFlags,CFileException*pError=NULL);
第3个参数与打开失败时的异常处理有关。
实例1:
以只读方式打开一个文件
步骤:
使用AppWizard创建一个对话框应用程序,删除其自动产生的所有控件,添加一个Button控件。
双击控件,在相应的函数里添加代码:
char*pszFileName="
C:
\\myfile.txt"
;
CStdioFilemyFile;
CFileExceptionfileException;
if(!
myFile.Open(pszFileName,CFile:
modeCreate|CFile:
typeText|CFile:
modeRead),&
fileException)
{
TRACE("
Can'
topenfile%s,error=%u\n"
pszFileName,fileException.m_cause);
}
运行结果:
如果C:
\下没有myfile.txt文件,则新生成该文件。
3.向从文本文件中写入信息
CStdioFile提供了函数WriteString来向文本文件中写入文本,WriteString函数的格式如下:
voidWriteString(LPCTSTRlpsz);
WriteString的参数lpsz是一个以”\0”字符结束的字符串,要把这个字符串的内容写入文件。
提示:
使用WriteString函数时,如果希望每执行一次WriteString,文本文件中的内容就会自动换行一次,那么就需要在需要换行的地方输出“\n”:
myFile.WriteString(“第1行\n”);
实例2:
向文件中写入文本
建立MFC基于对话框的程序,删除自动添加的所有控件,添加一个“确定”按钮,双击按钮,按默认添加事件函数,双击按钮,在相应的函数处添加如下代码:
char*pszFileName="
if(myFile.Open(pszFileName,CFile:
modeReadWrite),&
myFile.WriteString("
第1行\n"
);
CStringstrOrder;
strOrder.Format("
%d,%.3f"
66,88.88);
myFile.WriteString(strOrder);
else
topenfile%s,error=%u\n"
程序运行结果:
\myfile.txt文件中内容如下:
第1行
66,88.880
4.从文本文件中读取信息
CStidoFile提供了函数ReadString来读取文本,ReadString有两种形式,一种为:
virtualLPTSTRReadString(LPTSTRlpsz,UINITnMax);
ReadString函数的参数如下:
lpsz:
是用户提供的一个指向字符串的指针,它用来接受从文件读出的文本,以”\0”结束。
nMax是本次所允许读入的文本字符个数,不计“\0”字符,也就是说最多能读入nMax-1个文本字符。
ReadString的返回值是一个LPTSTR类型的指针,它指向从文件读出的文本字符串,如果到达文件尾,则返回NULL。
ReadString的另一种形式为:
BOOLReadString(CString&
rString);
参数rString用来容纳从文件读出的文本。
CString版本忽略回车换行符,返回值是一个布尔值。
如果返回值为FALSE,表示因到达文件尾而没有读到任何字符。
每执行一次ReadString,就会自动从文本文件中读取一行数据,同时文件操作指针会自动跳转到下一行。
实例3:
从文件中读取文本信息
创建基于对话框的MFC程序,删除所有自动添加的控件,添加按钮控件,为按钮添加事件,并在相应的函数处,添加如下代码:
myFile.SeekToBegin();
CStringstr1;
myFile.ReadString(str1);
CStringstr2;
myFile.ReadString(str2);
AfxMessageBox(str1+str2);
myFile.Close();
为程序F9设置断点,然后F5单步执行,
对文件的操作完成后,使用CloseFile关闭文件。
函数CStdioFile:
Close关闭一个文件,一般一个文件使用完毕就应该关闭它:
错误的文本文件读写过程
在读写文本文件的时候,最常见的错误是---操作文件不存在。
这种错误产生的典型原因有:
1.路径错误
\\Windows\\MyFile.txt"
//文件操作代码
由于将文件变量与一个绝对路径的文件名关联,而程序的数据通常存储在相对路径下,所以一旦相对路径和相对路径不一致时,就会出错。
举例而言,上一段程序本意是想从windows的安装目录下面的MyTextFile.txt文件中读取一行数据,但是如果操作系统安装的路径不是C:
\Windwos,而是C:
\Winnt,那么这段程序就会出错。
解决方法是在程序中使用相对路径,改正后的程序如下:
//获取windows路径
LPTSTRlpBuffer=newchar[MAX_PATH];
GetWindowsDirectory(lpBuffer,MAX_PATH);
strcat(lpBuffer,"
\\MyFile.txt"
if(myFile.Open(lpBuffer,CFile:
CStringstrFileTitle="
MyFile.txt"
if(myFile.Open(strFileTitle,CFile:
测试!
"
2.操作文件不存在
如果应用程序所有路径下面不存在MyFile.txt文件,那么在WriteString写入信息时就会出错。
解决办法就是在程序中打开文件前要检查是否存在此文件。
如下程序:
CFileFindfinder;
if(finder.FindFile(strFileTitle))
tfindfile%s\n"
strFileTitle);
3.超越文件权限进行读写操作
在打开文件的过程中,通过参数指定了文件的读写权限,如果读写的操作没有和相应的权限对应,就会出现错误。
下面的程序就是典型的忽略了文件操作权限的例子:
NoTruncate|CFile:
测试!
strFileTitle,fileException.m_cause);
支招儿:
1.准确定位文件的路径
操作文件的过程中,经常需要将文本文件放在程序自身的目录中,但是如果仅仅在程序中使用不指定任何路径信息的相对路径,如:
myFile.Open("
CFile:
modeReadWrite);
那么就有可能出现不能正确定位的情况,准确定位文件位置的方法是获得可执行程序自身的绝对路径,如:
TCHARFilePath[MAX_PATH];
GetModuleFileName(NULL,FilePath,MAX_PATH);
(_tcstchr(FilePath,'
\\'
))[1]=0;
lstrcat(FilePath,_T("
));
if(myFile.Open(FilePath,CFile:
FilePath,fileException.m_cause);
2.读文本文件指定的一行,并得到文本文件的总行数。
读文本文件指定的一行,并得到文本文件的总行数
要统计文本文件的总行数,可以从头逐行读,直到文件尾,程序:
if(myFile.Open("
modeNoTruncate|CFile:
CStringstrContent;
intorder=1;
while(myFile.ReadString(strContent))
if(2==order)
AfxMessageBox(strContent);
order=order+1;
topenfile"
实例演示文件操作过程客户操作记录实例
本软件分为两个部分,一部分是DLL模块,里面利用Hook技术完成键盘监控和写入文件的功能;
另一部分是界面部分,调用DLL启动和停止客户操作记录功能。
第1步:
创建MFCDLL项目
第2步:
创建TestHook.h文件
第3步:
加入全局共享数据变量
第4步:
保存DLL实例句柄
第5步:
类CKeyboradHook的成员函数
第6步:
创建钩子可执行程序
创建一个名为HookTest的project,project的类型为选择MFCAppWizard(DLL),DLL类型为MFCExtensionDLL(usingsharedMFCDLL)
注意:
选择File->
New菜单项,在弹出对话框的左边的列表框中选择MFCAppWizard(DLL).
在projectname文本框中输入项目名称,HookTest;
location中输入项目的存盘路径;
选中Createnewworkspace;
在platForms列表中选择Win32选项。
单击OK按钮继续下一步,在弹出的对话框中设置DLL类型为MFCExtensionDLL(usingsharedMFCDLL).
在IDE中,选择FileView选项卡,在其中就会发现其中有HookTest.cpp文件,却没有HookTest.h文件,这是因为visualC++6.0中没有现成的钩子类,所以要自己动手创建TestHook.h文件,在其中建立钩子类。
选择File菜单,再选择New菜单项,将弹出New对话框。
选择files选项卡,并且选择其中的C/C++HeaderFile.
选中addtoproject,并且在对应的下拉列表中选择项目名称HookTest;
在location文本框中输入项目的存盘路径,或单击右边的按钮选择相应的路径;
在file对应的文本框中输入文件名HookTest.h;
单击OK按钮,在IDE中自动打开Hooktest.h文件供编辑代码用;
TestHook.h文件:
#if_MSC_VER>
1000
#pragmaonce
#endif//_MSC_VER>
classAFX_EXT_CLASSCHookTest:
publicCObject
public:
CHookTest();
~CHookTest();
BOOLStartHook();
//StartHook()函数实现安装钩子
BOOLStopHook();
//StopHook()函数实现卸载钩子
};
HookTest.cpp文件中添加:
//存储各个键赌赢的字符
CStringcskey[TOTAL_KEYS]=
BACKSPACE"
TAB"
……
F12"
//存储各个键对应的键值
intnkey[TOTAL_KEYS]=
0X08,//"
0X09,//"
…….
0x7b,//"
#pragmadata_seg("
mydata"
)
//安装的键盘钩子子句柄
HHOOKglhTestHook=NULL;
//DLL实例句柄
HINSTANCEglhkInstance=NULL;
#pragmadata_seg()
DllMain函数中添加如下代码:
if(dwReason==DLL_PRO