Image
29.6.2016 0 Comments

C++ pod Windows / How to... I / 23. časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Vítam vás pri ďalšom pokračovaní seriálu. V predchádzajúcej časti sme dobrali všetko, čo som na začiatku označil ako rozumný základ, po ktorého zvládnutí budete pripravení na získavanie ďalších vedomostí a budete takisto schopní samostatne vytvárať štandardné aplikácie pre Windows. V tejto časti si môžete overiť, čo v praxi znamená „získavanie ďalších vedomostí“. Len výnimočne totiž budete mať dostatok času na preštudovanie nejakej knihy alebo rozsiahlejšej dokumentácie, dopodrobna rozoberajúcej konkrétny problém, ktorý sa snažíte vyriešiť. Oveľa častejšie budete vyhľadávať už jeho funkčné riešenie, čo je veľakrát rýchlejšie a jednoduchšie ako pokúšanie sa o samostatné riešenie (treba však povedať, že nie vždy je takéto hľadanie úspešné ). A takýto prístup vám tu teraz ponúkam. Sú to riešenia štandardných „zákysov“, s ktorými sa môžete stretnúť (niektoré som vybral z vašich mailov). Nebudú to vôbec zložité veci, na všetky by ste istotne po určitom čase prišli aj sami, ale načo vymýšľať niečo, čo už bolo vymyslené?

HOW TO ZOBRAZIŤ BITMAPU. Bitmapy sa v programoch používajú relatívne často. Najjednoduchším spôsobom, ako zobraziť bitmapu, je pridať ju do zdrojov v design-time a odtiaľ ju pomocou štandardných funkcií počas behu programu natiahnuť a zobraziť. Vytvorte si štandardnú SDI aplikáciu s Document/View podporou. Základnú triedu pohľadu odvoďte od CView. V editore zdrojov vyberte z menu Insert -> New Resource, kliknite na Bitmap a potom na Import (za predpokladu, že bitmapu už máte vytvorenú).

Nalistuje a naimportujte želanú bitmapu (napr. c:\Windows\zapotec.bmp). Tá sa teraz zobrazí v zdrojoch pod názvom IDB_BITMAP1 (ten môžete zmeniť). V triede pohľadu vo funkcii OnDraw pridajte tento kód:

void CBitmapView::OnDraw(CDC* pDC)
{
      CSize m_sizeZdroj;
 
      CBitmap* pbmpMyBitmap;
      CDC* pdcMemory;
 
      BITMAP bm;
 
      pdcMemory=new CDC;
      pbmpMyBitmap=new CBitmap;
 
      pbmpMyBitmap->LoadBitmap(IDB_BITMAP1);
      pdcMemory->CreateCompatibleDC(pDC);
      pdcMemory->SelectObject(pbmpMyBitmap);
      pbmpMyBitmap->GetObject(sizeof(bm), &bm);
 
      // Ziskame rozmery bitmapy
      m_sizeZdroj.cx=bm.bmWidth;
      m_sizeZdroj.cy=bm.bmHeight;
 
      // Zachova velkost bitmapy (+100 nema ziadny vyznam)
      pDC->BitBlt(0, 0, m_sizeZdroj.cx+100, m_sizeZdroj.cy+100, pdcMemory, 0, 0, SRCCOPY);
 
      // Umozni zmenit velkost bitmapy
      pDC->SetStretchBltMode(2);
      pDC->StretchBlt(100, 0, m_sizeZdroj.cx+100, m_sizeZdroj.cy+100, pdcMemory, 0, 0,
 m_sizeZdroj.cx, m_sizeZdroj.cy, SRCCOPY);
 
      delete pdcMemory;
      delete pbmpMyBitmap;
}

Uvedený kód predstavuje len umelý (ale funkčný) príklad, ako zobraziť v programe bitmapu. V praxi by sa žiadalo deklarácie premenných dať do hlavičkového súboru, alokovať (new) a uvoľniť (delete) pamäť do konštruktora/deštruktora a obslúžiť aj ďalší mapovací režim (uvedený príklad funguje správne len v mapovacom režime MM_TEXT).  Skúste si to.

How to prehraŤ wav zvuk. Keď už sme pri zdrojoch, ukážeme si, ako prehrať jednoduchý zvuk (wav – súbor). Najprv použijeme funkciu PlaySound (budeme prehrávať priamo súbor nahrávaný z disku) a potom si ukážeme použitie funkcie sndPlaySound na prehrávanie zvuku zo zdrojov. Vytvorte novú Dialog-Based aplikáciu a na dialóg pridajte dve tlačidlá: PlayF a PlayR (to sú hlavičky, ID nechajte default). Namapujte na ne správu BN_CLICKED a do obslužnej funkcie pre tlačidlo PlayF (IDC_BUTTON1) pridajte tento kód:

void CSoundDlg::OnButton1()
{
      // prehravame priamo zo suboru
      CString sndSound;
 
      sndSound="c:\\Windows Logon Sound.wav";
      PlaySound(sndSound, NULL, SND_FILENAME);
}

Aby sme vôbec mohli prehrávať nejaký súbor zo zdrojov, je potrebné ho tam najprv pridať. V editore zdrojov vyberte z menu Insert -> Resource a potom Import. Nalistujte hocijaký wav súbor. Po pridaní sa v editore zdrojov vytvorí nová zložka s názvom "WAVE" a v nej zdroj IDR_WAVE1.

Teraz už môžete pridať kód do funkcie OnButton2:

void CSoundDlg::OnButton2()
{
      // prehravame zo zdrojov
      HRSRC hRes;
      HGLOBAL hData;
      BOOL bOk = FALSE;
 
      if ((hRes = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_WAVE1),
"WAVE")) != NULL &&
        (hData = ::LoadResource(AfxGetResourceHandle(), hRes)) != NULL)
      {
            // prehrame zdroj
            bOk = sndPlaySound((LPCSTR)::LockResource(hData), SND_MEMORY |
       SND_SYNC | SND_NODEFAULT);
            // uvolnime
            FreeResource(hData);
      }
      if (!bOk)
            if (!bOk)
                  MessageBox("Chyba pri prehravani suboru.", "Upozornenie",
       MB_ICONWARNING | MB_OK);
}

Funkcie PlaySound sndPlaySound sú deklarované v súbore mmsystem.h a implementované v súbore winmm.lib.  Pridajte preto túto include direktívu:

#include <mmsystem.h>

a v nastaveniach projektu [menu Project -> Settings (ALT + F7)] na karte Link pridajte knižnicu winmm.lib.

How to po kliknutí na tlačidlo odobrať zo zoznamu položku a pridať ju do druhého zoznamu. Veľmi častý problém. Vytvorte si nový projekt (MFC AppWizard exe) typu Dialog based application. Všetky ostatné nastavenia nechajte default. V editore zdrojov pridajte na dialóg ovládacie prvky. Ich ID nechajte default.

Potom vo funkcii OnInitDialog naplňte IDC_LIST1:

CListBox* pLB=(CListBox*) GetDlgItem(IDC_LIST1);
 
pLB->InsertString(-1, "1. Polozka");
pLB->InsertString(-1, "2. Polozka");
pLB->InsertString(-1, "3. Polozka");
pLB->InsertString(-1, "4. Polozka");
pLB->InsertString(-1, "5. Polozka");

Pomocou Class Wizardu namapujte na tlačidlo IDC_BUTTON1 správu BN_CLICKED. Do tela obslužnej funkcie OnButton1 pridajte takýto kód:

void CListCtrlDlg::OnButton1()
{
      CString strSelection;
     
      CListBox* pLB1=(CListBox*) GetDlgItem(IDC_LIST1);
      CListBox* pLB2=(CListBox*) GetDlgItem(IDC_LIST2);
 
      // index polozky, ktora je oznacena
      int index=pLB1->GetCurSel();
 
      // ak sme nieco oznacili
      if (index!=-1)
      {
            // ziskame text
            pLB1->GetText(index, strSelection);
 
            // ak uz v List2 existuje pridavana
            // polozka, tak nepridat
            if ((pLB2->FindString(-1, strSelection))==LB_ERR)
                  pLB2->AddString(strSelection);
            else
MessageBox("Tento zaznam uz bol pridany!", "Upozornenie",
       MB_ICONINFORMATION | MB_OK);
      }
}

How to zmazať označenú položku zo zoznamu. Využijeme predchádzajúci príklad. V editore zdrojov pridajte ešte jedno tlačidlo IDC_BUTTON2 s hlavičkou X. Namapujte naň správu BN_CLICKED a do obslužnej funkcie napíšte kód:

void CListCtrlDlg::OnButton2()
{
      CListBox* pLB1=(CListBox*) GetDlgItem(IDC_LIST1);
 
      // index polozky, ktora je oznacena
      int index=pLB1->GetCurSel();
 
      if (index!=-1)
      {
            // zmazeme polozku
            pLB1->DeleteString(index); 
      }
}

 

HOW TO NAKRESLIŤ DO DIALÓGU NEJAKÚ GRAFIKU. Ak ste programovali vo Visual Basicu, kresliť do dialógu sa dalo jednoducho využitím ovládacích prvkov Shape a Line už v design time. Vo Visual C++ však tieto prvky nenájdete. Kresliť je možné len počas behu programu (run-time). Najvhodnejšia funkcia na kreslenie je funkcia OnPaint. Najlepšie je kresliť do nejakého ovládacieho prvku (napr. Static Text). Vychádzame z toho, že ovládací prvok je vlastne okno (potomok triedy CWnd), a preto môžeme doň kresliť rovnako, ako keby sme kreslili do okna.

Opäť využijeme zdroj dialógu z predchádzajúceho príkladu. Pridajte na dialóg ovládací prvok Static Text (ID nechajte default, hlavičku zmažte, rozmer: 158 × 38). Potom do funkcie OnPaint do vetvy else pridajte nasledujúci kód:

 
else
{
      // device context na kreslenie
      CPaintDC dc(this);
                 
      // ziskame ukazovatel na ovladaci prvok, do ktoreho chceme kreslit
      CWnd* pWnd=GetDlgItem(IDC_STATIC);
 
      // ziskame kontext zariadenia
      CDC* pControlDC=pWnd->GetDC();
     
      // povieme mu, ze chceme don kreslit
      pWnd->Invalidate();
      pWnd->UpdateWindow();
 
      // kreslime
      pControlDC->SelectStockObject(BLACK_BRUSH);
      pControlDC->LineTo(150, 50);
      pControlDC->Ellipse(30, 30, 50, 50);
     
      // nezabudnut uvolnit kontext zariadenia
      pWnd->ReleaseDC(pControlDC);      
           
      CDialog::OnPaint();
}

Samozrejme, nemusíte kresliť len do ovládacieho prvku Static Text, ale napríklad aj do tlačidla, zoznamu atď. (jednoducho do všetkého, čo je odvodené od CWnd).

HOW TO ZMENIŤ CAPTION TLAČIDLA ALEBO JEHO ĎALŠIE VLASTNOSTI (ROZMER, UMIESTNENIE) ZA BEHU PROGRAMU. Riešenie je podobné ako v predchádzajúcom prípade. Stačí pristupovať k ovládaciemu prvku ako k oknu a pomocou štandardných funkcií zmeniť niektoré vlastnosti. Ukážeme si, ako zmeniť hlavičku a umiestnenie. Vytvorte nový zdroj dialógu a pridajte doň ovládací prvok tlačidlo. ID nechajte default a hlavičku takisto. Ďalej pridajte ešte jedno tlačidlo (to bude iniciovať zmenu). Jeho ID tiež nechajte default a hlavičku zmeňte na Change. Namapujte naň správu BN_CLICKED a do tela obslužnej funkcie pridajte kód:

void CDrawDlg::OnButton2()
{
      //ziskame ukazovatel na ovladaci prvok tlacidla
      CWnd* pWnd=GetDlgItem(IDC_BUTTON1);
 
      // nastavime text na tlacidle
      pWnd->SetWindowText("Moj button");
 
      // zmenime polohu tlacidla - zachovame jeho velkost
      pWnd->SetWindowPos(&wndTop, 50, 10, 0, 0, SWP_NOSIZE);
}
 

HOW TO POUŽÍVAŤ ŠTANDARDNÉ FUNKCIE NA PRÁCU S REŤAZCAMI, AKO MÁ VB (MID, COMPARE ATĎ.). Visual Basic má veľmi silnú podporu pre prácu s reťazcami. Oproti nemu sa môže zdať používanie céčkovských funkcií strcmp, strcpy... trochu zdĺhavé a zložité. Ale aj VC++ (presnejšie MFC) má zabudovanú takúto podporu. Tá však nie je prístupná pre „klasické“ reťazce (char*). Aby sme ju mohli využívať, je potrebné deklarovať reťazce ako objekty odvodené od triedy MFC CString. Príklad jej použitia je tu:

CString strFirst;
CString strSecond;
 
strFirst="Mama ma Emu";
 
// skopirujeme od piatej pozicie
strSecond=strFirst.Mid(5);
// porovname (no case sensitive)
int jeRovne=strSecond.CompareNoCase(strFirst);
// hladame podretazec
int nasiel=strSecond.Find("ma");
                       
cout << (LPCTSTR)strSecond << "\n";
cout << jeRovne << "\n";
cout << nasiel << "\n";
           
// konvertujeme na velke
strSecond.MakeUpper();
cout << (LPCTSTR)strSecond << "\n";
// otocime retazec
strSecond.MakeReverse();
cout << (LPCTSTR)strSecond << "\n";
// kopitujeme obsah retazca
strSecond=strFirst;
cout << (LPCTSTR)strSecond;

Samozrejme, že funkcií na prácu s reťazcami poskytuje trieda CString oveľa viac, ich zoznam nájdete v helpe.

Nabudúce. Prvú časť How to máme úspešne za sebou. O mesiac sa rovnakým štýlom pozrieme na ActiveX komponenty, knižnice DLL, tlač a možno aj databázy. Keďže sa blížime k záveru seriálu, pýtajte sa na veci, čo vám nie sú jasné (z jednotlivých častí, prípadne iné problémy, na aké ste narazili). Môžem vám odpovedať prostredníctvom časopisu a vaše otázky tak môžu pomôcť viacerým čitateľom.


Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Tipy a triky: Ako na snímku obrazovky na akomkoľvek počítači s Windows?

02.12.2016 00:13

Ak snímky obrazovky robíte často apotrebujete napríklad funkcie na posun stránok alebo snímanie zobrazenia pri vyššom rozlíšení displeja, zrejme používate nejakú špecializovanú aplikáciu. Väčšina použ ...

Ako na to 1

Tipy a triky: Ako aplikácii prednastaviť spúšťanie s administrátorskými právami?

30.11.2016 00:10

Väčšina aspoň trochu skúsenejších používateľov vie, že aj keď máte na operačnom systéme Windows vytvorený administrátorský účet, aplikácie pre bezpečnosť nefungujú vždy splnými administrátorskými práv ...

Ako na to 2

Tipy a triky: Ako vypnúť uzamykaciu obrazovku vo Windows 10?

29.11.2016 00:10

Rozčuľuje vás, že pred každým prihlásením doúčtu vášho počítača musíte prejsť uzamykacou obrazovkou? Windows 10 na tejto obrazovke ukazuje čas,dátum anejakú zaujímavú fotografiu zrôznych kútov sveta. ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá