消息映射如何与 SendMessage() 方法交互?

How do message maps interface with the SendMessage() method?

尽管阅读了大量 MSDN 文章,但我似乎无法完全理解 MFC 的消息映射和 SendMessage() 函数。现在我有一个名为 IDC_IPADDRESS_MYADDRESS 的 IP 控件,我想为其设置值。我知道 IPM_SETADDRESS 是正确的消息类型,但我不知道如何成功发送消息并更新 ip 控件的值。

我需要将什么添加到我的消息映射中,

BEGIN_MESSAGE_MAP(myDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON1, &myDlg::OnBnClickedButton1)
END_MESSAGE_MAP()

以及如何正确使用该映射条目来更新 ip 地址控件的值?下面是我尝试在对话框初始化方法中使用 SendMessage() 调用更新它。

// myDlgmessage handlers

BOOL myDlg::OnInitDialog()
{
    myDlg::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here

    //set default IP address    
    DWORD IP = MAKEIPADDRESS(192, 168, 0, 254);
    SendMessage(IPM_SETADDRESS, 0, IP); 

    return TRUE;  // return TRUE  unless you set the focus to a control
}
SendMessage(IPM_SETADDRESS, 0, IP);

IPM_SETADDRESS 是正确的消息,但它被发送到主对话框。对话框不查找此消息并忽略它。

您想改为将消息发送到 IP 控件。这意味着您需要 IP 地址控制的 window 句柄:

CWnd *ptr_ip_address = GetDlgItem(IDC_IPADDRESS_MYADDRESS);
if (ptr_ip_address)
    ptr_ip_address->SendMessage(IPM_SETADDRESS, 0, IP);

在 MFC 中,您可以使用 CIPAddressCtrl class 代替。你必须用 DoDataExchange 声明 m_ip_address 和 subclass 它。这个class还有SetAddress方法。

class CMyDialog : public CDialogEx
{
    ...
    CIPAddressCtrl m_ip_address;
    void DoDataExchange(CDataExchange* pDX);
};

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_IPADDRESS_MYADDRESS , m_ip_address);
}

BOOL myDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    m_ip_address.SetAddress(192, 168, 0, 254);
    ...
}

MFC 消息映射与您的问题没有直接关系。消息映射用于响应 windows 消息。例如,您想回复 ON_BN_CLICKED。但是这里你是向控件发送消息,而不是接收消息。

您可以在有关 WinAPI 编程的书籍中阅读更多相关信息。在普通 windows 编程中,有一个 "message loop" 和一个 "windows procedure",您可以在其中回复消息。 MFC 使用消息映射来简化此过程。

BOOL myDlg::OnInitDialog()
{
    myDlg::OnInitDialog(); <- recursive
    ...
}

顺便说一句,把myDlg::OnInitDialog放在myDlg::OnInitDialog里会导致栈溢出。改为调用基数 class,CDialogEx::OnInitDialog();