爱丽小屋十色眼影盘:关于CListBox和CComboBox修改窗口Style的问题

来源:百度文库 编辑:中财网 时间:2024/04/28 07:22:29
 

 

在界面编程中,经常遇到修改CListBox和CComboBox窗口式样(style)的问题.可恼的时,一旦窗口创建后(Creation),没有办法可以修改窗口式样.也就是说,ModifyStyle()和SetWindowLong()都不起作用(但调用会成功).如下面的代码:

// you can not change the style of a list box dynamically, after creation.

A. Use ModifyStyle()

m_ListBox.ModifyStyle(0,WS_HSCROLL|LBS_MULTICOLUMN);

B. Use SetWindowLong()

long style=GetWindowLong(m_ListBox,GWL_STYLE);

style|=LBS_MULTICOLUMN;

style|=WS_HSCROLL;

SetWindowLong(m_ListBox1,GWL_STYLE,style);

而在模式对话框运用中,系统是不产生OnCreate()消息的,所以就没机会修改窗口式样了.

1. 关于"CListBox"的多列功能:

当使用该功能时”垂直滚动”将不起作用,这是因为第一列后的列要等前一列的行用完后才开始使用,这很象报纸上的”栏”,有时也叫”蛇形列(snaking column)”.如果窗口只有一行, 多列显示的list象一个横向list.除非一定要这样做,不如用TabStop功能.

2. 关于"CComboBox"中list的多列功能:

CComboBox其实有3个窗口,分别为combo,edit,list.要得到edit和list的窗口句柄不容易可以参考”http://support.microsoft.com/default.aspx?scid=kb;en-us;Q174667”. 在”.net”下可以使用GetComboBoxInfo(),可惜VC++6.0下无这个函数.

// .net

//typedef struct ComboBoxInfo_tag

//{

//int cbSize;

//RECT rcItem;

//RECT rcButton;

//int  stateButton;

//HWND hwndCombo;

//HWND hwndEdit;

//HWND hwndList; // That's what I'm interested in....

//} COMBOBOXINFO,*PCOMBOBOXINFO;

//[DllImport("user32")] public static extern bool

//BOOL GetComboBoxInfo(HWND hwndCombo,COMBOBOXINFO& info);

 

//  COMBOBOXINFO info;

//  BOOL bl=GetComboBoxInfo(this->m_hWnd, info);

CComboBox中的listbox叫”COMBOLBOX”,不过跟CLlistBox好像一样(?).

3. 下面说一下对CComboBox中的listbox修改式样的方法:

a.     新建一个CSuperCombo类.响应OnCtlColor(),OnDestroy()和OnDropdown():

HBRUSH CSuperComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

    // TODO: Change any attributes of the DC here

if (nCtlColor == CTLCOLOR_LISTBOX)

{//ListBox control,It is a COMBOLBOX,not a normal listbox.Besides,

//It is not a child window of combobox.

    if (m_listbox.GetSafeHwnd() == NULL)

    {

        m_listbox.SubclassWindow(pWnd->GetSafeHwnd());

        //too later to change the sytle!         

        m_listbox.ModifyStyle(0,WS_HSCROLL|LBS_MULTICOLUMN);

        //you have to create a new list box.

        //see "Dynamically re-creating a list box" from “code project”.

        RecreateComboLBox(&m_listbox);  }

    }

 //

    HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);

    return hbr;

}

void CSuperComboBox::OnDestroy()

{

    if (m_listbox.GetSafeHwnd() != NULL) m_listbox.UnsubclassWindow();

    CComboBox::OnDestroy();

}

void CSuperComboBox::OnDropdown()

{

    // TODO: Add your control notification handler code here

    if(IsWindow(m_listbox) && !GetDroppedState())

    {

        m_listbox.ShowWindow(SW_NORMAL);

    }

}

还要一个函数来重新创建一个listbox(CSuperList类):

BOOL CSuperComboBox::RecreateComboLBox(CListBox* pList, LPVOID lpParam)

{

    CWnd* pParent = GetParent();//父窗口是对话框 dlg

    // get current attributes

    DWORD dwStyle = pList->GetStyle();

    DWORD dwStyleEx = pList->GetExStyle();

    CRect rc;

    pList->GetWindowRect(&rc);

    pParent->ScreenToClient(&rc);   // 到客户坐标

    UINT nID = IDC_COMBO;  

    CFont* pFont = pList->GetFont();

 

    // create the new list box and copy the old list box items

    // into a new listbox along with each item's data, and selection state

    CListBox listNew;//这是临时对象

// 创建一个你需要式样的listbox

    if (! listNew.CreateEx(dwStyleEx, _T("COMBOLBOX"), _T(""), dwStyle,

                                rc, pParent, nID, lpParam))

      return FALSE;

    listNew.SetFont(pFont);

    int nNumItems = pList->GetCount();

    BOOL bMultiSel = (dwStyle & LBS_MULTIPLESEL || dwStyle & LBS_EXTENDEDSEL);

    for (int n = 0; n < nNumItems; n++)

    { //所有项

        CString sText;

        pList->GetText(n, sText);

        int nNewIndex = listNew.AddString(sText);

        listNew.SetItemData(nNewIndex, pList->GetItemData(n));

        if (bMultiSel && pList->GetSel(n)) listNew.SetSel(nNewIndex);

    }

    if (! bMultiSel)

    {// 所有选择项

        int nCurSel = pList->GetCurSel();

        if (nCurSel != -1)

        {

            CString sSelText;

            // get the selection in the old list

            pList->GetText(nCurSel, sSelText);

            // now find and select it in the new list

            listNew.SetCurSel(listNew.FindStringExact(-1, sSelText));

        }

    }

    // destroy the existing window, then attach the new one

    pList->DestroyWindow();

    HWND hwnd = listNew.Detach();

    pList->Attach(hwnd);

//

    return TRUE;

}

b.     经过上步后,还要新建一个”CSuperList”类,否则listbox不会响应鼠标,要响应OnLButtonDown(),OnMouseMove():

void CSuperList::OnLButtonDown(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    BOOL bOutside;

    UINT idx=ItemFromPoint(point,bOutside);

    CString txt;

    GetText(idx,txt);

    ShowWindow(SW_HIDE);

    CMyComboDlg* pCmoboTest=(CMyComboDlg*)GetParent();

    if(idx>=0)

    {// 置ComboBox的Edit

        pCmoboTest->m_ComboTest.SetWindowText(txt);

        pCmoboTest->m_ComboTest.SetEditSel(0,-1);

        pCmoboTest->m_ComboTest.SetFocus();

    }

//  CListBox::OnLButtonDown(nFlags, point);

}

 

void CSuperList::OnMouseMove(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    BOOL bOutside;

    UINT idx=ItemFromPoint(point,bOutside);

//  afxDump <

    if(idx>=0) SetCurSel(idx);

    CListBox::OnMouseMove(nFlags, point);

}

注意:

class CSuperComboBox : public CComboBox

{…

CSuperList   m_listbox;

..

};

4. 结果:

缺图

 

源码见"schlafenhamster"发布的csdn资源