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

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

本文关键字:方法 交互 SendMessage 映射 消息      更新时间:2023-10-16

尽管阅读了很多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 地址控件的值?下面是我在对话框 init 方法中使用 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 地址控制的窗口句柄:

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

在 MFC 中,可以改用CIPAddressCtrl类。您必须声明m_ip_address并用DoDataExchange对其进行子类化。此类还具有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 消息映射与您的问题没有直接关系。消息映射用于响应窗口消息。例如,您要响应ON_BN_CLICKED。但在这里,您向控件发送消息,而不是接收消息。

您可以在 WinAPI 编程书籍中阅读有关此内容的更多信息。在普通窗口编程中,有一个"消息循环"和一个"窗口过程",您可以在其中响应消息。MFC 使用消息映射来简化此过程。

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

顺便说一下,将myDlg::OnInitDialog放入myDlg::OnInitDialog会导致堆栈溢出。改为调用基类,CDialogEx::OnInitDialog();