Kurz Visual C++ (5.)


Po delší době je tu nová lekce o vývojovém prostředí VC++. Lekce je rozdělena na dvě části, přičemž první část bude o editoru VC++. Dozvíte se například, jak lze formátovat text a co všechno se dá nastavit pro IDE. V druhé části se zaměříme na dynamické knihovny a na správu větších projektů. Dovíte se, jak vkládat další projekty do stávajícího projektu a zajistit, aby se kompilovaly ty správné projekty.

5.1 Editor Visual C++

Záložky

Záložky jsou velmi účinným prostředkem pro navigaci v souboru. Používají se pro rychlý přístup k nejpoužívanějším řádkám zdrojového kódu (klávesovou zkratkou). Existují dva typy záložek: pojmenované a nepojmenované. Hlavní rozdíl mezi nimi je, že pojmenované záložky se zachovávají i po uzavření projektu a jeho opětovném otevření, ale nepojmenované ne. Výhodou nepojmenovaných záložek ale je, že je lze nastavit rychle nastavit (klávesovou zkratkou Ctrl+F2) a jsou okamžitě vidět v šedém levém okrají otevřeného souboru. Nepojmenovaná záložka se nastavuje na řádek, na kterém je kurzor, a na první sloupec (bez ohledu na to, ve kterém sloupci je kurzor). Všechny nepojmenované záložky je možné vymazat klávesovou zkratkou Ctrl+Shift+F2.

Oproti tomu pro nastavení pojmenovaných záložek použijte klávesovou zkratku Alt+F2 nebo z menu vyberte Edit - Bookmarks. Do pole Name napište název a klikněte na tlačítko Add. Záložka se nastavuje na aktuální řádek i sloupec, ale není nijak vidět (pouze v dialogu Bookmarks).

Pro přechod na záložku použijte klávesové zkratky F2 pro přechod na další záložku nebo Shift+F2 pro pohyb na předchozí. Tyto klávesové zkratky fungují pro pojmenované i nepojmenované záložky.

Pohyb mezi závorkami

Ve zdrojovém kódu jsou velmi časté konstrukce uzavřené mezi závorkami. Může se jednat o bloky kódu uzavřené ve složených závorkách, nebo o struktury s kulatými závorkam ve výrazech, ve kterých je někdy velmi špatná orientace, kdy nemůžeme najít zavírací závorku k otevírací. Visual C++ toto řeší velice jednoduchým způsobem: pokud je kurzor před nějakou závorkou (ať už otevírací nebo zavírací) je možné najít její pár klávesovou zkratkou Ctrl+E nebo Ctrl+]. Obdobně je možné označit celý text mezi odpovídajícími si závorkami klávesovou zkratkou Ctrl+Shift+E nebo Ctrl+Shift+].

Podmínky preprocesoru

Používáte-li podmíněný překlad pomocí podmínkových direktiv preprocesoru, můžete pro rychlý přesun mezi direktivami používat klávesové zkratky Ctrl+K pro přesun dopředu (na další direktivu #elif, #else, #endif) nebo Ctrl+J pro přesun dozadu. Obdobně jako u pohybu mezi závorkami můžete pro označení místo pouhého nalezení přidat klávesu Shift.

Další možnosti hledání

F4/Shift+F4 Hledání v chybách při překladu (přesun na další/předchozí chybu)
F12 Nalezení deklarace/definice identifikátoru (proměnné, funkce) na místě kurzoru
Shift+F12 Nalezení reference (použití) identifikátoru (proměnné, funkce)
Ctrl+Num- Nalezení předchozí reference identifikátoru (proměnné, funkce)
Ctrl+Num+ Nalezení další reference identifikátoru (proměnné, funkce)

Tyto klávesové zkratky (až na F4 a Shift+F4) se opírají o informace pro prohledávání (browse info), které se negenerují automaticky. Pro povolení jejich generování je potřeba v nastaveni projektu (Project Settings – Alt+F7) povolit "Generate browse info" na kartě C++ v kategorií General. Visual C++ Vám také nabídne vytvoření informací pro prohledávání při prvním použití nějakého hledání, které je vyžaduje.

Informace pro prohledávání jsou mnohem výkonnější, pomocí nich je možné nechat si zobrazit strukturu zdrojového kódu. Tato možnost je dostupná přes klávesovou zkratkou Alt+F12.

Dialog Go To

Nechcete-li používat klávesové zkratky, můžete vyvolat dialog Go To klávesovou zkratkou Ctrl+G. Tento dialog umí hledat některé výše uvedené položky (chyby, záložky, reference, deklarace) a také přechod na řádku textu zadáním jejího čísla.

Další zajímavé klávesové zkratky

Sestavení a překlad

Ctrl+F5 Spuštění programu
F5 Spouštění programu v ladicím módu (platí "breakpoints")
Shift+F5 Zastavení programu běžícího v ladicím módu
F7 Sestavení aktivního projektu (bez spuštění)
Ctrl+F7 Překlad zdrojového souboru v aktivním okně

Editor

Alt+F8 Formátuje označený text standardním způsobem (který Visual C++ nabízí při psaní) – za tip děkuji Vladimíru Vojtovi
Ctrl+U/Ctrl+Shift+U Převede označený text na malá/velká písmena
Ctrl+Shift+8 Zobrazuje mezery a tabulátory
Ctrl+I Inkrementální hledání (po stisknutí se text, který zadáte, neprojeví v textu, ale použije se pro hledání). Hledání ukončíte klávesou Esc (zrušení označení dosud nalezeného textu) nebo Enter
Tab/Shift+Tab Posune označený text (alespoň jeden celý řádek) o jeden tabulátor doprava/doleva

 

5.2. Dynamicky linkované knihovny - DLL

Tato část o DLL není pro ty, kteří se chtějí dozvědět, jak pracují DLL, ale pro ty, kteří chtějí vědět, jak DLL vytvořit a jak ji zakomponovat do stávajícího projektu, případně jak pracovat s jejími exportovanými funkcemi či třídami. To znamená, že zde nebudu vysvětlovat jakým způsobem se DLL připojuje k hlavnímu programu a ani zde nebudu vysvětlovat vnitřní strukturu DLL.

5.2.1 Typy projektů DLL

Ve Visual C++ máme hned několik typů dynamických knihoven, které můžeme vytvořit. Výsledné knihovny jsou velice podobné, ale odlišný je způsob jejich programování a odlišné jsou také schopnosti knihovny.

Za prvé můžete vytvořit Win32 DLL, to je tak úplně nejzákladnější knihovna, která ovšem neumí pracovat s MFC. Dále můžete vytvořit knihovnu s podporou MFC, ale ty se dále dělí na dva druhy. MFC knihovna může být buď běžná (regular) nebo rozšiřující (extension). Běžná knihovna navíc může linkovat MFC knihovny buď staticky nebo dynamicky, to je stejné jako u projektu EXE (o statickém a dynamickém linkování MFC knihoven byla řeč v minulosti). Jinak knihovna Win32 a běžná DLL MFC se od sebe liší jen málo, samozřejmě podstatný rozdíl je v používání MFC, ale jinak jsou identické. Rozdílná je ovšem rozšířená knihovna DLL.

5.2.2. Běžná versus rozšířená DLL

Rozšířená knihovna narozdíl od běžné může exportovat třídy, členské funkce, přetížené funkce apod., zkrátka podporuje objektové C++. Tohle všechno běžná knihovna neumožňuje a můžete tak exportovat pouze C funkce. Pokud ale budete chtít knihovnu použitelnou i z jiného programovacího prostředí, měli byste použít běžnou knihovnu.

Další je rozdíl ve vyhledávání zdrojů (resources - dialogy, bitmapy, kursory apod.). Pokud máte uložený nějaký zdroj v rozšířené knihovně a tento zdroj má v programu unikátní ID, pak ho program najde. Program se totiž nejdříve podívá, zda-li nemá hledaný zdroj u sebe, pokud ne, hledá v rozšířených knihovnách připojených k tomuto programu, nakonec hledá zdroje v knihovnách MFC. Pokud se ID opakují ve vašem programu a  v knihovně, pak se použije zdroj z programu a ne z knihovny! Běžné knihovny se neprohledávají.

5.2.3. Příklad

Výsledkem této lekce bude projekt, který obsahuje program EXE a jednu rozšiřující knihovnu. Zkusíme si vytvořit jednoduchou třídu a tu exportovat. Navíc si ukážeme, jak ve VC++ nastavit projekt tak, aby se rozšiřující knihovna linkovala k našemu program EXE.

Nyní si vytvoříme tzv. Blank Workspace, což je úplně prázdný projekt, který neobsahuje žádný pod projekt. Je to snadné! V menu File vyberte New. Na následujícím dialogu zvolte Workspaces a zde Blank Workspace. Vepište jméno do příslušného okénka a stiskněte OK. Všimněte si, že v  Classview nevidíte zatím nic.

Nyní vložte do programu MFC projekt. Opět dejte New z menu File, ale nyní zvolte kartu Projects. Tam nastavte třeba MFC EXE. Teď ale musíte na kartě také nastavit, že tento projekt chcete přidat do stávajícího Workspace. Tuto možnost vidíte vpravo na dialogu: Add to current workspace. Zatrhněte tuto volbu, opět vepište jméno a OK. Samozřejmě se spustí AppWizard, ale nás teď nebude příliš zajímat, jaký typ aplikace vytvoříme. Vytvořte třeba dialogovou aplikaci. Nyní vidíte, že do Classview se nám přidal projekt, jakoby bychom ho vytvořili přímo. Jediný rozdíl je ten, že tento projekt je v podadresáři Workspace.

Dále přidejme knihovnu DLL. Opět v menu File vyberte položku New a na kartě Projects vyberte projekt MFC DLL. Opět musíte zatrhnout položku Add to current workspace. Vepište jméno a OK. Objeví se dialog AppWizardu:

Zvolte MFC Extension DLL a Finish! Nyní vidíte v  ClassView zásadní rozdíl. Projekt se přidal k našemu programu, takže máte dva projekty v jednom workspace. Ve workspace může být jen jeden projekt aktivní (to je ten, který se kompiluje a spustí po stisku F5). K tomuto aktivním projektu se kompilují ty projekty, které jsou potřeba pro správný běh aktivního projektu. Jak nastavíme, který projekt závislý na kterém? Velice snadno. VC++ má toto nastavení přímo v sobě. Ve menu Project zvolte položku Dependencies (závislosti):

V prvním okénku zvolte projekt, který chcete modifikovat (tj. projekt, která má být na někom závislý). V druhém okénku pak vidíte, na kom aktuální projekt může být závislý. My zde máme pouze Knihovnu, takže tu zaškrtněte a dejte OK. Kdybyste nyní označili jako aktuální Knihovnu, zjistili byste, že již nemůže být závislá na Programu. To je logické. Když je Program závislý na Knihovně, nemůže být zároveň Knihovna závislá na Programu. Lze tedy nastavit jen jednosměrnou závislost. Toto nastavení závislosti za prvé způsobí, že se bude kompilovat projekt Knihovny kdykoliv, kdy budete kompilovat Program, čili program se nespustí, aniž by se nejdříve nevytvořila Knihovna. Zadruhé způsobí to, že knihovna je automaticky přilinkována k Programu tzn., že budete moci používat exporty Knihovny v Programu.

Dále musíme nastavit, aby se Knihovna (soubor .DLL) i Program (soubor .EXE) vytvořili ve stejném adresáři, v nějakém Debug či Release adresáři celého Workspace. V menu Project zvolte položku Settings.... Na kartě Link musíme do okénka Output file name přidělat dvě tečky a lomítko, aby se adresář Debug vytvořili o úroveň výš tj. v adresáři Multiprojekt. Toto nastavení proveďte pro oba projekty v Release i v Debug módu:



Nyní nastavíme aktivní projekt Program. Klikněte v ClassViev pravým tlačítkem na projekt, který chcete aby byl aktivní. V kontextovém menu zvolte volbu Set as Active project. Vidíte, že aktivní projekt se v ClassView objeví jako tučný. Nyní si zkuste cvičně zkompilovat projekt Program a uvidíte, že se nejdříve zkompiluje Knihovna a pak Program. Ve skutečnosti se Knihovna vůbec nezavádí, protože ještě nevoláme žádnou její exportovanou funkci či nepoužíváme žádnou její exportovanou třídu. To se ale brzo změní.

Přidáme novou třídu do projektu Knihovna. Abych nemuseli přepínat aktivní projekt na Knihovnu, využijeme opět kontextového menu v ClassView. Nyní ale zvolte New Class. Objeví se již známý dialog. Zde zvolte Generic Class a vepište nějaké zajímavé jméno, třeba CPepa. Nyní použijeme makro AFX_EXT_CLASS, které zajistí export z DLL a import do EXE. Toto makro vložte za klíčové slovo class v deklaraci třídy CPepa. Nyní je třída CPepa exportována a můžeme ji využít v Programu. Ještě Pepovi doplníme nějaká jednoduchá data, abychom viděli, že to skutečně funguje. V příkladu jsem mu doplnil jen věk, ale vy samozřejmě můžete vytvořit co právě potřebujete.

Poznámka: Makro AFX_EXT_CLASS můžete využít i při exportu funkcí. Zkrátka vložte makro vložte buď před funkci nebo mezi návratovou hodnotu a jméno funkce, tím se stává funkce viditelná pro okolní projekty. Dejte si ale pozor, abyste vložili hlavičkový soubor funkce do projektu, kde ji chcete použít. Výše uvedené makro se už postará, aby funkce byla importována. Makro využívá konstanty, které jsou definovány pouze v rozšířené knihovně. Z toho plyne, že nejde použít v běžné DLL.


Dále vytvoříme instanci Pepy v Programu. Například ve třídě CProgramDlg najděte funkci OnInitDialog(). V této funkci vytvoříme objekt Pepy a zkusíme ho naplnit daty, které si později zase vyzvedneme. Důležité ovšem je, abyste "includovali" hlavičkový soubor třídy CPepa do Programu. Makro AFX_EXT_CLASS importuje celou třídu. Jakmile toto všechno uděláte, můžete třídu Pepa používat stejně jako by byla v Programu a ne v Knihovně. Také si všimněte výstupního okna IDE, zde uvidíte jak se knihovna zavádí a jak se ruší.

Příklad k této lekci si můžete stáhnout v sekci Downloads. Možná na vás tento příklad bude přespříliš složitý, protože jsme ještě nedělali dialogy apod., ale to hlavní tam jistě najdete.

Děkujeme za pozornost a u dalšího dílu se těšíme nashledanou.

Andrei Badea a Jiří Formánek