在了解CWinApp的类之前先了解一下CWinApp的构造继承关系。
一般我们用VS新建的MFC应用程序中,主类CXXAPP类继承于 CWinApp.
例如:
//如下是我新建的MFC应用程序,主类是CApp类
class CApp : public CWinApp
{
public:
CApp();
// 重写
public:
virtual BOOL InitInstance();
// 实现
DECLARE_MESSAGE_MAP()
};
然后查看CWinApp类的定义,进入MFC内部源码,下面是我从源码中拷贝出来精简整理了一下的类:
//CWinApp类,直接从内部源码拷贝出,然后做了精简
//出于初学者的视角,会把部分成员删除,方便理解阅读
class CWinApp : public CWinThread
{
public:
// Constructor 构造函数
explicit CWinApp(LPCTSTR lpszAppName = NULL); // app name defaults to EXE name
// This module's hInstance. 资源管理实例
HINSTANCE m_hInstance;
// Pointer to the command-line. 执行程序时传入的参数
LPTSTR m_lpCmdLine;
//显示方式 具体可以查看HelpView
int m_nCmdShow;
//应用程序名称可能来自该参数传递给 CWinApp 构造函数
//或者,如果未指定,则为 AFX_IDS_APP_TITLEID的资源字符串。
//如果应用程序名称在资源中未找到,它来自程序的.EXE文件名。
LPCTSTR m_pszAppName;
/// <summary>
/// 应用程序用户模型ID. 目前不知道是啥
LPCTSTR m_pszAppID;
// Name of registry key for this application. See
// SetRegistryKey() member function.
LPCTSTR m_pszRegistryKey;
public:
// Executable name (no spaces). 可执行文件名
LPCTSTR m_pszExeName;
// Contains the name of the application's .INI file. 存储了配置文件的文件名
//下面提示源于MSDN,意思就是m_pszProfileName是用malloc申请的堆空间,CWinApp 的析构函数会释
//释放这个空间,如果你需要改变这个值的时候也要记得free这个空间,防止内存泄露。
//If you assign a value to m_pszProfileName, it must be dynamically allocated on the
//heap.
//The CWinApp destructor calls free( ) with this pointer.
//You many want to use the _tcsdup( ) run-time library function to do the allocating.
//Also, free the memory associated with the current pointer before assigning a new
//value. For example:
//free((void*)m_pszProfileName);
//m_pszProfileName = _tcsdup(_T("c:\\somedir\\myini.ini"));
//例子中,_tcsdup是一个复制函数,内部也是调用了malloc来申请空间的。
LPCTSTR m_pszProfileName;
// Returns TRUE is application is running under Windows 7 or higher
//判断当前系统版本是不是WIN7
BOOL IsWindows7();
protected:
// Load MRU file list and last preview state.
void LoadStdProfileSettings(UINT nMaxMRU = _AFX_MRU_COUNT);
// Set registry key name to be used by CWinApp's
// profile member functions; prevents writing to an INI file.
//使应用程序设置存储在注册表中,而不是INI文件中。
void SetRegistryKey(LPCTSTR lpszRegistryKey);
void SetRegistryKey(UINT nIDRegistryKey);
//为应用程序指定唯一的应用程序用户模型ID(AppUserModelID),此界面的方法将从其任务栏按钮
//的跳转列表中删除目标。此方法是可选的。
void SetAppID(LPCTSTR lpcszAppID);
//调用此成员函数可在Windows文件管理器中注册应用程序的所有文档类型。
void RegisterShellFileTypes(BOOL bCompat = FALSE);
//调用此成员函数可在Windows文件管理器中注销应用程序的所有文档类型。
void UnregisterShellFileTypes();
public:
// 执行RegisterShellFileTypes未处理的任何注册任务。
//具体查看MSDN中 CWinApp::Register 详细内容
virtual BOOL Register();
// 注销应用程序对象注册的所有文件。
virtual BOOL Unregister();
public:
// 加载光标 通过资源名
HCURSOR LoadCursor(LPCTSTR lpszResourceName) const;
//加载光标 通过资源ID
HCURSOR LoadCursor(UINT nIDResource) const;
//加载标准光标,意思就是系统自带的光标
//eg:IDC_ARROW箭头 IDC_WAIT转圈 IDC_CROSS 十字
//具体请查看MSDN中 CWinApp::LoadStandardCursor 详解
HCURSOR LoadStandardCursor(LPCTSTR lpszCursorName) const;
// 加载由nIDCursor指定的Windows预定义游标资源。
HCURSOR LoadOEMCursor(UINT nIDCursor) const;
// 加载图标资源 用资源名
HICON LoadIcon(LPCTSTR lpszResourceName) const;
// 加载图标资源 用资源ID
HICON LoadIcon(UINT nIDResource) const;
// 加载系统图标资源
//LoadStandardIcon函数原型其实是LoadIcon(NULL, lpIconName)
//具体请在MSDN中查看LoadIcon的详解
//系统自带资源包括:IDI_ERROR错误图标 IDI_HAND 手形图标等等
HICON LoadStandardIcon(LPCTSTR lpszIconName) const;
// 加载nIDIcon指定的Windows预定义图标资源。
//You must have #define OEMRESOURCE before #include <afxwin.h> to access the OIC_
// constants in WINDOWS.H.
HICON LoadOEMIcon(UINT nIDIcon) const;
// 从配置文件中读取int型数据
virtual UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault);
//在配置文件中写入int型数据
virtual BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue);
// 从配置文件中读取字符串
virtual CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL);
// 在配置文件中写入字符串
virtual BOOL WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue);
// 从配置文件中读取二进制数据
virtual BOOL GetProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPBYTE* ppData, UINT* pBytes);
// 在配置文件中设置一个二进制数据
virtual BOOL WriteProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPBYTE pData, UINT nBytes);
};
以下是上课笔记
1、CWinApp类的属性介绍:
a)WinMain参数保存:m_hInstance、m_lpCmdLine、m_nCmdShow;
2、程序(工程)名:LPCTSTR m_pszAppName ;
a)来源有三种:主要通过CWinApp的构造函数传递,其次通过字符串表AFX_IDS_APP_TITLE,如果以上都没有则通过执行文件名;
b)如果CWinApp的构造函数默认传递NULL指针,通过关键API获取本进程关联的执行文件名:GetModuleFileName
c)之后调用拆分路径的API:PathFindFileName把C:\\xxx\\yyy.exe 拆分成yyy
d)具体参考以下WinMain启动后的平台构建代码:
3、 m_pszExeName:执行文件名
4、程序配置相关:很多软件都有相关的.ini或者注册表数据管理
注册表和.ini的数据管理,主要的特点是提供给运维人员使用,如果CFile进行二进制保存,运维人员没法用;
LPCTSTR m_pszProfileName;// 配置文件:Default based on this application's name.
// SetRegistryKey() member function.
LPCTSTR m_pszRegistryKey; // 注册表名:Name of registry key for this application. See
【附录】:explicit:语法
1、通常对于单参数构造函数构造对象时,可以采用()和=两种;
比如:CWinApp a(_T("888") ;
或者:CWinApp a=_T("666");
2、如果构造函数前面加了explicit这个关键字,就会禁止使用以上的第二种构造方式;
更加明确是构造函数,否则他认为是赋值语句;
5、LPCTSTR m_pszProfileName;
a)配置文件ini的文件名,可以在程序中free之后再tcsdup一个新的文件名;
b)CWinApp::所有GetProfilexx和所有WriteProfilexx都通过GetPrivatexx代入 m_pszProfileName。
6、LPCTSTR m_pszRegistryKey;
a)注册表键值名:通过CWinApp::SetRegistryKey设置;
b)如果没有调用设置,m_pszRegistryKey默认是空指针。
空指针CWinApp::所有GetProfilexx都通过GetPrivatexx的API来读写ini文件。
7、光标和图标:
a)参见API:LoadCursor和LoadIcon;
b)CWinApp封装图标和光标加载的方法时,采用系统和资源图标两种函数;
c)窗口图标的调用可以调用:CWnd::SetIcon设置标题图标;
d)列表控件图标,一般要配合CImageList来使用,CXXX::SetImageList。
e)光标的设置不能像以上方法来设置,MFC提供了单独的设置光标的消息;
在WM_SETCUSOR消息中,要分别按照不同的窗口设置不同的光标;
HICON CWinApp::LoadIcon(UINT nIDResource) const
{ return ::LoadIconW(AfxFindResourceHandle(ATL_MAKEINTRESOURCE(nIDResource),
ATL_RT_GROUP_ICON), ATL_MAKEINTRESOURCEW(nIDResource)); }
HICON CWinApp::LoadStandardIcon(LPCTSTR lpszIconName) const
{ return ::LoadIcon(NULL, lpszIconName); }
HICON WINAPI LoadIcon( _In_opt_ HINSTANCE hInstance, _In_ LPCTSTR lpIconName);
如果hInstance参数代入NULL,加载系统图标(总共有4-5个,参见MessageBox的图标)