WINDOWS动态链接库.docx
- 文档编号:8954483
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:22
- 大小:20.38KB
WINDOWS动态链接库.docx
《WINDOWS动态链接库.docx》由会员分享,可在线阅读,更多相关《WINDOWS动态链接库.docx(22页珍藏版)》请在冰点文库上搜索。
WINDOWS动态链接库
WINDOWS动态链接库
第一代window程序员使用windowsapi进行编程,到了后来,微软推出MFC类库,于是,动态链接库进行了升级,可以在动态连接库中使用MFC的API,这就叫做MFC动态链接库,
其中MFC动态链接库又分为两种,MFC规则动态链接库和MFC扩展动态链接库,两者有些不同,一般来说规则动态链接库封装一些函数,方法和自己对MFC方法的封装,而扩展动态链接库
主要用于扩展MFC的控件,比如MFC的CLIST功能单一,就可以扩展成功能强大的表格,甚至可以扩展到像excel的功能.
今天说说MFC规则动态链接库,在VS中选择新建一个MFCDLL项目,就可以选择建立规则DLL还是扩展DLL,规则DLL没有WIN32动态链接库所有的DllMain函数,但是它包含有一个从
CWinApp继承下来的类,theapp在DLL初始化的时候自动调用DllMain,也就是说,类似于MFC编程WinMain函数被封装起来一样,MFC规则动态链接库封装了DllMain.
在调用规则动态链接库的时候,需要注意两个方面,第一是:
静态链接的时候,不需要DLL进行模块状态的切换,第二是动态链接的时候,一定不能忘了切换模块.windows程序都有着自己的资源
ID,程序启动的时候,默认系统使用的是主线程的资源ID,程序调用的工具栏,菜单,等等资源,都与这个资源ID相关联,或者叫做资源模板.但是当DLL和调用程序都有着自己的资源模板的时候,主线程
调用DLL显示或者使用某个资源的时候,如果没有切换资源ID,DLL会使用主线程的资源,而不是使用DLL本身的资源,这样就会造成程序的混乱,所以,记住一点,在MFC规则动态链接库中,任何函数的第一行加上
AFX_MANAGE_STATE(AfxGetStaticModuleState());
该函数类似于单片机的中断压栈指令,他会将原先的资源模板替换成现在正在使用的实例本身的资源模板,当程序退出这个实例的时候,又会因为析构函数的作用自动恢复原先的资源模板,极为方便.
MFC规则DLL并非MFC应用程序,他所包含的CWinApp类并不包含消息循环,因为规则DLL不包括MFC的CWinApp:
:
Run()机制,主消息泵依然由应用程序拥有,如果DLL生成非模态对话框,或者自己
的主窗口框架,则应用程序的主消息泵必须调用从DLL导出来的函数来调用CWinApp的PreTranslateMessage()函数,将消息传送到DLL中
虽然没有DLLMain函数,但是MFC规则DLL包含另一个用于初始化DLL环境的函数InitInstance(),该函数在DLL项目的主APP入口类文件中,原型如下1//唯一的一个CDinkMfcRegularDllApp对象
2
3CDinkMfcRegularDllApptheApp;
4
5
6//CDinkMfcRegularDllApp初始化
7
8BOOLCDinkMfcRegularDllApp:
:
InitInstance()
9{
10CWinApp:
:
InitInstance();
11
12//初始化函数放在这里
13dllMessage.Empty();
14dllMessage.Append(TEXT("hellomfcregulardll"));
15
16returnTRUE;
17}
和win32dll一样,规则DLL也可以导出所需的类和函数以及变量,不过有了更方便的方法,MFC定义了三个宏,帮助我们快速导出,分别是
AFX_EXT_APIAFX_EXT_DATAAFX_EXT_CLASS分别用于导出函数,变量和类,实际上对应的是这三个条件宏,如下
#ifndefAFX_EXT_DATA
#ifdef_AFXEXT
#defineAFX_EXT_CLASSAFX_CLASS_EXPORT
#defineAFX_EXT_APIAFX_API_EXPORT
#defineAFX_EXT_DATAAFX_DATA_EXPORT
#defineAFX_EXT_DATADEF
#else
#defineAFX_EXT_CLASSAFX_CLASS_IMPORT
#defineAFX_EXT_APIAFX_API_IMPORT
#defineAFX_EXT_DATAAFX_DATA_IMPORT
#defineAFX_EXT_DATADEF
#endif
#endif
#ifndefAFX_DATA_EXPORT
#defineAFX_DATA_EXPORT__declspec(dllexport)
#endif
#ifndefAFX_DATA_IMPORT
#defineAFX_DATA_IMPORT__declspec(dllimport)
#endif
#ifndefAFX_CLASS_EXPORT
#defineAFX_CLASS_EXPORT__declspec(dllexport)
#endif
#ifndefAFX_CLASS_IMPORT
#defineAFX_CLASS_IMPORT__declspec(dllimport)
#endif
//forglobalAPIs
#ifndefAFX_API_EXPORT
#defineAFX_API_EXPORT__declspec(dllexport)
#endif
#ifndefAFX_API_IMPORT
#defineAFX_API_IMPORT__declspec(dllimport)
#endif
我们只需要在项目->属性->VC++->预处理中定义_AFXEXT这个宏就可以了.
下面是一个实际的代码演示,首先是头文件
#pragmaonce
#include"stdafx.h"
//动态链接库版本
#defineDINK_MFC_REGULAR_DLL_VERSION0.01
#defineDINK_MFC_REGULAR_DLL_NAME"DinkMfcRegularDll.dll"
#defineDINK_MFC_REGULAR_LIB_NAME"DinkMfcRegularDll.lib"
//变量
EXTERN_CCStringAFX_EXT_DATAdllMessage;
//动态导出变量,需要三个东西,一个是导出函数的load时候的字符串
//第二个转换空指针到数据指针和实际数据的两个宏定义
#defineDINK_REGULAR_DLL_VAR_DLLMESSAGE"dllMessage"
#defineMAKE_REGULAR_DLL_DLLMESSAGE_PTR(ptr)((CString*)ptr)
#defineMAKE_REGULAR_DLL_DLLMESSAGE_VALUE(ptr)(*((CString*)ptr))
//全局方法
EXTERN_CvoidAFX_EXT_APIPathAppendName(CStringpath,CStringname,CString&dst);
typedefvoid(*DINK_REGULAR_FUNC_PATHAPPENDNAME)(CStringpath,CStringname,CString&dst);
#defineDINK_REGULAR_DLL_NAME_FUNC_PATHAPPENDNAME"PathAppendName"
EXTERN_CUINTAFX_EXT_APIShowConfirmDialog(CString&showString);//存放所有需要导出的MFC规则DLL的函数,变量,类的头文件
//类不能动态导出,所以相对比较好一点
//个人文件处理函数
classAFX_EXT_CLASSCDinkFileLogic
{
public:
//检测指定文件是否存在
BOOLFileIsExist(CStringfilePath,CStringfileName);
//读取指定文件的第一行文本
BOOLFileReadFirstLine(CStringfilePath,CStringfileName,CString&readStr);
//删除指定文件
BOOLFileRemove(CStringfilePath,CStringfileName);
//创建指定文件force表示文件要是已经存在,是否删除并覆盖,为真,删除覆盖
BOOLFileCreate(CStringfilePath,CStringfileName,BOOLforce);
//创建文件,并添加事件后缀,withTime表示是否添加时间,为false,则创建文件仅仅包含日期
BOOLFileCreateByTime(CStringfilePath,CStringfileName,BOOLforce,BOOLwithTime);
//文件写入一行,isCreate表示当文件不存在是否主动创建
BOOLFileWriteLine(CStringfilePath,CStringfileName,CString&writeStr,BOOLisCreate);
//文件移动,moveOrCopy为真,为剪切操作为假,是拷贝操作,如果目标文件已经存在,返回失败
BOOLFileMove(CStringSourceFilePath,CStringSourceFileName,CStringdstFilePath,CStringdstFileName,BOOLmoveOrCopy);
//文件移动,moveOrCopy为真,为剪切操作为假,是拷贝操作,如果目标文件已经存在,默认覆盖该文件
BOOLFileMoveForce(CStringSourceFilePath,CStringSourceFileName,CStringdstFilePath,CStringdstFileName,BOOLmoveOrCopy);
protected:
private:
BOOLFileIsExist(CStringfileFullPath);
};
//个人目录处理函数
classAFX_EXT_CLASSCDinkDirLogic
{
public:
//检测指定目录是否存在
BOOLDirIsExist(CStringdirPath);
//创建指定目录,如果目录已经存在,返回OK
BOOLDirCreate(CStringdirPath);
//创建指定目录,目录名带时间,withTime为真,带时分秒为假,仅仅年月日
BOOLDirCreateByTime(CStringdirPath,BOOLwithTime);
//移除指定目录,只有在目录为空的时候才能执行
BOOLDirRemoveByEmpty(CStringdirPath);
//移除指定目录,不管目录是否为空
BOOLDirRemoveNoEmpty(CStringdirPath);
//检测目标文件夹是否还含有子文件,返回子文件个数
UINTIsDirContainFile(CStringdirPath);
//获取指定文件夹的子文件夹名和子文件夹个数
UINTDirListOfDir(CStringdirPath,CArray<CString>&dirArray);
//获取指定文件夹的子文件名列表和子文件个数
UINTFileListOfDir(CStringdirPath,CArray<CString>&fileNameArray);
//移动指定目录,withFile表示是带文件的移动还是仅仅移动目录
//不会删除源文件夹
UINTDirMove(CStringsourceDirPath,CStringdstDirPath,BOOLwithFile);
protected:
private:
};
然后是与之对应的方法文件,数据文件和类文件,我习惯把三个文件分开,比较好维护,如下
#include"stdafx.h"
#include"DinkMfcRegularDllExtend.h"
BOOLCDinkFileLogic:
:
FileIsExist(CStringfilePath,CStringfileName)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//检测文件是否存在
CStdioFiletest;
CStringfileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(test.Open(fileFullPath,CFile:
:
modeRead))
{
//可以打开
test.Close();
returnTRUE;
}
else
{
returnFALSE;
}
}
BOOLCDinkFileLogic:
:
FileIsExist(CStringfileFullPath)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFiletest;
if(test.Open(fileFullPath,CFile:
:
modeRead))
{
//可以打开
test.Close();
returnTRUE;
}
else
{
returnFALSE;
}
}
BOOLCDinkFileLogic:
:
FileReadFirstLine(CStringfilePath,CStringfileName,CString&readStr)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//读取制定文件第一行
CStdioFiletest;
CStringfileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(test.Open(fileFullPath,CStdioFile:
:
modeRead))
{
//打开了
readStr.Empty();
test.ReadString(readStr);
test.Close();
returnTRUE;
}
else
{
//文件打不开
returnFALSE;
}
}
BOOLCDinkFileLogic:
:
FileRemove(CStringfilePath,CStringfileName)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFiletest;
CStringfileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
CFile:
:
Remove(fileFullPath);
returnTRUE;
}
BOOLCDinkFileLogic:
:
FileCreate(CStringfilePath,CStringfileName,BOOLforce)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFiletest;
CStringfileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(force==TRUE)
{
//强制创建,如果存在,清除源文件内容
if(test.Open(fileFullPath,CStdioFile:
:
modeRead|CFile:
:
modeCreate))
{
test.Close();
//已经存在文件
CFile:
:
Remove(fileFullPath);
returnTRUE;
}
else
{
//创建失败
returnFALSE;
}
}
else
{
if(test.Open(fileFullPath,CFile:
:
modeCreate|CFile:
:
modeRead|CFile:
:
modeNoTruncate))
{
test.Close();
returnTRUE;
}
else
{
returnFALSE;
}
}
}
BOOLCDinkFileLogic:
:
FileCreateByTime(CStringfilePath,CStringfileName,BOOLforce,BOOLwithTime)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStringtimeStr;
CTimetime;
time=time.GetCurrentTime();
if(withTime==TRUE)
{
timeStr.Append(time.Format(TEXT("%Y-%m-%d-%H-%M-%S-")));
}
else
{
timeStr.Append(time.Format(TEXT("%Y-%m-%d-")));
}
CStringfileFullName(TEXT(""));
fileFullName.Append(filePath);
fileFullName.Append(TEXT("\\"));
fileFullName.Append(timeStr);
fileFullName.Append(fileName);
CFilefileCreate;
if(force==TRUE)
{
if(fileCreate.Open(fileFullName,CFile:
:
modeRead|CFile:
:
modeCreate))
{
fileCreate.Close();
returnTRUE;
}
else
{
returnFALSE;
}
}
else
{
if(fileCreate.Open(fileFullName,CFile:
:
modeRead|CFile:
:
modeNoTruncate|CFile:
:
modeCreate))
{
fileCreate.Close();
returnTRUE;
}
else
{
returnFALSE;
}
}
}
BOOLCDinkFileLogic:
:
FileWriteLine(CStringfilePath,CStringfileName,CString&writeStr,BOOLisCreate)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStringfullName;
PathAppendName(filePath,fileName,fullName);
CStdioFiledinkFile;
if(TRUE==isCreate)
{
//创建文件,如果文件已经存在就清空
if(dinkFile.Open(fullName,CFile:
:
modeCreate|CFile:
:
modeReadWrite))
{
dinkFile.SeekToEnd();
dinkFile.WriteString(writeStr);
dinkFile.Flush();
dinkFile.Close();
returnTRUE;
}
else
{
//打开文件失败
returnFALSE;
}
}
else
{
//如果文件已经存在就打开而且不清空,不存在就创建
if(TRUE==dinkFile.Open(fullName,CStdioFile:
:
modeReadWrite|CFile:
:
modeCreate|CFile:
:
modeNoTruncate))
{
dinkFile.SeekToEnd();
dinkFile.WriteString(writeStr+TEXT("\n"));
dinkFile.Flush();
dinkFile.Close();
returnTRUE;
}
else
{
//打开文件失败
returnFALSE;
}
}
}
BOOLCDinkFileLogic:
:
FileMove(CStringSourceFilePath,CStringSourceFileName,CStringdstFilePath,CStringdstFileName,BOOLmoveOrCopy)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//文件移动
returnFALSE;
}
BOOLCDinkFileLogic:
:
FileMoveForce(CStringSourceFilePath,CStringSourceFileName,CStringdstFilePath,CStringdstFileName,BOOLmoveOrCopy)
{
AFX_MANAGE_STATE(AfxGetModuleState());
returnFALSE;
}
#include"stdafx.h"
#include"DinkMfcRegularDllExtend.h"
#include"DinkConfirmResultDialog.h"
voidPathAppendName(CStringpath,CStringname,CString&dst)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
dst.Empty();
if(path.IsEmpty())
{
dst.Append(TEXT(".\\"));
dst.Append(name);
}
else
{
dst.Append(path);
dst.Append(TEXT("\\"));
dst.Append(name);
}
}
EXTERN_CUINTAFX_EXT_APIShowConfirmDialo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- WINDOWS 动态 链接