扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
//========================================================================
//TITLE:
// 对《在C++类中实现Windows窗口的创建》一文的补充
//AUTHOR:
// norains
//DATE:
// Sunday 26-November-2006
//Passed Environment:
// WinCE4.2+EVC4.0
//========================================================================
《在C++类中实现Windows窗口的创建》(以下简称《创建》,文章地址:http://blog.csdn.net/norains/archive/2006/11/09/1376412.aspx)一文中提到,如果全局变量g_pDlg需要调用类的非public函数,需要借助于一个对于CallDlgProc()函数。正如在文中所说,这样会暴露一个无用的接口,虽然只有一个,但也有可能会造成使用者的迷惑。思考再三,其实可以采用定义一个静态的结构体,然后给该结构体的成员赋予地址实现CallDlgProc()的功能。
为方便对比,这里依然还是采用《创建》的代码。
首先我们需要定义一个结构,该结构的成员全是指针,并且指向的是CMainDlg类中的部分private或protected对象及其函数。
typedef struct _InternalMember
{
HINSTANCE *pm_hInst;
void (*pTempTestFuncion)();
}INTERNALMEMBER,*LPINTERNALMEMBER;
然后声明一个全局变量,并在构造函数中给其赋值.
INTERNALMEMBER g_internalMember; //声明全局变量
...
//构造函数
CMainDlg::CMainDlg(HINSTANCE hInst)
{
...
g_internalMember.pTempTestFunction = TempTestFnction; //将private的TempTestFnction()函数地址赋给pTempTestFnction指针
g_internalMember.pm_hInst = &m_hInst; //将private成员m_hInst的地址赋给g_internalMember的pm_hInst指针.
...
}
最后我们在MainDlgProc()函数中就可以很方便的调用TempTestFnction(),不必再借助于CallDlgProc()了:
//消息的回调函数的实现
BOOL CALLBACK CMainDlg::MainDlgProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)
{
if(g_pDlg != NULL)
{
(*g_internalMember.pTempTestFunction)();
//如果需要获取m_hInst值,可以这么简单调用:
//HINSTANCE hInst = *(g_internalMember.pm_hInst);
}
return FALSE;
}
有的朋友看了《创建》一文后,觉得设置一个静态变量不是一个好方法,因为如果创建多个对象的话,静态变量只保持最后一个对象的地址。但在平时的使用中,我们发现同一个进程几乎不会同时出现两个及两个以上的一模一样功能相同的对话框,所以这个例子是针对于一次只出现一个对话框的实现。
严谨一点来说,其实这个类还应该设置个互斥量,让在同一进程中对象只存在一个。这个比较简单,但和本篇主题联系不大,故在此暂且不表。
附:更改后的代码
///////////////////////////
//MainDlg.h
///////////////////////////
typedef struct _InternalMember
{
HINSTANCE *pm_hInst;
void (*pTempTestFuncion)();
}INTERNALMEMBER,*LPINTERNALMEMBER;
class CMainDlg
{
//--------------------------------------------------------------------------------------------
public:
//静态的回调函数
static BOOL CALLBACK CMainDlg::MainDlgProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
//-------------------------------------------------------------------------------------------
//Function
public:
//构造函数
CMainDlg(HINSTANCE hInst);
//析构函数
virtual ~CMainDlg();
//创建对话框
BOOL CreateMainDlg();
private:
//临时测试调用函数,仅作为调试用
void TempTestFuncion(){MessageBox(NULL,L"test",L"",NULL);};
//---------------------------------------------------------------------------------------------
//数据成员
private:
HINSTANCE m_hInst;
HWND m_hDlg;
};
然后是MainDlg类的实现:
/////////////////////////////////
//MainDlg.cpp
////////////////////////////////
#include "stdafx.h"
#include "MainDlg.h"
#include "resource.h"
//全局指针,用来指向所创建的对象,即this的指向对象
CMainDlg *g_pDlg = NULL;
InternalMember g_internalMember;
//消息的回调函数的实现
BOOL CALLBACK CMainDlg::MainDlgProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)
{
switch(wMsg)
{
case WM_INITDIALOG:
(*g_internalMember.pTempTestFunction)();
break;
}
return FALSE;
}
//构造函数
CMainDlg::CMainDlg(HINSTANCE hInst)
{
g_pDlg = this; //存储this对象到全局变量中
m_hInst = hInst;
g_internalMember.pTempTestFunction = TempTestFnction;
g_internalMember.pm_hInst = &m_hInst;
}
//析构函数
CMainDlg::~CMainDlg()
{
}
//创建对话框
BOOL CMainDlg::CreateMainDlg()
{
m_hDlg = CreateDialog(m_hInst,MAKEINTRESOURCE(IDD_MAIN_DLG),NULL,MainDlgProc);
if(m_hDlg == NULL)
{
return FALSE;
}
ShowWindow(m_hDlg,TRUE);//显示窗口
return TRUE;
}
这是在主程序中对类的的调用:
//////////////////
//MainApp.cpp
//////////////////
#include "stdafx.h"
#include "MainDlg.h"
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
//声明一个对象
CMainDlg mainDlg(hInstance);
//创建并显示窗口
if(mainDlg.CreateMainDlg() == FALSE)
{
return 0x05;
}
//消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者