Windows隐含窗体的实现及使用

来源:互联网 发布:网络教育要不要学 编辑:程序博客网 时间:2024/04/30 01:56

1.Windows消息机制之PostMessage

        在Windows环境下,我们无法绕开Windows消息机制的话题。

        对于Windows消息机制的使用,我们用得较多的是PostMessage,该函数Windows API(应用程序接口中的一个常用函数,其功能是将一个消息抛送到指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式消息队列里的消息通过调用GetMessagePeekMessage取得。

1.1函数原型

          BOOL  PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);

1.2参数说明

        hWnd:其窗口程序接收消息的窗口的句柄。

        Msg:指定被寄送的消息。

        wParam:指定附加的消息特定的信息。

        IParam:指定附加的消息特定的信息。

       返回值:如果函数调用成功,返回非零值:如果函数调用失败,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。

       参见:http://msdn.microsoft.com/zh-cn/ms911937

2.隐含窗体的实现

2.1使用背景

        使用PostMessage首先需要获取窗口句柄hWnd,但是在有些情况下,我们无法得到窗口句柄,如创建的是MFC DLL工程,而上层应用却没有给我们传进窗口句柄参数。此时,我们可以在DLL内部创建一个隐含的窗口,通过隐含窗口的句柄来实现PostMessage函数的调用。

2.2隐含窗体的实现

        首先,我们需要创建一个子窗口类,其继承与CWnd。头文件的声明如下:

const DWORD WM_PROCEEPOSTMSG = WM_USER+1000;

class CTestChildWnd : public CWnd  

{

public:

CTestChildWnd();

//主窗口句柄,此处用于展示子窗体收到的消息

HWND m_hNotifyWnd;

 

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CMultiCastWnd)

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CTestChildWnd();

// Generated message map functions

protected:

//{{AFX_MSG(CMultiCastWnd)

// NOTE - the ClassWizard will add and remove member functions here.

//}}AFX_MSG

 

LRESULT OnProcessPostMsg(WPARAM wParam,LPARAM lParam);

DECLARE_MESSAGE_MAP()

 

};

类实现的CPP如下:

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

CTestChildWnd::CTestChildWnd()

{

m_hNotifyWnd = NULL;

}

 

CTestChildWnd::~CTestChildWnd()

{

 

}

 

BEGIN_MESSAGE_MAP(CTestChildWnd, CWnd)

//{{AFX_MSG_MAP(CMultiCastWnd)

// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP

ON_MESSAGE(WM_PROCEEPOSTMSG,OnProcessPostMsg)

END_MESSAGE_MAP()

 

 

/////////////////////////////////////////////////////////////////////////////

// CMultiCastWnd message handlers

LRESULT CTestChildWnd::OnProcessPostMsg(WPARAM wParam,LPARAM lParam)

{

//Post到主窗口展示

if (!::PostMessage(m_hNotifyWnd, WM_PROCEESHOWMSG, wParam, lParam))

{

CString *pMsg = (CString*)wParam;

if (pMsg != NULL)

{

delete pMsg;

pMsg = NULL;

}

}

 

return 0;

}

       好了,窗口框架我们已经搭建得差不多了,剩下关键的一步:创建窗体。

       为了便于说明子窗口句柄的使用方法,我们新建一个类CTestPlay,该类声明了CTestChildWnd *m_pMultiCastWnd变量。下面我们在类CTestPlay的构造函数中创建CTestChildWnd 窗体。

m_pMultiCastWnd = NULL;

m_pMultiCastWnd = new CTestChildWnd();

    _dwObjectCount++;

    CString WndClassName;

    WndClassName.Format("ChildWnd_%u",_dwObjectCount);

m_pMultiCastWnd->CreateEx(0,AfxRegisterWndClass(0),WndClassName,WS_OVERLAPPED,0,0,0,0,NULL,NULL);

       窗体使用完毕后,别忘记销毁。

if (m_pMultiCastWnd != NULL)

{

m_pMultiCastWnd->DestroyWindow();

delete m_pMultiCastWnd;

m_pMultiCastWnd = NULL;

}

        至此,CTestChildWnd 窗体创建完毕,我们可以使用其窗口句柄了。在类CTestPlay声明一个函数VOID TestPostMsg(HWND hMainWnd, int nPostCount),该函数主要功能是把消息抛送给刚创建的窗口。为了能够形象地展示我们抛送到新创建的子窗口的消息,我们在此函数中传进了主窗口句柄参数HWND hMainWnd。函数TestPostMsg的实现如下:

VOID CTestPlay::TestPostMsg(HWND hMainWnd, int nPostCount)

{

if(m_pMultiCastWnd != NULL)

{

m_pMultiCastWnd->m_hNotifyWnd = hMainWnd;

 

CString strMsg;

strMsg.Format("%d: Show Post Message Test!", nPostCount);

CString *pMsg = new CString(strMsg);

//Post到隐含子窗口处理

if (!::PostMessage(m_pMultiCastWnd->m_hWnd, WM_PROCEEPOSTMSG, (WPARAM)pMsg, 0))

{

delete pMsg;

pMsg = NULL;

}

}

}

        该函数被调用后,将会触发子窗口CTestChildWnd 的消息处理函数LRESULT OnProcessPostMsg(WPARAM wParam,LPARAM lParam),我们可以在此函数中对收到的消息进行处理。在此,我们只是继续抛送到主窗口来展示收到的消息。

LRESULT CTestChildWnd::OnProcessPostMsg(WPARAM wParam,LPARAM lParam)

{

//Post到主窗口展示

if (!::PostMessage(m_hNotifyWnd, WM_PROCEESHOWMSG, wParam, lParam))

{

CString *pMsg = (CString*)wParam;

if (pMsg != NULL)

{

delete pMsg;

pMsg = NULL;

}

}

 

return 0;

}

3总结

        以上VC++6.0实现的测试程序见资源WndTest.zip:http://download.csdn.net/detail/psy361212/7656037

       除了上述使用场景外,在异步的WIndows Socket中也可使用上述方法创建隐含窗口,来响应Socket事件。

0 0
原创粉丝点击