原文链接:http://www.codeproject.com/KB/combobox/recreatecombobox.aspx
这篇文章不错,担心以后被网站删除掉,难以看到,于是,放在这。以后自己查看也方便。呵呵
Dynamically re-creating a combo box
Introduction
Something which I frequently find myself needing to do is to switch a combo box to or from sorted. This is one reason (though not the main reason) I came up with my Dynamically Switchable Control. However, changing these styles after creation is something that combo-box does not support. This function presented here will recreate the combo box so that style changes take effect. The function will retain all list items, with item data, and the currently selected, or entered, text.
When the style is modified on a combobox to include or remove the CBS_SORT
for example, it can be seen (by using GetStyle()
, or using a tool such as Spy++) that the control does in fact have the new style, and yet the control's behaviour has not changed. The function here simply gets the current info from the control, i.e. styles, font etc, and recreates the control using these values.
How to use
I originally had a CComboBox
-derived class which one member function to recreate the controls, but decided that this was more trouble than it was worth, as most of my combos derived from other things. Therefore I have presented this as a single function, which should be included in a global library file, so that you can invoke it on any combobox at any time.
In order to change the style of a combo, you should perform the usual method of setting the new style e.g.
combo.ModifyStyle(0, CBS_SORT);
and then after that call you should call:
RecreateComboBox(&combo)
The function takes an optional void pointer, lpParam
, which is passed to CreateEx
on recreating the control. If you have special requirements when creating your controls, and you normally pass in some data for the creation parameters, then you should pass the same info in here. Most developers can simply ignore this parameter.
The Function
The function to recreate the combo is below:
// recreate the combo box by copying styles etc, and list items // and applying them to a newly created control BOOL RecreateComboBox(CComboBox* pCombo, LPVOID lpParam/*=0*/) { if (pCombo == NULL) return FALSE; if (pCombo->GetSafeHwnd() == NULL) return FALSE; CWnd* pParent = pCombo->GetParent(); if (pParent == NULL) return FALSE; // get current attributes DWORD dwStyle = pCombo->GetStyle(); DWORD dwStyleEx = pCombo->GetExStyle(); CRect rc; pCombo->GetDroppedControlRect(&rc); pParent->ScreenToClient(&rc); // map to client co-ords UINT nID = pCombo->GetDlgCtrlID(); CFont* pFont = pCombo->GetFont(); CWnd* pWndAfter = pCombo->GetNextWindow(GW_HWNDPREV); // get the currently selected text (and whether it is a valid list selection) CString sCurText; int nCurSel = pCombo->GetCurSel(); BOOL bItemSelValid = nCurSel != -1; if (bItemSelValid) pCombo->GetLBText(nCurSel, sCurText); else pCombo->GetWindowText(sCurText); // copy the combo box items into a temp combobox (not sorted) // along with each item's data CComboBox comboNew; if (! comboNew.CreateEx(dwStyleEx, _T("COMBOBOX"), _T(""), dwStyle, rc, pParent, nID, lpParam)) return FALSE; comboNew.SetFont(pFont); int nNumItems = pCombo->GetCount(); for (int n = 0; n < nNumItems; n++) { CString sText; pCombo->GetLBText(n, sText); int nNewIndex = comboNew.AddString(sText); comboNew.SetItemData(nNewIndex, pCombo->GetItemData(n)); } // re-set selected text if (bItemSelValid) comboNew.SetCurSel(comboNew.FindStringExact(-1, sCurText)); else comboNew.SetWindowText(sCurText); // destroy the existing window, then attach the new one pCombo->DestroyWindow(); HWND hwnd = comboNew.Detach(); pCombo->Attach(hwnd); // position correctly in z-order pCombo->SetWindowPos(pWndAfter == NULL ? &CWnd::wndBottom : pWndAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); return TRUE; }
History
- Version 1 - 26 Jul 2002 - First version
- Version 2 - 30 Jul 2002 - modified to include changes suggested by Jean-Michel LE FOL and Davide Zaccanti