Kurz3 - Kapitola8

17. června 2007 v 15:49 | http://www.sweb.cz/kurz_evt/ |  Programování pro WinCE

5.8 Výběr portu a jeho parametry

Jak bylo slíbeno minule, začneme dnes již pracovat se sériovým portem. Měli bychom zprovoznit kartu pro volbu a nastavení portu - "COM Options".
Z první lekce máme na první kartě funkční tlačítko pro ukončení aplikace. Pokusíme se tedy rozběhnout funkci ostatních prvků a začít detekovat a nastavovat porty na počítači.
V hlavičkovém souboru upravíme třídu CPrvni na:
////// Trida prvniho dialogu - Volby portu
class CPrvni: public CPropertyPage
{
// Volby uchovavajici nastaveni portu a jeho cislo
int m_nCom;
int m_nBaud;
int m_nParity;
int m_nData;
int m_nStop;
// Pole pro bitmapy typu portu
CBitmap Bitmap[4];

public:
CPrvni():CPropertyPage(IDD_PRVNI) {m_nCom=m_nBaud=m_nData=m_nParity=m_nStop=0;};

protected:
virtual void DoDataExchange(CDataExchange*);
afx_msg BOOL OnInitDialog();
afx_msg void OnKonec();
afx_msg void OnVolCom();
afx_msg void OnSetCom();
DECLARE_MESSAGE_MAP()
};
Předpokládám, že proměnné uchovávající nastavení portu jsou jasné. Konstruktor navíc pouze tyto proměnné vynuluje. Pole Bitmap je připraveno pro uchování obrázků typu portu. V metodách jsou doplněny OnInitDialog (volána jedenkrát při inicializaci dialogu), OnVolCom (při každé změně portu) a OnSetCom (při změně parametrů zvoleného portu).
Implementace ve zdrojovém souboru pak bude následující:
///////////////////////////////////////
//// CPrvni

BEGIN_MESSAGE_MAP (CPrvni,CPropertyPage)
ON_BN_CLICKED(IDC_KONEC,OnKonec)
ON_CBN_SELCHANGE(IDC_COM,OnVolCom)
ON_CBN_SELCHANGE(IDC_BAUD,OnSetCom)
ON_CBN_SELCHANGE(IDC_PARITY,OnSetCom)
ON_CBN_SELCHANGE(IDC_DATA,OnSetCom)
ON_CBN_SELCHANGE(IDC_STOP,OnSetCom)
END_MESSAGE_MAP()
Jistě poznáváte již důvěrně známou mapu zpráv. Povšimněte si, že metoda OnSetCom je spojena se 4 prvky.
// Inicializace dialogoveho okna
BOOL CPrvni::OnInitDialog()
{
int nBitmap[]={IDB_NONE,IDB_WHAT,IDB_COM,IDB_INFRA};
int i;
HWND hCombo;

CDialog::OnInitDialog();
// Naplnime ComboBoxy polozkami
hCombo= ::GetDlgItem(this->m_hWnd,IDC_COM);
for(i=0;i<7;i++) ::SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)szCOM[i]);
::SendMessage(hCombo,CB_SETCURSEL,0,0);
hCombo= ::GetDlgItem(this->m_hWnd,IDC_BAUD);
for(i=0;i<1;i++) ::SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)szBaud[i]);
::SendMessage(hCombo,CB_SETCURSEL,0,0);
hCombo= ::GetDlgItem(this->m_hWnd,IDC_PARITY);
for(i=0;i<4;i++) ::SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)szParity[i]);
::SendMessage(hCombo,CB_SETCURSEL,0,0);
hCombo= ::GetDlgItem(this->m_hWnd,IDC_DATA);
for(i=0;i<4;i++) ::SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)szData[i]);
::SendMessage(hCombo,CB_SETCURSEL,0,0);
hCombo= ::GetDlgItem(this->m_hWnd,IDC_STOP);
for(i=0;i<2;i++) ::SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)szStop[i]);
::SendMessage(hCombo,CB_SETCURSEL,0,0);
// Naplnim pole obrazku
for(i=0;i<4;i++) Bitmap[i].LoadBitmap(nBitmap[i]);

return 0;
}
Metoda OnInitDialog je velmi jednoduchá. Nejprve v ní zavoláme stejnojmennou metodu základní třídy, abychom zajistili správnou inicializaci dialogu. Poté naplníme jednotlivé ComboBoxy položkami pro volby.
Zde jsem si dovolil netradiční postup. I když programujeme pomocí MFC a jednotlivé prvky dialogu si můžeme zpřístupnit prostřednictvím odpovídající třídy MFC, použil jsem volání standardních API funkcí. Účelem je pouze připomenout, že knihovna MFC je nadstavbou funkcí operačního systému. Vždy se tedy můžeme s důvěrou obrátit na oblíbené API funkce... :-)
V konkrétním případě jsou volány GetDlgItem a SendMessage. Problém by mohl nastat, pokud třída (nebo některá základní třída) obsahuje metodu stejného jména jako požadovaná API funkce. Pro rozlišení se používá operátor globálního rozsahu platnosti identifikátoru (::). Funkce rozhraní API je v MFC programu volána takto:
    ::JmenoFunkce()
Dále již volání API nepoužíváme, v následující metodě vidíte, jak lze totéž provést pomocí tříd MFC.
// Obslouzeni volby portu
void CPrvni::OnVolCom()
{
int i,nPort,nOldCOM;
CComboBox *pCombo;
CStatic* pStatic;

nOldCOM=m_nCom;
UpdateData();
// Nove nastaveni provadim pokud je zvolen opravdu jiny port
if(nOldCOM != m_nCom) {
// Budu provadet vychozi nastaveni portu
m_nBaud=m_nData=m_nParity=m_nStop=0;
mujCOM.Otevreni(m_nCom);
// Zmenim ikonu typu portu
pStatic = (CStatic*)GetDlgItem(IDC_DLGBMP);
pStatic->SetBitmap((HBITMAP)Bitmap[mujCOM.TypPortu()]);
// Povolim nebo zakazu jednotlive prvky dialogu:
// Nejprve nastavim prvek pro rychlost
pCombo=(CComboBox*)GetDlgItem(IDC_BAUD); // Ziskam jeho ukazatel
// Podle typu portu naplnim ComboBox COM
pCombo->ResetContent();
nPort=1;
if(mujCOM.TypPortu()==2) nPort=10; // pro COM povolim 10 rychlosti
for(i=0;i<nPort;i++) pCombo->AddString(szBaud[i]);
pCombo->SetCurSel(0);
// Rychlost je povolena pro COM a IrCOMM
pCombo->EnableWindow(mujCOM.TypPortu()>1);
// Dalsi volby nastavim na prvni moznost a povolim pouze pro COM
pCombo=(CComboBox*)GetDlgItem(IDC_DATA);
pCombo->SetCurSel(0);
pCombo->EnableWindow(mujCOM.TypPortu()==2);
pCombo=(CComboBox*)GetDlgItem(IDC_PARITY);
pCombo->SetCurSel(0);
pCombo->EnableWindow(mujCOM.TypPortu()==2);
pCombo=(CComboBox*)GetDlgItem(IDC_STOP);
pCombo->SetCurSel(0);
pCombo->EnableWindow(mujCOM.TypPortu()==2);
}
}
Ve funkci OnVolCom již využívám možnosti tříd MFC. Například ke ComboBoxům se dostaneme pomocí ukazatele pCombo na třídu CComboBox. Jakmile naplníme ukazatel odkazem na požadovaný prvek, můžeme začít využívat členské metody třídy CComboBox, která zapouzdřuje ComboBox.
Přístup k ComboBoxům pro nastavení parametrů je povolen pouze při detekci standardního sériového portu. Výjimku tvoří infračervený port, kde je ponecháno pseudonastavení rychlosti na 115 kBaud. Protože ovladač IrCOMM si vše řídí sám, je možnost "volby rychlosti" pouze "na okrasu".
// Nastaveni parametru portu
void CPrvni::OnSetCom()
{
UpdateData();
mujCOM.SetBaud(m_nBaud);
mujCOM.SetData(m_nData);
mujCOM.SetParity(m_nParity);
mujCOM.SetStop(m_nStop);
// Promenne s parametry jsou pripraveny - nastavim port
mujCOM.SetPort();
}
Jestliže uživatel změnil nastavení parametrů portu, změním tyto údaje u objektu mujCOM a pak port podle toho nastavím.
// Ukoncim celou aplikaci
void CPrvni::OnKonec()
{
mojeAplikace.m_pMainWnd->DestroyWindow();
}
Metoda CPrvni::OnKonec() zůstala stejná - zde je zobrazena pouze pro úplnost.
// Svazani promennych s ovladacimi prvky
void CPrvni::DoDataExchange(CDataExchange* pDX)
{
DDX_CBIndex(pDX, IDC_COM, m_nCom);
DDX_CBIndex(pDX, IDC_BAUD, m_nBaud);
DDX_CBIndex(pDX, IDC_PARITY, m_nParity);
DDX_CBIndex(pDX, IDC_DATA, m_nData);
DDX_CBIndex(pDX, IDC_STOP, m_nStop);
}
... a k tomuto pouze poznamenejme, že funkce DDX_CBIndex vytváří vazbu mezi celočíselnou hodnotou a polem se seznamem.
Pokud se vám vše podařilo podle návodu upravit a přeložit, měli byste být schopni otestovat váš přístroj a zjistit, které porty jsou na něm dostupné.

obr. 59 Volba portu a jeho parametrů

Co bychom si měli z této lekce zapamatovat?

  • API funkce můžeme volat i při použití knihovny MFC.
  • Pro volání funkce rozhraní API se používá :: operátor.
 

Buď první, kdo ohodnotí tento článek.

Nový komentář

Přihlásit se
  Ještě nemáte vlastní web? Můžete si jej zdarma založit na Blog.cz.