2017-09-14 106 views
1

我有一個組合框,因爲我想在選擇組合項目時顯示不同的字符串。在組合框中選擇項目時顯示格式化文本

我的組合框是一個下拉式組合框。

例如:我在我的組合框中有以下內容。


亞歷克斯 - 經理

雨 - 項目負責人

Shiney - 工程師

米拉 - 高級工程師


OnSelecting在組合框中的項目我只想diaply名字即亞歷克斯。

我嘗試下面的代碼

struct details{ 
    CString name; 
    CString des; 
}; 

BOOL CComboTestDlg::OnInitDialog() 
{ 
    CDialog::OnInitDialog(); 

    details d1; 
    d1.name = _T("alex"); 
    d1.des =_T("manager"); 
    m_vec.push_back(d1); 

    details d2; 
    d2.name = _T("Rain"); 
    d2.des =_T("Engineer"); 
    m_vec.push_back(d2); 


    // TODO: Add extra initialization here 
    for(int i=0;i<m_vec.size();i++) 
    { 
     m_ctrlCombo.AddString(m_vec[i].name+m_vec[i].des); 
     m_ctrlCombo.SetItemData(i,(DWORD_PTR)&m_vec[i]); 
    } 
    m_ctrlCombo.SelectString(-1,m_vec[0].name); 
    m_ctrlCombo.SetWindowText(m_vec[0].name); 

    return TRUE; // return TRUE unless you set the focus to a control 
} 

void CComboTestDlg::OnCbnSelchangeCombo1() 
{ 
    int nItem = m_ctrlCombo.GetCurSel(); 
    details* det = (details*)m_ctrlCombo.GetItemData(nItem); 
    PostMessage(SETCOMBOTEXT,IDC_COMBO1,(LPARAM)(LPCTSTR)det->name); 
} 

BOOL CComboTestDlg::PreTranslateMessage(MSG* pMsg) 
{ 
    MSG msg1=*pMsg;//I am loosing the value after checking ..so storing temp. 
    MSG msg; 
    CopyMemory(&msg, pMsg, sizeof(MSG)); 
    HWND hWndParent = ::GetParent(msg.hwnd); 
    while (hWndParent && hWndParent != this->m_hWnd) 
    { 
     msg.hwnd = hWndParent; 
     hWndParent = ::GetParent(hWndParent); 
    } 

    if (pMsg->message==SETCOMBOTEXT && (pMsg->wParam == IDC_COMBO1)) 
     SetDlgItemText(IDC_COMBO1, (LPCTSTR)pMsg->lParam); 

    if(pMsg->message==WM_KEYDOWN) 
    { 
     if(pMsg->wParam==VK_RETURN && msg.hwnd ==m_ctrlCombo.m_hWnd) 
     { 
      OnCbnSelchangeCombo1(); 
     } 
    } 
    return CDialog::PreTranslateMessage(pMsg); 
} 

我能達到我的要求OnComboSelChange()鍵和方向鍵的事件,但是,按在組合框中使用箭頭鍵回車鍵後,它沒有顯示在組合格式的文本框。

+3

您應該避免使用PreTranslateMessage,並且不要使用所需的事件,但SELEND_OK:請參閱此處的更多信息:https://msdn.microsoft.com/en-us/library/12h9x0ch(VS.80).aspx – flaviu2

+3

「 ON_CBN_SELCHANGE由於用戶在列表框中單擊或使用箭頭鍵更改選定內容,組合框的列表框中的選擇即將更改。處理此消息時,編輯控件中的文本組合框只能通過GetLBText或其他類似的函數獲取,GetWindowText不能使用。「 – flaviu2

+0

謝謝flaviu2。但我需要只顯示格式的文本列表框,當用戶單擊或使用箭頭keys.How實現這一改變選擇? – user566

回答

5

我覺得最可靠和最容易實現的解決方案就是對組合框的編輯控件subclass。攔截WM_SETTEXT消息並在將其轉發到鏈的其餘部分(最後是原始窗口過程)之前,根據需要更改文本。

OnInitDialog()安裝子類PROC:

COMBOBOXINFO cbi{ sizeof(cbi) }; 
if(m_ctrlCombo.GetComboBoxInfo(&cbi)) 
{ 
    SetWindowSubclass(cbi.hwndItem, ComboEditSubClassProc, 0, 0); 
} 

ComboEditSubClassProc()看起來是這樣的:

LRESULT CALLBACK ComboEditSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, 
    LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) 
{ 
    switch(uMsg) 
    { 
     case WM_SETTEXT: 
     { 
      CString text = reinterpret_cast<LPCTSTR>(lParam); 
      // Extract the name (everything before "-"). 
      CString name = text.SpanExcluding(_T("-")); 
      name.TrimRight(); 
      // Forward the modified text to any other sub class procs, aswell 
      // as the original window proc at the end of the chain. 
      return DefSubclassProc(hWnd, uMsg, 0, reinterpret_cast<LPARAM>(name.GetString())); 
     } 
     case WM_NCDESTROY: 
     { 
      // We must remove our subclass before the subclassed window gets destroyed. 
      // This message is our last chance to do that. 
      RemoveWindowSubclass(hWnd, ComboEditSubClassProc, uIdSubclass); 
      break; 
     } 
    } 

    return DefSubclassProc(hWnd, uMsg, wParam, lParam); 
} 

注:

出乎我的處理CBN_SELCHANGEoriginal solution,目前解決方案也可以正常工作,如果組合框下拉按退還或被解僱。

我認爲它通常更可靠,因爲我們不必依賴通知的順序。組合框必須最終調用WM_SETTEXT來更改編輯控件的內容,以便始終接收此消息。

也不會像原來的解決方案那樣閃爍,其中文本首先被組合框改變,然後只有在事實後才由我們的代碼修改。

相關問題