通過編寫串口助手工具學習MFC過程——(四)添加ComboBox組合框

來源:互聯網
上載者:User

標籤:ppa   傳回值   val   控制   tco   數值   app   部分   內容   

通過編寫串口助手工具學習MFC過程

因為以前也做過幾次MFC的編程,每次都是項目完成時,MFC基本操作清楚了,但是過好長時間不再接觸MFC的項目,再次做MFC的項目時,又要從頭開始熟悉。這次通過做一個串口助手再次熟悉一下MFC,並做了一下記錄,以便方便以後查閱。做的過程中多是遇到問題直接百度和Google搜尋來的,所以很多都是不求甚解,知其然不知其所以然。另外做此工具只是為了熟悉瞭解,許多功能還沒有完善!(開發工具VS2008)

(四)添加ComboBox組合框

ComboBox組合框有編輯框和下拉式清單方塊的複合功能。通過該控制項的Type屬性可以進行相關設定。ComboBOX控制項Type屬性 :

Dropdown(預設)組合框,可下拉可編輯  

Drop List 下拉式清單方塊,只能下拉不能編輯

Drop Simple  編輯框,只能編輯不能下拉。

屬性:資料可設定下拉式清單顯示的內容,資料間隔用英文的分號”;”。下拉式清單顯示的內容也可以在程式中設定,如果這個下拉式清單的內容可能會編輯更改,這裡就不要設定,直接在程式在添加就可。

中屬性Sort也很重要,將他設定成False就不會根據下拉式清單的內容自動排文了,下拉式清單顯示的順序就是自己想要的定義成的那樣。

添加控制項、修改屬性ID和增加變數部分略,參見按按鈕部分。

1、ComboBox的準系統:

//校正位 無;奇數同位;偶校正;

char verifiBuf[][7]={"無","奇數同位","偶校正"};

for(int i=0;i<3;i++)

{

m_ComboCheckBit.AddString(A2T(verifiBuf[i]));

}

m_ComboCheckBit.SetCurSel(0);

上面幾行代碼出現在初始對話方塊時,預設顯示的。

m_ComboCheckBit.AddString(A2T(verifiBuf[i]));

在下拉式清單增加字串,不管原來是什麼,直接增加到後面(Sort設定為False)。回值大於等於0時,是列表中項的下標。出錯時,返回CB_ERROR,沒有足夠的空間存放新的字串時返回CB_ERRSPACE。

A2T()將字串轉為寬字元WCHAR *。char verifiBuf[][7]定義成了二維數組來儲存字串,當然也可以定義成字串數組來儲存字串。

m_ComboCheckBit.SetCurSel(0); 設定當前選項為第0項,如不設定,此組合框最初什麼數值都沒有。本函數在組合框的列表框中選擇一個字串,調用成功時返回選中的項的下標。如果nSelect大於列表中項的個數,則返回CB_ERR。如果nSelect為-1,則清除當前的選擇並返回CB_ERR。

m_ComboCheckBit.GetCurSel();本函數用於取得組合框中當前選中的項的下標。返回組合框中列表框中當前選中的項的下標。如果沒有選中項,則返回CB_ERR。

下面幾行代碼從組合框中擷取字串

//傳輸速率

int baudIndex = pstComCWnds->pComboBaudActual->GetCurSel(); //傳輸速率序號

pstComCWnds->pComboBaudActual->GetLBText(baudIndex,m_BaudStr); //從組合框的列表框中取得一個字串(下標,擷取字串存入的cstring類)返回字串長度

BaudRate = atoi(T2A((LPCTSTR)m_BaudStr)); //獲得傳輸速率

這個函數做為獲得傳輸速率在編輯自訂的傳輸速率時要判斷輸入是否是數字,才能這麼使用,否則不安全。

這個從組合框擷取字串的函數還有另一個重載。

int GetLBText( int nIndex, LPTSTR lpszText ) const;

返回字串的位元組數,不包括終結符null。如果nIndex指定的值無效,則返回CB_ERR。

(2)實現特殊功能:下拉式清單自動調整寬度

串口名字是通過枚舉獲得的,名字較長,點下拉框時,名字不能完全顯示。所以就讓下拉框下拉時寬度變寬,從而能顯示出完整的名字

當點擊ComboBOX的三角使下拉式清單展開時,下拉部分自動根據文字長度設定寬度,不改變原大小。

//ComboSelseri 選擇串口組合框下拉動作響應將根據下拉選項最大的長度設定下拉框寬度

//控制項添加 CbnDropdown 響應事件 下拉框下拉訊息

void CserialtestDlg::OnCbnDropdownComboSelseri()

{

// TODO: 在此添加控制項通知處理常式代碼

int i = 0;

int originalLen = m_ComboSelSeri.GetDroppedWidth();  //擷取原下拉框的寬度(像素)

int lenBuf = originalLen;

int lenTmp = 0;

//宣告身份識別符

USES_CONVERSION; //使用A2T()或T2A()寬位元組和多位元組轉換時使用的

//點開下拉框時,預設選擇原來的那個串口

char m_SeriouStr[16] = {0};

CDeviceInfo * pCDeviceInfo = &m_DeviceInfo; //串口裝置名稱字

int m_SeriouCurSel =  m_ComboSelSeri.GetCurSel();; //串口選擇按鈕,當前選擇的序號

memcpy(m_SeriouStr, pCDeviceInfo->stDeviceInfo[m_SeriouCurSel].sDeviceName, sizeof(m_SeriouStr));//串口名字

m_ComboSelSeri.ResetContent(); //下拉式清單清除清單項目

for(i = 0; i<m_ComboSelSeri.GetCount();i++) //擷取下拉式清單項數

{

//擷取下拉式清單每項顯示文字的位元組數 並轉為像素寬度。因為設定下拉式清單的寬度單位是像素。此轉換方式是用笨法測試出來的。

lenTmp = (m_ComboSelSeri.GetLBTextLen(i)+1)*CHAR_PIXEL_NUM;

if(lenTmp > lenBuf)

{

lenBuf = lenTmp;

}

}

if(lenBuf > originalLen)

m_ComboSelSeri.SetDroppedWidth(lenBuf);    //設定下拉式清單的寬度(像素)

}

#define CHAR_PIXEL_NUM 6 //每個字元多少像素 人為根據現象設定

相關函數說明:

CComboBox::GetDroppedWidth
int GetDroppedWidth( ) const;
傳回值:
調用成功時,返回允許的最小寬度,否則返回CB_ERR。
說明:
本函數用於取得組合框中的列表框所允許的最小寬度(以像素為單位)。它只對風格為CBS_DROPDOWN或CBS_DROPDOWNLIST的組合框有效。

CComboBox::SetDroppedWidth
int SetDroppedWidth( UINT nWidrh );
傳回值:
調用成功時,返回列表框的新寬度。否則返回CB_ERR。
參數:nWidth 組合框的列表框所允許的最小寬度(以像素為單位)。

說明:
本函數用於設定組合框中列表框所允許的最小寬度。只對風格為CBS_DROPD-OWN或CBS_DROPDOWNLIST的組合框有效。

顯示效果如下:

(3)實現特殊功能:只能下拉和只能編輯切換屬性

組合框只能下拉或只能做編輯功能好辦,只需要修改控制項的type屬性為Drop List 或Drop Simple就能實現。但如果需要在程式運行過程中動態切換這兩種屬性如何做呢?

方法一:通過一個複選框實現切換功能

//複選框單擊事件

void CserialtestDlg::OnBnClickedCheck1()

{

// TODO: 在此添加控制項通知處理常式代碼

long param ;

if(check1.GetCheck()) //擷取複選框1(check1.)是否選中

{

//如果複選框1(check1.)被選中

check2.EnableWindow(FALSE); //另一個實驗中  複選框禁止

//修改屬性,CBS_DROPDOWN 原屬性,CBS_DROPDOWNLIST新的屬性

if(TRUE == m_comboBox1.ModifyStyle(CBS_DROPDOWN,CBS_DROPDOWNLIST))

{

printf("1111\n");

}

else

{

printf("2222\n");

}

//m_comboBox1.DestroyWindow();

RecreateComboBox(&m_comboBox1,&param); //修改屬性實現,執行此功能才能修改控制項屬性。

}//m_LcConfig是你的ListCtrl控制項變數

else

{

check2.EnableWindow(TRUE);

if(TRUE == m_comboBox1.ModifyStyle(CBS_DROPDOWNLIST,CBS_DROPDOWN))

{

printf("1111\n");

}

else

{

printf("2222\n");

}

//m_comboBox1.DestroyWindow();

RecreateComboBox(&m_comboBox1,&param);

}

}

複選框的功能將在下一節介紹,此函數中有printf()調試時列印語句,在VC的控制台程式中會列印輸出,但MFC中預設不會列印輸出,以後會介紹如何在MFC中添另控制台用於列印輸出。

//RecreateComboBox函數引自://(http://www.codeproject.com/KB/combobox/recreatecombobox.aspx)

// 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;

}

方法二:通過兩個組合列表框交替使用來實現

本例中使用了下面的方法,此方法是自己原創(也許不是,只是自己按方法一實現後想到的另一種實現方法而已)

通過兩個組合列表框交替使用來實現, 並將使用的賦給程式正常用時的指標變數。pComboBaudActual為程式中使用的指標變數,他儲存兩個組合列表框中的正在使用的那個地址。

並將正在使用的組合列表框顯示,將不在使用的隱藏(這兩個組合框位置上重合,程式執行起來就像是同一個組合框一樣)。

把當前組合框選中的項,設定為新組合框的選項。通過pComboBaudActual指標實現。

//兩個組合框添加  CBN_SELCHANGE事件響應, 控制項中的選定內容已變更事件。

//ComboBaud 傳輸速率組合框選中切換某一項動作

void CserialtestDlg::OnCbnSelchangeComboBaud()

{

// TODO: 在此添加控制項通知處理常式代碼

int i =0;

if((i = pComboBaudActual->GetCurSel()) == 0) //當列表框選擇第0項時

{

//切換組合框

pComboBaudActual ->ShowWindow(SW_HIDE);  //原來使用的隱藏

pComboBaudActual = &m_ComboBaudEdit; //將另一個要使用賦值

pComboBaudActual ->SetCurSel(i); //並將選擇項賦給新列表

pComboBaudActual->ShowWindow(SW_SHOW); //將新列表框顯示

}

}

//ComboBaudedit 傳輸速率組合框選中切換某一項動作

//這是另一個組合框選擇程式,功能與上個函數相同

void CserialtestDlg::OnCbnSelchangeComboBaudedit()

{

// TODO: 在此添加控制項通知處理常式代碼

int i =0 ;

if((i = pComboBaudActual->GetCurSel()) != 0)

{

//切換組合框

pComboBaudActual ->ShowWindow(SW_HIDE);

pComboBaudActual = &m_ComboBaud;

pComboBaudActual ->SetCurSel(i);

pComboBaudActual->ShowWindow(SW_SHOW);

}

}

pComboBaudActual->ShowWindow(SW_SHOW); //將列表框顯示

pComboBaudActual ->ShowWindow(SW_HIDE); //將列表框隱藏

通過編寫串口助手工具學習MFC過程——(四)添加ComboBox組合框

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.