【Demo 0050】消息窗体

本例练习消息窗体的实现以及消息窗体收发消息;  对消息窗体的定义MSDN里描述大体是这样的, 父窗体指定为HWND_MESSAGE常量,它可以收发消息,没z-order, 不可遍历且不无能接收到广播消息仅做简单的消息分发; 我们可以在创建窗体时指定其父窗体为HWND_MESSAGE常量也可以将现有窗体通过SetParent将父窗体设为HWND_MESSAGE常量从而达到变成消息窗体的目的;

查找消息窗体句柄, 可以通过FindWindowEx这个函数将其hParent设为HWND_MESSAGE, 并指定类名或窗体名即可找到;

一、代码演示(为了方便演示提供了二个工程分别为Demo0050 – 实现消息窗体创建以及接受消息和发送消息;  Demo0050Ex – 实现消息的发送以及广播消息的接收

     1.  创建消息窗体(Demo0050)


//////////////////////////////////////////////////////////////////////////
HWND CreateWnd(const TCHAR* szClsName, const TCHAR* szWndCaption, HWND hParent = NULL,
               DWORD dwStyle = WS_POPUP|WS_VISIBLE|WS_SYSMENU|WS_CAPTION,
               DWORD dwStyleEx = 0)
{
    if (NULL != szClsName)
    {
        HWND hWnd = CreateWindowEx(dwStyleEx, szClsName, szWndCaption, dwStyle,
                                   0, 0, 800, 480, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
    
        if (NULL != hWnd && IsWindow(hWnd))
        {
            return hWnd;
        }
    }
    return NULL;
}

     2.  查找消息窗体并发送消息(Demo0050Ex)

    

HWND hMsgWnd = FindWindowEx(HWND_MESSAGE, NULL, _T("Win32App"), NULL);
for (int ii = 0; ii < sizeof(CtrlsInfo) / sizeof(*CtrlsInfo); ii++)
{
    if (wParam == CtrlsInfo[ii].m_ID)
    {
        CtrlsInfo[ii].m_fnProc(hMsgWnd, hWnd);
        
        break;
    }
}

     列举了自定义消息(WM_UMSG_DATA),系统默认消息(WM_QUIT),  广播消息(WM_UMSG_BROADCAST、WM_UMSG_MSGWNDCREATED) 以及WM_COPYDATA消息

const UINT  WM_UMSG_DATA            = (WM_APP + 1001);
const UINT    WM_UMSG_REGISTER        = RegisterWindowMessage(_T("Register_MSG"));
const UINT    WM_UMSG_BROADCAST        = RegisterWindowMessage(_T("BroadCast_MSG"));
const UINT    WM_UMSG_MSGWNDCREATED    = RegisterWindowMessage(_T("MSGWndCreated_MSG"));

typedef void (*FUNPROC)(HWND hWnd, HWND hSender);
struct TCtrlInfo {
    TCHAR        m_szClsName[32];
    TCHAR        m_szText[64];
    UINT        m_ID;
    FUNPROC        m_fnProc;
};

void  OnSendUserMsg(HWND hWnd, HWND hSender)
{
    PostMessage(hWnd, WM_UMSG_DATA, 100, 110);
    
    return;
}

void  OnSendRegisterMsg(HWND hWnd, HWND hSender)
{
    PostMessage(hWnd, WM_UMSG_REGISTER, 200, 220);

    return;
}
void  OnSendBroadcastMsg(HWND hWnd, HWND hSender)
{
    PostMessage(HWND_BROADCAST, WM_UMSG_BROADCAST, 300, 330);

    return;
}

void  OnSendCopyDataMsg(HWND hWnd, HWND hSender)
{
    struct TPerson {
        UINT    m_nAge;
        TCHAR    m_szName[64];
    };
    
    TPerson Person = { 25, _T("Greg.Yi") };
    COPYDATASTRUCT cds;
    cds.dwData    = 1;
    cds.cbData    = sizeof(Person);
    cds.lpData    = &Person;

    SendMessage(hWnd, WM_COPYDATA, (WPARAM)hSender, (LPARAM)&cds);

    return;
}

void  OnSendExitMsg(HWND hWnd, HWND hSender)
{
    PostMessage(hWnd, WM_CLOSE, 0, 0);

    return;
}

   

     3.   接收消息( Demo0050,  Demo0050Ex)

     a. Demo0050 消息处理


const UINT  WM_UMSG_DATA            = (WM_APP + 1001);
const UINT    WM_UMSG_REGISTER        = RegisterWindowMessage(_T("Register_MSG"));
const UINT    WM_UMSG_BROADCAST        = RegisterWindowMessage(_T("BroadCast_MSG"));
const UINT    WM_UMSG_MSGWNDCREATED    = RegisterWindowMessage(_T("MSGWndCreated_MSG"));

struct TPerson {
    UINT    m_nAge;
    TCHAR    m_szName[64];
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{    
    switch (nMsg)
    {
        case WM_CREATE:
        {
            MessageBox(hWnd, _T("Message Reciver(Demo0050) Launched!"), _T("Demo0050"), MB_OK);
            PostMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 0);
            break;
        }
        case WM_COPYDATA:        
        {
            COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
            TPerson* pPerson = (TPerson*)cds->lpData;

            TCHAR szTmp[129];
            _stprintf(szTmp, _T("Demo0050 Received a CopyData Messaged -- age: %d name: %s"), pPerson->m_nAge, (LPTSTR)pPerson->m_szName);
            MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);

            break;
        }
        case WM_UMSG_DATA:        
        {
            TCHAR szTmp[129];
            _stprintf(szTmp, _T("Demo0050 Received a User Messaged -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
            MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
            break;
        }
        case WM_CLOSE:
        {
            SendMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 1);
            PostQuitMessage(0);
            break;
        }
    }

    if (WM_UMSG_REGISTER == nMsg)
    {
        TCHAR szTmp[129];
        _stprintf(szTmp, _T("Demo0050 Received a Register Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
        MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
    } else if (WM_UMSG_BROADCAST == nMsg) {
        TCHAR szTmp[129];
        _stprintf(szTmp, _T("Demo0050 Received a Broadcast Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
        MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
    }
    
    return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}

     b.  Demo0050Ex 消息处理


if (WM_UMSG_BROADCAST == nMsg)
{
    TCHAR szTmp[129];
    _stprintf(szTmp, _T("Demo0050Ex Broadcast Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
    MessageBox(NULL, szTmp, _T("Demo0050Ex"), MB_OK);
} else if (WM_UMSG_MSGWNDCREATED == nMsg) {
    HWND hMsgWnd = FindWindowEx(HWND_MESSAGE, NULL, _T("Win32App"), NULL);
    for (int ii = 0; ii < sizeof(CtrlsInfo) / sizeof(*CtrlsInfo); ii++)
    {
        EnableWindow(GetDlgItem(hWnd, CtrlsInfo[ii].m_ID), (0 == lParam) ? TRUE : FALSE);
    }
}

二、演示结果总结

     1.  消息窗体窗体是不可见,在SPY++窗体中可以找到, 但同步不到也就是说没有被遍历到.

     2.  在Demo0050Ex发出广播消息(WM_UMSG_BROADCAST)后, Demo0050Ex自己收到, 但Demo0050没有收到

     3.  WM_COPYDATA 消息必须由SendMessage 函数发送(同步方式,系统为了确保数据有效)

演示代码

原文地址:https://www.cnblogs.com/ztercel/p/2175047.html