簡體   English   中英

CEdit框的NM_KILLFOCUS被調用兩次

[英]NM_KILLFOCUS of a CEdit box is called twice

我有一個CPropertyPage,上面保存了一些編輯框,最著名的是基於CPropertySheet的選項卡控件,它由一個稱為CMainPage的類控制。 此CPropertySheet選項卡控件由6個相同的CPropertyPages組成,它們的顯示取決於是否選中某些復選框。 這些后續頁面由稱為CPage的單獨類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的問題是, 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;
         }
    }
}

也許不是您要尋找的答案,但有幾件事浮現在腦海:

  1. 您可以檢查緩沖區是否被修改(例如,通過存儲緩沖區的哈希值),請參閱: https : //en.cppreference.com/w/cpp/utility/hash
  2. 代替KillFocus事件,您可以使用空閑循環來檢入並保存。這可能是更適合自動保存的時間。 請參閱: https : //docs.microsoft.com/zh-cn/cpp/mfc/reference/cwinapp-class?view=vs-2019#onidle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM