Deci, vom crea un program care:
- Acesta poate deschide și salva fișiere de mai multe formate, în timp ce în dialogul de salvare puteți alege unul dintre următoarele tipuri:
- Toate tipurile acceptate (* .ex1; * .ex2; * .ex3)
- Primul tip (* .ex1)
- Al doilea tip (* .ex2)
- Al treilea tip (* .ex3)
- Toate fișierele (*. *)
- Înregistrează deschiderea fișierelor cu astfel de extensii prin dublu clic.
- La voință, la înregistrare creează sau nu creează o intrare în meniul contextual "Creare".
- Fiecare dintre aceste trei extensii își cartografiază pictograma.
Noțiuni de bază
Deci, rulați AppWizard, numim aplicația noastră SDI. În primul pas, selectați tipul - Document unic. bifați caseta de selectare Document / View architecture support Limba engleză. Al doilea pas. nu sunt necesare baze de date, setate la None. În al treilea rând. containerele nu sunt necesare, niciunul. A patra. Aici am pus casetele de validare, am lăsat totul ca în mod implicit. Faceți clic pe butonul Avansat și introduceți parametrii noii aplicații:
Apoi puteți apăsa imediat Finish. nu există setări mai mult sau mai puțin importante. Ne compilam proiectul curat și îl executăm. Nu puteți face nimic în program, înregistrarea fișierelor apare automat la pornire.
Acum vreau să fac o altă abatere, dedicată unei analize mai detaliate a ceea ce tocmai am intrat. Aici veți afla cum sunt înregistrate fișierele în sistem și ce este scris în registru. Dacă cineva știe deja toate acestea, puteți trece peste paragraful următor.
Înregistrarea fișierelor în sistem
Presupun că cititorul este deja familiarizat cu ceea ce este un registru și cum să lucrați cu el. Dacă nu, este o mulțime de literatură dedicată acestui lucru, așa că nu vă voi spune aici elementele de bază.
Pentru ca Windows să știe cum să lucreze cu un fișier, setați pictograma pentru acesta, schimbați nota de context etc. trebuie să creați un identificator de fișier în registru. Aceasta este ceea ce am specificat în câmpul ID de tip de fișier. Acesta este, în esență, numele tipului de fișier din punctul de vedere al sistemului. Toate tipurile de fișiere sunt stocate în registru în filiala [HKEY_CLASSES_ROOT] cu același nume. Să ne uităm la ramura noului tip de fișier: [HKEY_CLASSES_ROOT \ SDI.Document]. În această ramură a opțiunii (implicit) (în versiunile engleză de Windows - (implicit)) conține un nume de tip de fișier așa cum apare acesta pentru utilizator: Deschideți orice folder de pe unitatea pentru a deschide meniul contextual, și acolo submeniul nou. printre altele, veți vedea un anumit "fișier Unnamed" - nimic asemănător? Aceasta este valoarea introdusă în câmpul Nume nou nume (lung nume). și este, de asemenea, în parametrul (implicit) al ramurii [HKEY_CLASSES_ROOT \ SDI.Document].
Păi, mergem mai departe. Noi extindem această crenguță și a vedea cele două subsecțiuni: DefaultIcon și coajă .Vtoroy nu avem nevoie, iar acest lucru este primul în aceeași setare (implicit) implicit conține pictograma care este asociat cu acest tip de fișier.
Ei bine, așa cum am descris tipul de fișier, am dezasamblat. Rămâne să învățăm ceva mai mult: cum comunică tipul de fișier cu extensia? Este foarte simplu. În aceeași secțiune de registry, [HKEY_CLASSES_ROOT] enumeră toate extensiile - acestea sunt partiții care încep cu o perioadă. Găsiți acolo și extensia noastră - .ex1 (punctul este important!). În parametrul (Implicit) din această secțiune, vedem doar identificatorul tipului căruia este atașată această extensie, adică documentul nostru SDI.Document.
Și rămâne să indicăm ultimul detaliu de care avem nevoie în viitor: aceasta este prezența subcheiei ShellNew în secțiunea [HKEY_CLASSES_ROOT \ .ex1]. Din cauza prezenței acestei subsecțiuni, avem un nou tip de fișier în meniul Nou. Încercați să eliminați sau să redenumiți ShellNew. și veți vedea că fișierul "Unnamed" va dispărea din acest meniu.
Deci acum știm semnificația a trei dintre cele șapte câmpuri umplute. Câmpurile rămase nu sunt relevante pentru registru, ci numai pentru programul propriu-zis. Anume: Captionul principal al cadrului este pur și simplu titlul ferestrei principale a aplicației; Numele filtru - un filtru care apare în ferestrele de dialog pentru deschiderea și salvarea fișierelor; Doc nume de tip - tipul nostru numele punctului programului de vedere (dacă vom programa acceptă mai multe tipuri diferite de documente pe care le creați un nou pentru dialog este afișată vă solicită să selectați tipul de document care urmează să fie creat Doc nume de tip -. Este numele care apare pe lista din. cererea noastră nu va fi); Fișier nou nume (nume scurt) - numele noului document în mod implicit (în aplicațiile cu mai multe ferestre, când se creează un nou document gol, numele său este creat din acest parametru plus numărul de serie).
Acum cunoaștem în întregime semnificația tuturor acestor manipulări misterioase pe care le-am făcut înainte. Puteți începe procesul de modificare a programului în conformitate cu sarcina.
Adăugați mai multe extensii
În momentul de față programul suportă doar o singură extensie - EX1. Pentru a adăuga EX2 și EX3 avem nevoie. deschideți resursele șir ale programului nostru și căutați linia cu IDR_MAINFRAME. Nu voi descrie în detaliu formatul acestei linii - majoritatea sunt liniile despre care am spus deja, dacă ceva nu este clar - mergeți la MSDN. ) Următoarea parte a acestei linii este importantă pentru noi acum: \ nSDI Fișiere (* .ex1) \ n.ex1 \ n. Să o modificăm după cum urmează: \ nSDI Fișiere (* .ex1; * .ex2; * .ex3) \ n.ex1; .ex2; .ex3 \ n. compilați și executați cererea noastră. În ferestrele de deschidere și de economisire, vedem aceleași filtre și funcționează! E atât de simplu? Din păcate, nu chiar. Uită-te în registru: tipul de fișier este asociat cu o extensie foarte interesantă .ex1; .ex2; .ex3. Nu este foarte asemănător cu înregistrarea corectă a tipurilor de fișiere de care avem nevoie.
Și acum încep dansurile cu tamburina, ceea ce ar trebui să ne ducă la ceea ce vrem să primim.
Deci, avem probleme cu înregistrarea extensiilor. Metoda CWinApp este responsabilă de înregistrare. RegisterShellFileTypes (). Cu toate acestea, intrăm în această metodă, vedem că singura acțiune semnificativă pe care o efectuează este o provocare
m_pDocManager -> ÎnregistrareShellFileTypes (bCompat);
Și aici este metoda CDocManager. RegisterShellFileTypes (BOOL bCompat) nu face decât să lucreze la înregistrarea formatelor. Deci, trebuie să redefinăm.
Creați o nouă clasă CDocManagerEx. moștenit de la CDocManager. Acum, în fișierul SDI.cpp adăugăm o linie
m_pDocManager = noul CDocManagerEx;
Acum trebuie să ignorăm metoda CDocManagerEx. RegisterShellFileTypes (BOOL bCompat). Cea mai ușoară modalitate de a realiza o implementare normală este să o copiați din codul sursă MFC.
Atenție, vă rog. în MFC 4.2 există o mică eroare în această metodă. Într-un proiect atașat, este fixat (nimic serios, doar înregistrarea fișierului nu era cazul în condițiile în care ar trebui să se întâmple, judecând după logica codului). În MFC 7.1, această eroare este rezolvată.
Această metodă utilizează mai multe constante și funcții care nu sunt definite în fișierul nostru, deci trebuie să le transferăm din același fișier din care am luat codul de mai sus (acesta este fișierul docmgr.cpp). Aceste definiții sunt la începutul acestui fișier. Pentru codul nostru avem nevoie de toate constantele și funcția _AfxSetRegKey (.). În plus, trebuie să conectați fișierul afxpriv.h (am făcut acest lucru în fișierul stdafx.h), altfel codul nu va fi compilat.
Să începem acum cu registrele noastre de înregistrare. Această metodă pentru fiecare șablon de document înregistrat în cerere (este, avem doar un singur) creează o intrare de registru cu ID-ul corespunzător, înregistrează deschiderea fișierelor de pe dvs. EXE-fișier și stabilește o legătură între extinderea și tipul de fișier. Dacă bCompat == TRUE. trece apoi mai sunt înregistrate la aceeași comandă de imprimare EXE-fișier, se adaugă o intrare pe pictograma pentru tipul de fișiere și înregistrează cheia ShellNew pentru apariția unui nou tip de fișier din submeniu nou.
Pentru scopurile noastre, opțiunea cea mai convenabilă ar fi crearea unei metode separate pentru înregistrarea unei anumite extensii. Declarați-o ca atare
bool ÎnregistrareSingleFileType (CDocTemplate * pTemplate.CString FilterExt,
int IconNum. BOOL bCompat. BOOL bShellNew);
- pTemplate. șablon pentru documente
- FilterExt. extensie de fișier (.ex1)
- IconNum. numărul pictogramei pentru această extensie
- bCompat. trebuie doar să mutați acest parametru din RegisterShellFileTypes
- bShellNew. verificați dacă doriți să creați o intrare în meniul Nou.
În această metodă, puteți transfera aproape tot conținutul metodei RegisterShellFileTypes. trebuie doar să eliminați bucla care se repetă prin toate șabloanele de documente și să adăugați condiția de verificare a pavilionului bShellNew. Apoi, introducem codul care modifică numele tipului de fișier (este necesar pentru a face diferite pictograme), câteva adăugiri cosmetice, iar metoda este gata.
Acum rămâne să corecteze RegisterShellFileTypes. Lăsați-l pe seria șabloane de documente (în viitor, dintr-o dată este necesar.), Se introduce contorul este incrementat numere de icoane și în acest RegisterSingleFileType apel ciclu cu parametrii necesari. Rămâne să adăugați încă două pictograme pentru tipurile de fișiere dorite și decideți dacă doriți să adăugați acest tip de fișiere în meniul Nou. Am decis să nu adaug această înregistrare. Dacă cineva are nevoie cu adevărat, cred că cititorul cu această sarcină arhetipală se va descurca singur ;-)
În prezent, aproape toate sarcinile au fost deja finalizate. A rămas cel mai mic lucru - corectați dialogurile de deschidere și salvare a fișierelor, astfel încât acestea să permită alegerea filtrelor de fișier de care avem nevoie.
Mai întâi, vom repara o altă metodă - CSingleDocTemplate. MatchDocType (). În versiunea noastră de sarcină aceasta nu este, în general, necesară. Metoda MatchDocType () este responsabilă pentru determinarea tipului de fișier pentru deschidere. La noi tip una (pentru a nu confunda cu expansiunea!), Prin urmare diferența specială nu va fi. Dar dacă cineva dorește să modifice programul astfel încât să susțină mai multe tipuri de documente, atunci această metodă va fi utilă.
Pentru a face acest lucru, trebuie să ne creăm propria clasă, moștenită de la CSingleDocTemplate. Să o numim CMyDocTemplate. vom folosi constructorul clasei de bază și vom adăuga o metodă
Confidență virtuală MatchDocType (LPCTSTR lpszPathName. CDocument * rpDocMatch);
Punerea în aplicare ia de la MFC sursă și corectează astfel încât extensia de fișier nu este comparat cu șirul model al formularului“.ex1; .ex2; .ex3" . dar separat cu fiecare extensie.
Pentru ca proiectul să fie compilat, este necesar să se declare în fișierul MyDocTemplate.cpp o funcție
BOOL AFXAPI AfxComparePath (LPCTSTR lpszPath1 LPCTSTR lpszPath2.);
În continuare, trebuie să adăugați un fișier shlwapi.h antet (cel mai bun pentru a face acest lucru în fișierul stdafx.h) și includ shlwapi.lib bibliotecă. După toate acestea, accesați fișierul SDI.cpp. scrieți acolo la început
și în metoda InitInstance () căutăm liniile
CSingleDocTemplate * pDocTemplate; pDocTemplate = nou CSingleDocTemplate (
IDR_MAINFRAME,
RUNTIME_CLASS (CSDIDoc),
RUNTIME_CLASS (CMainFrame), // fereastra principală a cadrului SDI
RUNTIME_CLASS (CSDIView));
AddDocTemplate (pDocTemplate);
și înlocuiți CSingleDocTemplate cu CMyDocTemplate.
Deci, minunat. O mică odihnă și din nou pe drum. A mai rămas destul de puțin.
Metoda CDocManager este responsabilă pentru lucrul cu dialogul de selectare a fișierelor. DoPromptFileName (). Clasa CDocManagerEx deja avem, deci direct în ea noi redefinim metoda
virtual BOOL DoPromptFileName (CString FileName. UINT nIDSTitle,
DWORD lFlags. BOOL bOpenFileDialog. CDocTemplate * pTemplate);
dacă (! bOpenFileDialog) // În dialogul "Salvează ca" trebuie să eliminăm
strFilter. Gol (); // primul filtru - "Fișiere SDI (* .ex1; * .ex2; * .ex3)"
strFilter + = "Fișiere SDI-1 (* .ex1)";
strFilter + = (TCHAR) '\ 0';
strFilter + = _T ("* .ex1");
strFilter + = (TCHAR) '\ 0';
strFilter + = "Fișierele SDI-2 (* .ex2)";
strFilter + = (TCHAR) '\ 0';
strFilter + = _T ("* .ex2");
strFilter + = (TCHAR) '\ 0';
strFilter + = "Fișierele SDI-3 (* .ex3)";
strFilter + = (TCHAR) '\ 0';
strFilter + = _T ("* .ex3");
strFilter + = (TCHAR) '\ 0';
Pentru ca această metodă să funcționeze, trebuie să adăugați funcția _AfxAppendFilterSuffix (). Definiția sa este în același fișier cu implementarea metodelor din clasa CDocManager. Noi o copiem de acolo și o corectăm în conformitate cu faptul că acum avem mai multe extensii în șablonul principal. Apropo, această funcție trebuie corectată numai în MFC 4.2. Versiunea 7.1 a MFC conține deja cod care gestionează corect șabloanele cu mai multe extensii.
Ei bine, atingerea finală este adăugarea de cod care ne va face extensia corectă pentru fișierul fără nume:
CString strExt;
dacă (pTemplate -> GetDocString (strExt, CDocTemplate, filterExt) . strExt. IsEmpty ()) ASSERT (strExt [0] == '.');
int pos = fileName. Găsiți (strExt);
dacă (pos! = -1)
fileName = nume_firma. Stânga (pos) + '.' + strDefault;
>
Acest cod este adăugat aproape de sfârșitul DoPromptFileName metoda (), înainte de numefișier variabilă va fi utilizată.