在 Win32 Application 中使用 MFC
- 格式:docx
- 大小:15.33 KB
- 文档页数:3
现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题。
这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题。
1.Win32 DLL在Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件。
然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息。
下面通过一个具体实例来学习如何在Win32 DLL中使用对话框,可以按照以下步骤来完成这个例子:1)在VC菜单中File->New新建一个命名为UseDlg的Win32 Dynamic-Link Library工程,下一步选择A simple DLL project。
2)在VC菜单中Insert->Resource添加一个ID为IDD_DLG_SHOW的Dialog资源,将此Dialog上的Cancel 按钮去掉,仅保留OK按钮。
再添加一个ID为IDD_ABOUTBOX的对话框,其Caption为About。
保存此资源,将资源文件命名为UseDlg.rc。
并将resource.h和UseDlg.rc加入到工程里面。
3)在UseDlg.app中包含resource.h,并添加如下代码:HINSTANCE hinst = NULL;HWND hwndDLG = NULL;BOOL CALLBACK DlgProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam);BOOL CALLBACK AboutProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam);extern "C" __declspec(dllexport) void ShowDlg();BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){switch(ul_reason_for_call){case DLL_PROCESS_ATTACH:hinst = (HINSTANCE)hModule;case DLL_PROCESS_DETACH:break;}return TRUE;}extern "C" __declspec(dllexport) void ShowDlg(){hwndDLG = CreateDialog(hinst,MAKEINTRESOURCE(IDD_DLG_SHOW), NULL,(DLGPROC)DlgProc);ShowWindow(hwndDLG, SW_SHOW);}BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){switch(message){case WM_INITDIALOG:return TRUE;case WM_COMMAND:if(LOWORD(wParam)==IDOK)DialogBox(hinst,MAKEINTRESOURCE(IDD_ABOUTBOX),hDlg,(DLGPROC)AboutProc);return TRUE;case WM_CLOSE:DestroyWindow(hDlg);hwndDLG = NULL;return TRUE;}return FALSE;}BOOL CALLBACK AboutProc(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam){switch(message){case WM_CLOSE:EndDialog(hDlg,NULL);hwndDLG = NULL;return TRUE;}return FALSE;}4)编译生成UseDlg.dll和UseDlg.lib。
MFC和Win32区别Visual C++设计软件有WIN32和MFC两中形式MFC ,Microsoft Foundation Classes.微软基础类库。
这个类库不光封装了大多数的GUI系统对象和数据结构,还为开发者提供了开发框架,使原本复杂繁琐的Windows开发(尤其使界面开发)变得非常简单。
MFC程序就是说,这个程序通过继承MFC的类实现的。
win32 是32位windows应用程序的统称。
从现在来看,MFC程序大都是win32的了,但在早期,MFC也能生成16位的应用程序。
WIN32 是Windows的一个子系统,也是最重要的一个。
(还有POSIX子系统和OS/2子系统)Win32子系统为应用程序提供了使用系统资源的接口Win32 API(Application Program Interface),WIN32 API是Windows用户态下应用程序编程的基础。
因此所有在WIN32API基础上的应用程序都是Win32应用程序。
MFC是对API的封装,因此它能实现的功能只是API的子集。
对于追求系统底层相关而且效率高的程序而言,MFC不够灵活而且开销也大。
但对于图形界面开发,如果没有MFC而使用API的话那么开发简直是对人的折磨。
MFC 很好用,但终归也是API的东西。
懂了系统原理和接口,MFC也就全明白了。
现在很少有直接用win32 API直接写GUI程序,除非程序很简单,要求程序很小的情况,,一般都用MFC,这样可以用相同的时间写出更漂亮和复杂的GUI 程序,使用封装好的类库会降低编程的灵活性,在一些开发中可能会束缚住手脚,VC中win32指的是windows 32位API,也就是32位windows提供的基础API,你建立的win32应用程序基于这些API,是完完全全的32位windows程序。
在VC中还分控制台和普通应用程序,主要是输出方式不同。
控制台下可能要使用cin这样的输入流对象,而非控制台程序可以使用图形API显示图形界面。
mfc使用手册MFC(Microsoft Foundation Class Library)是微软提供的一个类库,用于简化Windows应用程序的开发过程。
以下是MFC使用手册的简要介绍:1. 简介:MFC是一个基于C++的类库,它提供了许多用于构建Windows应用程序的类和函数。
通过使用MFC,开发人员可以快速地构建具有一致外观和感觉的应用程序,并利用Windows平台提供的各种功能。
2. 安装和配置:在开始使用MFC之前,您需要安装Microsoft Visual Studio并确保安装了MFC开发工作负载。
安装完成后,您需要创建一个新的MFC项目或打开一个现有的MFC项目。
3. 创建MFC应用程序:要创建一个新的MFC应用程序,您需要使用Microsoft Visual Studio的向导。
选择“File”菜单中的“New”选项,然后选择“Project”。
在弹出的对话框中,选择“MFC Application”并按照向导的提示完成应用程序的创建过程。
4. MFC类库:MFC提供了许多用于构建应用程序的类和函数。
以下是一些常用的MFC类:CWinApp:应用程序对象类,用于管理应用程序级别的操作,例如初始化应用程序和退出应用程序。
CWnd:窗口类,用于管理窗口的各种操作,例如创建窗口、处理消息和绘制窗口。
CDocument:文档类,用于管理应用程序中的文档数据。
CView:视图类,用于管理应用程序中的视图,例如显示文档数据和与用户交互。
5. MFC消息处理:MFC使用消息传递机制来处理用户与应用程序的交互。
每个窗口和控件都处理一组预定义的消息,例如鼠标点击、键盘输入和窗口大小改变等。
通过覆盖类中的虚函数,您可以定义应用程序如何响应这些消息。
6. MFC对话框和控件:MFC提供了许多内置的对话框和控件,例如按钮、文本框和列表框等。
您可以使用对话框编辑器来创建对话框,并将控件拖放到对话框中。
第一次实验基于VC++环境下的windows编程上机实验一、基于Win32应用程序实验实验内容:在Visual C++ 6.0中创建Win32 Application工程。
实验目的:(1)熟悉在Visual C++ 6.0中创建Win32 Application的过程。
(2)熟悉Visual C++6.0可以创建的3种Win32 Application。
(3)在Visual C++ 6.0种查看帮助文件。
实验步骤:(1)选择【开始】|【程序】|Microsoft Visual Studio 6.0|Microsoft Visual C++ 6.0命令启动Visual C++ 6.0,见图1-1.图1-1 启动Visual C++ 6.0(2)选择Visual C++ 6.0的菜单File|New命令打开New对话框,在这个对话框中选择Projects 选项卡,见图1-2.(3)在图1-2左侧的列表框中选中Win32 Application选项,在Project name编程框中填写工程名称(例如,MyPrj),在Lacation编辑框中选择存放工程文件的路径,其余使用默认选项,见图1-2.最后,单击OK按钮打开Win32 Application-Step 1 of 1对话框,见图1-3. (4)在图1-3所示的对话框中,有3种工程类型可以供选择:◆An empty project;◆ A simple Win32 application;◆ A typical “Hello World!” application。
选择An empty project选项,可以创建一个没有任何文件的空工程,用户需要自己向工程中添加所需要的文件。
图1-2 New对话框的Projects选项卡图1-3 Win32 Application-Step 1 of 1对话框选择A simple Win32 application选项,可以创建一个由系统自动生成必要代码的工程。
2. MFC和Win321. MFC Object和Windows Object的关系MFC中最重要的封装是对Win32 API的封装,因此,理解Windows Object和MFC Object (C++对象,一个C++类的实例)之间的关系是理解MFC的关键之一。
所谓Windows Object(Windows对象)是Win32下用句柄表示的Windows操作系统对象;所谓MFC Object (MFC对象)是C++对象,是一个C++类的实例,这里(本书范围内)MFC Object是有特定含义的,指封装Windows Object 的C++ Object,并非指任意的C++ Object。
MFC Object 和Windows Object是不一样的,但两者紧密联系。
以窗口对象为例:一个MFC窗口对象是一个C++ CWnd类(或派生类)的实例,是程序直接创建的。
在程序执行中它随着窗口类构造函数的调用而生成,随着析构函数的调用而消失。
而Windows窗口则是Windows系统的一个内部数据结构的实例,由一个“窗口句柄”标识,Windows系统创建它并给它分配系统资源。
Windows窗口在MFC窗口对象创建之后,由CWnd类的Create成员函数创建,“窗口句柄”保存在窗口对象的m_hWnd成员变量中。
Windows窗口可以被一个程序销毁,也可以被用户的动作销毁。
MFC窗口对象和Windows窗口对象的关系如图2-1所示。
其他的Windows Object和对应的MFC Object也有类似的关系。
下面,对MFC Object和Windows Object作一个比较。
有些论断对设备描述表(MFC类是CDC,句柄是HDC)可能不适用,但具体涉及到时会指出。
1. 从数据结构上比较MFC Object是相应C++类的实例,这些类是MFC或者程序员定义的;Windows Object是Windows系统的内部结构,通过一个句柄来引用;MFC给这些类定义了一个成员变量来保存MFC Object对应的Windows Object的句柄。
2010年9月14日16:58:44新建一个Win32控制台程序,使用MFC类库。
工程设置:点击菜单“Project” “Settings”,选择“General”标签,在“Microsoft Foundation Classes”组合框下,选择“Use MFC in a Shared DLL”。
以静态链接库的形式使用MFC类库。
源程序如下:#include<iostream.h>#include<afxwin.h>#include<afxtempl.h>int main(){CArray<CPoint,CPoint> m_array;//定义数组对象CPoint pt1(10,10);//定义对象并存放在数组中m_array.Add(pt1);CPoint pt2(20,20);m_array.Add(pt2);CPoint pt3(30,30);m_array.Add(pt3);int size=m_array.GetSize();//获取数组实际大小---元素个数CPoint pt;int index=0;for(index=0;index<size;index++){//输出数组元素pt=m_array.GetAt(index);cout<<pt.x<<" "<<pt.y<<endl;}return 0;}测试:输出成功。
2010年9月14日17:04:12下面是CArray的定义。
参考MSDN进行理解。
模板参数TYPE指出了存放在CArray中的对象的类型。
两个模板参数暂时认为应该一样。
// CArray<TYPE, ARG_TYPE>template<class TYPE, class ARG_TYPE>class CArray : public CObject{public:// ConstructionCArray();// Attributesint GetSize() const;int GetUpperBound() const;void SetSize(int nNewSize, int nGrowBy = -1);// Operations// Clean upvoid FreeExtra();void RemoveAll();// Accessing elementsTYPE GetAt(int nIndex) const;void SetAt(int nIndex, ARG_TYPE newElement);TYPE& ElementAt(int nIndex);// Direct Access to the element data (may return NULL)const TYPE* GetData() const;TYPE* GetData();// Potentially growing the arrayvoid SetAtGrow(int nIndex, ARG_TYPE newElement);int Add(ARG_TYPE newElement);int Append(const CArray& src);void Copy(const CArray& src);// overloaded operator helpersTYPE operator[](int nIndex) const;TYPE& operator[](int nIndex);// Operations that move elements aroundvoid InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);void RemoveAt(int nIndex, int nCount = 1);void InsertAt(int nStartIndex, CArray* pNewArray);// Implementationprotected:TYPE* m_pData; // the actual array of data//保存实际数组的指针int m_nSize; // # of elements (upperBound - 1)//数组的元素个数int m_nMaxSize; // max allocated//数组的容量大小int m_nGrowBy; // grow amountpublic:~CArray();void Serialize(CArchive&);#ifdef _DEBUGvoid Dump(CDumpContext&) const;void AssertValid() const;#endif};//构造函数的实现template<class TYPE, class ARG_TYPE>CArray<TYPE, ARG_TYPE>::CArray(){//数据成员初始化,空数组m_pData = NULL;m_nSize = m_nMaxSize = m_nGrowBy = 0;}typedef unsigned char BYTE;//1个字节//析构函数的实现template<class TYPE, class ARG_TYPE>CArray<TYPE, ARG_TYPE>::~CArray(){ASSERT_VALID(this);if (m_pData != NULL){DestructElements<TYPE>(m_pData, m_nSize);//释放元素---调用析构函数//数组容量未保存元素的部分不存在对象,所以不用调用析构函数,但要释放内存delete[] (BYTE*)m_pData;//释放内存}}#ifndef AFX_INLINE#define AFX_INLINE inline /*__forceinline*/#endif//返回数组的元素个数m_nSizetemplate<class TYPE, class ARG_TYPE>AFX_INLINE int CArray<TYPE, ARG_TYPE>::GetSize() const{ return m_nSize; }//返回数组的上限下标(元素个数-1)template<class TYPE, class ARG_TYPE>AFX_INLINE int CArray<TYPE, ARG_TYPE>::GetUpperBound() const{ return m_nSize-1; }//返回数组在指定下标的元素,应该是拷贝。
在Win32应用程序中使用MFC类库(转)转发评论2010-04-30 10:38由于MFC中的辅助类,如CFileDialog,CFileFind,CString等使用起来非常的方便如果用API来完成相应的工作,则需要自己完成大量的重复工作,使用MFC的辅助类可以节省大量的开发时间,具体方法如下: 1.加入相应的头文件由于在SDK程序中一定要包含windows.h头文件,所以在使用MFC中的类时,如加入afx.h一类的头文件会有一个提示与windows.h相冲突,解决的办法是,去掉windows.h,然后在所有的.h 文件前加入#include "stdafx.h"#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers#include <afxwin.h> // MFC core and standard components#include <afxext.h> // MFC extensions#include <afxdisp.h> // MFC Automation classes#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls#ifndef _AFX_NO_AFXCMN_SUPPORT#include <afxcmn.h> // MFC support for Windows Common Controls#endif // _AFX_NO_AFXCMN_SUPPORT注意一定要在所有的头文件之前加入这几行,而起顺序最好不要改变,否则会有大量的错误提示。
2.更改编译设置在Project->Setting->General中选Use MFC in a Shared DLL或者Use MFC in static Library,并把project->Setting->C/C++ 中的Use runing-time library 由Single-Threaded改为相应的Multithreaded。
一、窗口函数(Window)AdjustWindowRect函数功能:该函数依据所需客户矩形的大小,计算需要的窗日矩形的大小。
计算出的窗口矩形随后可以传递给CreateWindow函数,用于创建一个客户区所需大小的窗口。
函数原型:BOOLAdjustWindowRect(LPRECTlpRect,DWORDdwStyle,BOOLbMENU);参数:lpRect:指向 RECT 结构的指针,该结构包含所需客户区域的左上角和右下角的坐标。
函数返回时,该结构容纳所需客户区域的窗口的左上角和右下角的坐标。
dwStyle:指定将被计算尺寸的窗口的窗口风格。
bMenu:指示窗口是否有菜单。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。
获取错误信息,参看GetLastError。
备注:客户矩形是指完全包含一个客户区域的最小矩形;窗日矩形是指完全包含一个窗口的最小矩形,该窗口包含客户区与非客户区。
当一个菜单条下拉出两行或更多行时,AdjustWindowRect函数不增加额外的空间。
速查:WindowsNT:3.1以上版本:Windows:95以上版本:Windows CE:不支持;头文件:winuser.h;库文件:user32.lib。
AdjustWindowRectEX函数功能:该函数依据所需客户矩形大小,计算需要的窗口矩形的大小。
计算出的窗口矩形随后可以传送给CreateWindowEx函数,用于创建一个客户区所需大小的窗口。
函数原型:BOOLAdjustWindowRectEX(LPRECTlpRect,DWORDdwStyte;BOOLbMenu;DWORDdwExStyle);参数:lpRect:指向 RECT 结构的指针,该结构包含所需客户区域的左上角和右下角的坐标。
函数返回时,该结构包含容纳所需客户区域的窗口的左上角和右下角的坐标。
dwStyle:指定将被计算尺寸的窗口的窗口风格。
在 Win32 Application 中使用 MFC
在Virtual C++ 6.0创建的Win32 Application 和Win32 Console Application 中使用MFC 是可能的,主要的困难在于绕过MFC提供的WinMain函数。
下面我提供一个方法以供参考:
进入Project-->Setting--> C/C++ Page,做以下修改:
1.在Preprocessor definitions中加入_AFXDLL,加入后的设置大概是这样的:
WIN32,_DEBUG / NODEBUG,[_CONSOLE],[_MBCS],_AFXDLL
加入的_AFXDLL是关键,它欺骗MFC LIB,避免连接MFC 的WinMain 函数。
2.修改Project Options,将/MT或者/ML标志改为/MD。
原因是在afxver_.h 中会检查_AFXDL, _MT, _DLL 标志是否同时设置,否则报错。
尽管链接For Multi-Threaded 版本的Library 会损失一些性能,但是这个标志的存在并不导致编译器把Project 编译成DLL。
3.在Project的stdafx.h 中包含必要的头文件,或者直接从MFC AppWizard 创建的stdafx.h中拷贝:
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afx.h>
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT
4.在Project的WinMain / main中加入MFC的初始化代码,以下是
_tWinMain和_tmain的情况:
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
int nRetCode = 0;
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
TRACE0("Fatal Error: MFC initialization failed.\n");
nRetCode = 1;
}
else
{
// Actual WinMain codes ...
AfxWinTerm();
}
return nRetCode;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// Actual main codes ...
AfxWinTerm();
}
return nRetCode;
}
此外,在Virtual C++ 6.0创建的Win32 Dynamic-Link Library中也可以单独使用MFC,这样可以避免Project被MFC AppWizard和ATL COM
AppWizard添加CWinApp实例,方法简单,如下构造Project的DllMain函数即可:
#include <afxdllx.h>
static AFX_EXTENSION_MODULE ProjectDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved.
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization.
if (!AfxInitExtensionModule(ProjectDLL, hInstance))
{
TRACE0("Project.DLL initialize its extension module failed!\n");
return FALSE;
}
// CDynLinkLibrary’s destructor will be called in AfxTermExtensionModule.
new CDynLinkLibrary(ProjectDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("Project.DLL terminating...\n");
// Terminate the library before destructors are called.
AfxTermExtensionModule(ProjectDLL);
}
return TRUE; // ok.
}。