2017-09-14 2 views
1

J'ai une zone de liste déroulante dans laquelle je veux afficher une chaîne différente lors de la sélection d'un élément dans Combo.Afficher le texte formaté lors de la sélection d'un élément dans la zone de liste déroulante

Ma zone de liste déroulante est une liste déroulante déroulante.

Par exemple: J'ai suivi dans ma liste déroulante.


Alex - Directeur

Rain - Chef de projet

Shiney - Ingénieur

Meera - Ingénieur


OnSelecting un élément dans combobox Je veux diaply seulement nom c'est à dire Alex.

J'ai essayé ci-dessous le code

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); 
} 

Je suis en mesure d'atteindre mon exigence OnComboSelChange() et flèche événement touches mais en appuyant sur Entrée après l'aide des touches fléchées dans la boîte combo, il ne montre pas du texte formaté en combo boîte.

+3

Vous devriez éviter d'utiliser PreTranslateMessage, et attraper l'événement désiré pas là, mais SELEND_OK: Voir plus ici: https://msdn.microsoft.com/en-us/library/12h9x0ch(VS.80).aspx – flaviu2

+3

" ON_CBN_SELCHANGE La sélection dans la zone de liste d'une zone de liste modifiable est sur le point d'être modifiée suite à un clic de l'utilisateur dans la zone de liste ou à une modification de la sélection à l'aide des touches fléchées. la zone de liste déroulante peut uniquement être récupérée via GetLBText ou une autre fonction similaire. GetWindowText ne peut pas être utilisé. " – flaviu2

+0

Merci flaviu2.Mais je n'ai besoin d'afficher que du texte formaté lorsque l'utilisateur clique dans la zone de liste ou change la sélection en utilisant les touches fléchées.Comment réaliser ceci? – user566

Répondre

5

Je pense que la solution la plus fiable et la plus facile à implémenter est de subclass le contrôle d'édition de la liste déroulante. Interceptez le message WM_SETTEXT et changez le texte comme vous le souhaitez avant de le transmettre au reste de la chaîne (enfin le proc de la fenêtre d'origine).

Installer la sous classe proc OnInitDialog():

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

ComboEditSubClassProc() pourrait ressembler à ceci:

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); 
} 

Notes:

Contrairement à mon original solution de traitement CBN_SELCHANGE, le courant solution fonctionne également correctement si la liste déroulante la liste est fermée en appuyant sur Retourne ou est rejetée.

Je pense que c'est en général plus fiable car nous n'avons pas besoin de compter sur l'ordre des notifications. La zone de liste modifiable doit enfin appeler WM_SETTEXT pour modifier le contenu du contrôle d'édition afin que ce message soit toujours reçu.

Il n'y aura pas non plus de scintillement comme dans la solution d'origine où le texte a d'abord été modifié par la combobox et ensuite modifié par notre code seulement après le fait.