2017-09-14 33 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来更改编辑控件的内容,以便始终接收此消息。

也不会像原来的解决方案那样闪烁,其中文本首先被组合框改变,然后只有在事实后才由我们的代码修改。

相关问题