CEdit 框的NM_KILLFOCUS被调用两次
NM_KILLFOCUS of a CEdit box is called twice
我有一个CPropertyPage,上面保存了一些编辑框,最值得注意的是一个基于CPropertySheet的选项卡控件,它由一个名为CMainPage
的类控制。此 CPropertySheet 选项卡控件由 6 个相同的 CPropertyPages 组成,这些页面的显示取决于是否勾选了某些复选框。这些后续页面由一个名为CPage
的单独类控制。
在这些页面上,我有一堆CEdit框,我可以在其中写入一些数据。我希望以某种方式存储此数据,而无需用户执行某些操作(例如连续单击保存按钮)。
到目前为止,我已经设法通过使用ON_NOTIFY
宏捕获了NM_KILLFOCUS
消息。然后,我将这些数据存储在属于CPage
类的结构中。然后将此结构发送到CMainPage
类,该类处理它并将数据存储在 .xml 文件中。
它看起来像这样(仅显示相关功能):
CMainPage.h:
CPage::TPageData m_PageData[6];
CPage _page[6];
void SetPageData(int nPageId, CPage::TPageData::pageData);
CMainPage.cpp:
CMainPage::CMainPage()
{
for(int i = 0; i < 6; i++)
{
_page[i].InitUI(this);
_page[i].SetPageId(i);
}
}
void
CMainPage::SetPageData(int nPageId, CPage::TPageData pageData)
{
if( strlen(pageData.Edit1) > 0)
m_PageData[nPageId].Edit1 = pageData.Edit1
if( strlen(pageData.Edit2) > 0)
m_PageData[nPageId].Edit2 = pageData.Edit2
}
CPage.h:
struct TPageData {
CString Edit1,
CString Edit2;
};
afx_msg void OnKillFocus(NMHDR *pNMHDR, LRESULT *pResult);
void InitUI(CWnd* pVME);
void SetPageId(int n);
TPageData m_PageData;
int m_PageId;
CMainPage* m_pMainPage;
CPage.cpp:
BEGIN_MESSAGE_MAP(Page, CPropertyPage)
ON_NOTIFY(NM_KILLFOCUS, IDC_EDIT1, &Page::OnKillFocus)
ON_NOTIFY(NM_KILLFOCUS, IDC_EDIT2, &Page::OnKillFocus)
END_MESSAGE_MAP()
// Called during initialization of each CPage object.
void
CPage::InitUI(CWnd* pVME)
{
m_pMainPage = reinterpret_cast<CMainPage *>( pVME);
}
void
CPage::SetPageId(int n)
{
m_PageId = n;
}
void
Page::OnKillFocus(NMHDR *pNMHDR, LRESULT *pResult)
{
// Get text from edit box
CString Str;
GetDlgItem(pNMHDR->idFrom)->GetWindowText(Str);
switch(pNMHDR->idFrom)
{
case IDC_EDIT1:
{
m_PageData.Edit1 = Str;
m_pMainPage->SetPageData(m_PageId, m_PageData);
break;
}
case IDC_EDIT2:
{
m_PageData.Edit2 = Str;
m_pMainPage->SetPageData(m_PageId, m_PageData);
break;
}
}
*pResult = 1;
}
我现在遇到的问题是,NM_KILLFOCUS
消息被调用了两次,这意味着OnKillFocus()
被调用了两次。当我在不同的选项卡之间切换时,它会被更频繁地调用。我不知道是什么原因造成的,有人有什么建议吗?
编辑:过去我通过捕获NM_RETURN
消息来解决此问题。这意味着用户必须在完成输入后按 Enter 键。但是,用户很快就对这个解决方案感到恼火,并要求我以不同的方式解决它,因此提出了问题。
截至目前,我将各个CPage
的所有数据传输到一个"TPageData"结构数组。一旦用户确信所有数据传输到阵列,用户就会点击保存,然后将此阵列中的所有数据解析到磁盘。加载数据时,一切都是反向完成的。
使用EN_CHANGE
解决!看这里:
BEGIN_MESSAGE_MAP(CPage, CPropertyPage)
ON_EN_CHANGE(IDC_EDIT1, &CPage::OnEnChange)
ON_EN_CHANGE(IDC_EDIT1, &CPage::OnEnChange)
END_MESSAGE_MAP()
void
CPage::OnEnChange()
{
CString Str;
CWnd* pWnd = GetFocus();
int iControlID = pWnd->GetDlgCtrlID();
CEdit* pEditCtrl = (CEdit*)(pWnd);
pEditCtrl->GetWindowText(Str);
switch(iControlID)
{
case IDC_EDIT1:
{
m_PageData.Edit1 = Str;
m_pMainPage->SetPageData(m_PageId, m_PageData);
break;
}
case IDC_EDIT2:
{
m_PageData.Edit1 = Str;
m_pMainPage->SetPageData(m_PageId, m_PageData);
break;
}
}
}
也许不是您正在寻找的答案,但我想到了几件事:
- 您可以检查缓冲区是否被修改(例如,通过存储 缓冲区的哈希)请参阅:https://en.cppreference.com/w/cpp/utility/hash。
- 您可以使用空闲循环来代替 KillFocus 事件 签入+保存。这可能是更适合自动保存的时间。看: https://learn.microsoft.com/en-us/cpp/mfc/reference/cwinapp-class?view=vs-2019#onidle
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- C++析构函数调用两次,堆栈分配的复合对象
- Qt插槽调用了两次
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 调用一个小函数两次(例如在if条件和主体中)比将结果存储在局部变量中更可取
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 插槽调用了两次qt
- 调用某个回调函数两次会导致分段错误:Nan
- 基于 MFC 对话框的应用程序无法调用对话框两次
- 重载运算符 new(),为什么构造函数被调用两次?
- 当 reset() 被unique_ptr调用两次时会发生什么?
- 为什么在C 中超载邮政增量运算符两次调用构造函数
- 现代C++编译器是否能够避免在某些条件下两次调用常量函数
- 如果我对async_read进行两次调用,那么只有在处理完第一次调用之后,才会处理第二次调用,这是否安全
- 如何正确地将对象添加到向量,而无需两次调用析构函数
- boost::asio vs. libpcap:避免两次调用关闭
- 为什么 DNSServiceProcessResult 两次调用我的回调
- 在资源管理器左窗格上两次调用Windows 7外壳扩展dll Initialize方法
- 通过连续两次调用boost::asio::read来检索正确的数据