Основной алгоритм программы
Рисунок А.1 – Основной алгоритм программы
Вышеуказанный алгоритм основной программы реализует защиту от запуска второй копии приложения. Если копия приложения уже запущена (найдены ее окна) – программа активизирует свою предыдущую копию и завершает работу, иначе – стандартное выполнение программы. Рисунок А.2 – Алгоритм проверки регистрации по имени и номеру подкаталога Вышеуказанный алгоритм реализует проверку и регистрацию файла в отчете. Этот метод отчета применяется к каждому найденному файлу в контролируемых каталогах.
Рисунок А.3 – Главная функция для проверки каталогов и подготовки отчета
Вышеуказанный алгоритм реализует полный механизм проверки контролируемых каталогов и подготовки отчета. В алгоритме предусмотрены механизмы для досрочного завершения проверки по признаку завершения родительского потока, а также перезапуск проверки по признаку изменения файлов (от потока контроля файлов) Рисунок А.4 – Главная функция потока проверки файлов
Вышеуказанный алгоритм реализует работу потока проверки файлов. Вызовы методов потока CheckStep и SetLists синхронизируются с главным VCL-потоком программы. Проверка файлов с передачей отчета главному окну программы инициируется взведением события NeverEvent - потоком контроля файлов по факту изменения состава файлов. Также предусмотрен механизм завершения потока – взведением свойства Terminated и события NeverEvent.
Приложение Б (ОБЯЗАТЕЛЬНОЕ) Листинги программы
Файл проекта FileNames.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop //--------------------------------------------------------------------------- USEFORM("FMain.cpp", FForm); USEFORM("FSelectDirForm.cpp", SDForm);
//--------------------------------------------------------------------------- WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { //защита от повторного запуска HWND w=FindWindow("TFForm","Контроль одноименных файлов"), w2=FindWindow("TSDForm","Выбор каталога"); if(w) {//при обнаружении запущенной копии приложения - активизирует //ее главное окно и завершает работу if(IsWindowVisible(w)) { if(w2 && IsWindowVisible(w2)) SetForegroundWindow(w2); else SetForegroundWindow(w); } else PostMessage(w,WM_USER+2,0,0); } else{ //иначе - стандартное выполнение программы Application->Initialize(); Application->CreateForm(__classid(TFForm), &FForm); Application->CreateForm(__classid(TSDForm), &SDForm); Application->Run(); } } catch (Exception &exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception &exception) { Application->ShowException(&exception); } } return 0; } //--------------------------------------------------------------------------- Файл ArrayTemplate.h //---------------------------------------------------------------------------
#ifndef ArrayTemplateH #define ArrayTemplateH //--------------------------------------------------------------------------- //шаблон на динамический массив со свойствами коллекции(списка элементов) template <class T> class TArray { private: int fCount,fLength; //кол-во элементов,размер массива T *fItems; //указатель на массив protected: T __fastcall Get(int Index); //чтение элемента массива void __fastcall Put(int Index, T Item); //запись элемента массива void __fastcall SetCount(int NewCount); //установка fCount public: TArray(int aLength); //конструктор ~TArray(void); //деструктор void __fastcall Insert(int Index,T Item);//вставка элемента void __fastcall Delete(int Index); //удаление элемента void __fastcall Add(T Item); //добавление элемента void __fastcall Clear(void); //удаление всех элементов void __fastcall SetLength (int NewLen); //определить размер массива T& operator[](int Index); //оператор []-доступ к элементу void* operator&(void); //оператор & - адрес массива __property T Items[int Index] = {read=Get, write=Put}; //свойство для доступа к элементу __property int Count = {read=fCount, write=SetCount}; //свойство для доступа к кол-ву элементов списка __property int Length = {read=fLength, write=SetLength};//свойство для доступа к размеру массива }; template <class T> TArray<T>::TArray(int aLength) { fCount=0;
fLength=0; SetLength(aLength); } template <class T> TArray<T>::~TArray(void) { SetLength(0); } template <class T> T& TArray<T>::operator[](int Index) { return fItems[Index];} template <class T> void* TArray<T>::operator&(void) {return fItems;} template <class T> T __fastcall TArray<T>::Get(int Index) { return fItems[Index]; } template <class T> void __fastcall TArray<T>::Put(int Index, T Item) { fItems[Index]=Item; } template <class T> void __fastcall TArray<T>::Add(T Item){ Insert(fCount,Item); } template <class T> void __fastcall TArray<T>::Clear(void) { fCount=0; } template <class T> void __fastcall TArray<T>::SetCount(int NewCount) { fCount=NewCount; if(fCount<0) fCount=0; if(fCount>fLength) fCount=fLength; } template <class T> void __fastcall TArray<T>::Insert(int Index,T Item) { if(Index<0 || Index>fCount) return; if (fCount==fLength) SetLength(fLength+5); if (Index<fCount) Move(&fItems[Index],&fItems[Index+1],(fCount-Index)*sizeof(T)); fItems[Index]=Item; fCount++; } template <class T> void __fastcall TArray<T>::Delete(int Index) { if(Index<0 || Index>fCount-1) return; if (Index<fCount-1) Move(&fItems[Index+1],&fItems[Index],(fCount-1-Index)*sizeof(T)); fCount--; //if (fCount==fLength-6) SetLength(fCount+1); } template <class T> void __fastcall TArray<T>::SetLength (int NewLen) { if (NewLen<0 || fLength==0 && NewLen==0) return; else if (fLength==0) fItems=(T *)SysGetMem(NewLen*sizeof(T));else if (NewLen==0) SysFreeMem(fItems);else fItems=(T *)SysReallocMem(fItems,NewLen*sizeof(T)); fLength=NewLen; if (fLength<fCount) fCount=fLength; } //динамические массивы (с элементами int и HANDLE) typedef TArray<int> TIntArray; typedef TArray<HANDLE> THandleArray; #endif Файл ArrayTemplate.cpp //--------------------------------------------------------------------------- #pragma hdrstop #include <System.hpp> #include "ArrayTemplate.h" //--------------------------------------------------------------------------- #pragma package(smart_init) Файл FSelectDirForm.h //--------------------------------------------------------------------------- #ifndef FSelectDirFormH #define FSelectDirFormH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <FileCtrl.hpp> //--------------------------------------------------------------------------- class TSDForm: public TForm { __published: // IDE-managed Components TButton *Button1; TButton *Button2; TDirectoryListBox *DirectoryListBox1; TDriveComboBox *DriveComboBox1; private: // User declarations public: // User declarations __fastcall TSDForm(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TSDForm *SDForm; //--------------------------------------------------------------------------- #endif Файл FSelectDirForm.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "FSelectDirForm.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TSDForm *SDForm; //--------------------------------------------------------------------------- __fastcall TSDForm::TSDForm(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- Файл FMain.h //---------------------------------------------------------------------------
#ifndef FMainH #define FMainH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "ArrayTemplate.h" #include <ExtCtrls.hpp> #include <Menus.hpp> #include <Buttons.hpp> //--------------------------------------------------------------------------- //используемые коды сообщений #define WM_SHELLMESS (WM_USER + 1) //от значка в System Tray #define WM_SHOWMYWIN (WM_USER + 2) //от второй копии программы //тип-список строк для хранения имен файлов, а также номеров каталогов //(в списке каталогов) для каждого имени class TGlobalList:public TStringList { public: int __fastcall At(int Index); //доступ к номеру каталога для выбранного файла }; //тип-список строк для хранения имен файлов-дубликатов,а также указателей //на массивы номеров каталогов (TIntArray *) для каждого файла-дубликата class TNameList:public TStringList { public: TIntArray * __fastcall At(int Index); //доступ к массиву номеров для выбранного файла }; //предварительное объявление class TVerDirectory; //тип-поток для проверки каталогов и подготовки отчета по одноименным файлам class TDirThread:public TThread { protected: void __fastcall Execute(); //главная функция потока public: TVerDirectory *Report; //подготавливаемый отчет __fastcall TDirThread(bool CreateSuspended):TThread(CreateSuspended) {} //конструктор void __fastcall SetLists(void); //передача отчета главному окну программы void __fastcall CheckStep(void); //отмечает в главном окне начало проверки каталогов bool Term(void) {return Terminated;} //возвращает Terminated(protected - свойство) }; //тип-поток для автоматического контроля проверяемых каталогов - // при переименовке, добавлении и удалении файлов в данных каталогах (или их подкаталогах) // инициирует проверку каталогов с подготовкой отчета class TNotifyThread:public TThread { protected: void __fastcall Execute(); //главная функция потока public: __fastcall TNotifyThread(bool CreateSuspended):TThread(CreateSuspended) {}//конструктор bool Term(void) {return Terminated;} //возвращает Terminated(protected - свойство) }; //тип-подготавливаемый отчет class TVerDirectory { public: TDirThread * Owner; //поток-владелец отчета - только указатель AnsiString Path; TStringList *DirList; //список подкаталогов проверяемого каталога TGlobalList *GlobalList; //общий список имен файлов TNameList *NameList; //список обнаруженных одноименных файлов TNameList *ExNames; //проверяемые каталоги(пути) - только указатель
TVerDirectory(TStrings * fExNames, AnsiString fPath, TDirThread * aOwner);//-конструктор ~TVerDirectory(void); //-деструктор void __fastcall Clear(void); //-очистка отчета void __fastcall Fill(void); //-главная функция для подготовки отчета bool __fastcall WorkFile(int PathNum,AnsiString Name); //-проверка файла bool __fastcall WorkDir(AnsiString Path); //-проверка каталога // (с рекурсивными вызовами для подкаталогов) void __fastcall SetNameList(TStrings * DestList); //-для передачи в оконный компонент списка одноименных файлов void __fastcall SetExNames(TStrings * DestList); //-для передачи в оконный компонент списка исключений void __fastcall SetDirList(int NameNum,TStrings * DestList);//-для передачи в оконный компонент списка путей расположения // выбранного файла (с номером NameNum в списке NameList) void __fastcall SetDirListEx(int NameNum,TStrings * DestList);//-для передачи в оконный компонент списка путей расположения // выбранного файла (с номером NameNum в списке ExNames) bool __fastcall SetEx(int Index); //передать файл из NameList в ExNames bool __fastcall ResetEx(int Index); //передать файл из ExNames в NameList }; //--------------------------------------------------------------------------- //тип - форма главного окна class TFForm: public TForm { __published: // IDE-managed Components TButton *Button1; TPopupMenu *PopupMenu1; TMenuItem *N1; TMenuItem *N2; TPanel *Panel1; TLabel *Label1; TListBox *NameBox; TLabel *Label2; TListBox *DirBox; TPanel *Panel2; TLabel *Label3; TButton *AddDirButton; TTimer *Timer1; TLabel *Label5; TListBox *ExBox; TLabel *Label4; TSpeedButton *SetExButton; TSpeedButton *ResetExButton; TTimer *Timer2; void __fastcall NameBoxClick(TObject *Sender); void __fastcall FormActivate(TObject *Sender); void __fastcall N1Click(TObject *Sender); void __fastcall FormClose(TObject *Sender, TCloseAction &Action); void __fastcall N2Click(TObject *Sender); void __fastcall Button1Click(TObject *Sender); void __fastcall Timer1Timer(TObject *Sender); void __fastcall ExBoxClick(TObject *Sender); void __fastcall AddDirButtonClick(TObject *Sender); void __fastcall SetExButtonClick(TObject *Sender); void __fastcall ResetExButtonClick(TObject *Sender); private: // User declarations void __fastcall WMShellMess(TMessage &Message); //обработчик WM_SHELLMESS void __fastcall ShowMyWin(TMessage &Message); //обработчик WM_SHOWMYWIN public: // User declarations TVerDirectory *Report; //подготовленный отчет по одноименным файлам TDirThread *DirThr; //поток проверки каталогов TNotifyThread *NotifyThr; //поток автоматического контроля каталогов TNotifyIconData NotifyData; //структура для регистрации значка в System Tray bool AppClose; //признак выхода из программы __fastcall TFForm(TComponent* Owner);//конструктор void __fastcall CallThreads(void); //создание и запуск потоков контроля и проверки каталогов void __fastcall StopThreads(void); //завершение и удаление потоков контроля и проверки каталогов BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_SHELLMESS, TMessage, WMShellMess) MESSAGE_HANDLER(WM_SHOWMYWIN, TMessage, ShowMyWin) END_MESSAGE_MAP(TForm) }; //--------------------------------------------------------------------------- extern PACKAGE TFForm *FForm; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #endif Файл FMain.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop
#include "FMain.h" #include "FSelectDirForm.h" //--------------------------------------------------------------------------- #pragma package(smart_init)
#pragma resource "*.dfm" TFForm *FForm; bool DirectoryNever; //признак необходимости перезапуска проверки каталогов void *NeverMutex, //мъютекс для синхронизации доступа к DirectoryNever (для записи) *NeverEvent; //событие для синхронизации потоков проверки файлов и контроля файлов //--------------------------------------------------------------------------- //------------------------TGlobalList,TNameList--------------------------------- int __fastcall TGlobalList::At(int Index) {return (int)Objects[Index];} TIntArray * __fastcall TNameList::At(int Index) {return (TIntArray *)Objects[Index];} //--------------------------------------------------------------------------- //------------------------TVerDirectory---------------------------------------- TVerDirectory::TVerDirectory(TStrings * fExNames, AnsiString fPath, TDirThread * aOwner) { Path=fPath; Owner=aOwner; DirList= new TStringList(); GlobalList = new TGlobalList(); GlobalList->Sorted=true; NameList = new TNameList(); NameList->Sorted=true; ExNames = new TNameList(); ExNames->Sorted=true; ExNames->AddStrings(fExNames); } //--------------------------------------------------------------------------- TVerDirectory::~TVerDirectory(void) { Clear(); delete DirList; delete GlobalList; delete NameList; delete ExNames; } //--------------------------------------------------------------------------- void __fastcall TVerDirectory::Clear(void) { for(int i=0; i<NameList->Count;i++) delete NameList->At(i); for(int i=0; i<ExNames->Count;i++) if (ExNames->At(i)!= NULL) { delete ExNames->At(i); ExNames->Objects[i]=NULL; } NameList->Clear(); GlobalList->Clear(); DirList->Clear(); } //--------------------------------------------------------------------------- //главная функция для проверки каталогов и подготовки отчета //если проверка была прервана в связи с изменением состава файлов (взведен DirectoryNever)- //проверка начинается сначала. //если проверка была прервана в связи с завершением родительского потока - выход из функции void __fastcall TVerDirectory::Fill(void) { bool cc=true; while (!Owner->Term() && cc) { //проверка cc=!WorkDir(Path); if(cc) { Clear(); WaitForSingleObject(NeverMutex,INFINITE); DirectoryNever=false; ReleaseMutex(NeverMutex); } } } //--------------------------------------------------------------------------- //проверка-регистрация в отчете файла (по имени и номеру подкаталога) //при изменении состава файлов(взведен DirectoryNever) или при завершении //родительского потока - досрочный выход с результатом - false bool __fastcall TVerDirectory::WorkFile(int PathNum,AnsiString Name) { //выход при необходимости if (DirectoryNever || Owner->Term()) return false; int i, j,k; TIntArray *T;
j=ExNames->IndexOf(Name); if(j>=0)//имя в списке исключений { if(ExNames->At(j) == NULL) {//создать массив T = new TIntArray(3); ExNames->Objects[j]=(TObject *)T; } (ExNames->At(j))->Add(PathNum);//добавить номер каталога } else { i=GlobalList->IndexOf(Name); if(i>=0)//такой файл уже есть { j = NameList->IndexOf(Name); if(j>=0) (NameList->At(j))->Add(PathNum);//добавить номер каталога в массив else { //создать и заполнить массив номеров каталогов T = new TIntArray(3); T->Add(GlobalList->At(i)); T->Add(PathNum); //включить файл в список одинаковых NameList->AddObject(Name,(TObject *)T); } } else GlobalList->AddObject(Name,(TObject *)PathNum);//включить файл в общий список } //выход return true; } //--------------------------------------------------------------------------- //проверка-регистрация в отчете каталога (а также его содержимого, для подкаталогов - рекурсивные вызовы) //при изменении состава файлов(взведен DirectoryNever) или при завершении //родительского потока - досрочный выход с результатом - false bool __fastcall TVerDirectory::WorkDir(AnsiString Path) { //выход при необходимости if (DirectoryNever || Owner->Term()) return false; TSearchRec SRec; bool Result=true; TStringList *FList = new TStringList(),*DList= new TStringList(); FList->Sorted=true; DList->Sorted=true; //заполнить списки файлов и каталогов if(FindFirst(Path+"*.*",faAnyFile,SRec)==0) do{ if(SRec.Name!="." && SRec.Name!="..") { if (SRec.Attr & faDirectory) DList->Add(SRec.Name); else FList->Add(SRec.Name); } }while(FindNext(SRec)==0); FindClose(SRec); //обработка себя самого DirList->Add(Path); //обработка файлов for(int i=0;i<FList->Count;i++) if(!WorkFile(DirList->Count-1,FList->Strings[i])) {Result=false;break;} delete FList; //обработка подкаталогов if(Result) for(int i=0;i<DList->Count;i++) if (!WorkDir(Path+DList->Strings[i]+"\\")) {Result=false;break;}; delete DList; //выход return Result; } //--------------------------------------------------------------------------- void __fastcall TVerDirectory::SetNameList(TStrings * DestList) { DestList->Clear(); for(int i=0;i<NameList->Count;i++) DestList->Add(NameList->Strings[i]); } //--------------------------------------------------------------------------- void __fastcall TVerDirectory::SetExNames(TStrings * DestList) { DestList->Clear(); for(int i=0;i<ExNames->Count;i++) DestList->Add(ExNames->Strings[i]); } //--------------------------------------------------------------------------- void __fastcall TVerDirectory::SetDirList(int NameNum,TStrings * DestList) { DestList->Clear(); for(int i=0;i<NameList->At(NameNum)->Count;i++) DestList->Add(DirList->Strings[NameList->At(NameNum)->Items[i]]); } //--------------------------------------------------------------------------- void __fastcall TVerDirectory::SetDirListEx(int NameNum,TStrings * DestList) { DestList->Clear(); if (ExNames->At(NameNum) == NULL) DestList->Add("ФАЙЛ ОТСУТСТВУЕТ"); else for(int i=0;i<ExNames->At(NameNum)->Count;i++) DestList->Add(DirList->Strings[ExNames->At(NameNum)->Items[i]]); } //--------------------------------------------------------------------------- bool __fastcall TVerDirectory::SetEx(int Index) { if(Index>=0 && Index<NameList->Count) { ExNames->AddObject(NameList->Strings[Index],NameList->Objects[Index]); NameList->Delete(Index); return true; } else return false; } //--------------------------------------------------------------------------- bool __fastcall TVerDirectory::ResetEx(int Index) { if(Index>=0 && Index<ExNames->Count) { if(ExNames->At(Index)==NULL) { if(Application->MessageBoxA(((AnsiString)"Выбранный файл отсутствует в контролируемом каталоге.\n"+ "Удалить его из списка исключений?").c_str(),"Предупреждение",MB_YESNO | MB_ICONWARNING)==IDYES) { ExNames->Delete(Index); return true; } } else if(ExNames->At(Index)->Count==1) { if(Application->MessageBoxA(((AnsiString)"Выбранный файл в контролируемом каталоге присутствует в единственном числе.\n"+ "Удалить его из списка исключений?").c_str(),"Предупреждение",MB_YESNO | MB_ICONWARNING)==IDYES) { delete ExNames->At(Index); ExNames->Delete(Index); return true; } } else { NameList->AddObject(ExNames->Strings[Index],ExNames->Objects[Index]); ExNames->Delete(Index); return true; } } return false; } //--------------------------------------------------------------------------- //------------------------------TDirThread-------------------------------------- //включает мигание надписи "Запущена проверка" void __fastcall TDirThread::CheckStep(void) { FForm->Timer1->Enabled=true; FForm->Label5->Visible=true; } //--------------------------------------------------------------------------- //передает подготовленный отчет главному окну программы //(с открытием и активизацией главного окна) void __fastcall TDirThread::SetLists(void) { //отключить мигание надписи "Запущена проверка" FForm->Timer1->Enabled=false; FForm->Label5->Visible=false;
TVerDirectory *OldReport=FForm->Report; bool First=(OldReport == NULL);//First=true при подготовке потоком первого отчета FForm->Report=Report; //передача нового отчета //настройка оконных компонентов под новый отчет FForm->Report->SetNameList(FForm->NameBox->Items); FForm->ExBox->ItemIndex=-1; FForm->DirBox->Clear(); FForm->SetExButton->Enabled=false; FForm->ResetExButton->Enabled=false; if(Report->NameList->Count>0) FForm->Panel2->Caption="Обнаружены одноименные файлы!"; else FForm->Panel2->Caption="Одноименные файлы отсутствуют."; //открытие и активизация главного окна приложения if(!First && (Report->NameList->Count>0 || OldReport->NameList->Count>0)) if(FForm->Visible) { //Второй запуск самого себя - только такой путь, чтобы вытащить окно на передний //план (SetForegroundWindow из другого процесса) WinExec(ParamStr(0).c_str(),SW_SHOWNORMAL); } else {//открыть окно ShowWindow(Application->Handle, SW_SHOW); FForm->Show(); } if(!First) delete OldReport; //удалить старый отчет //при подг-ке первого отчета (одноименных файлов нет) - скрыть окно через 2 сек. else if (Report->NameList->Count==0) FForm->Timer2->Enabled=true; } //--------------------------------------------------------------------------- //главная функция потока проверки файлов //первую проверку выполняет безусловно, последующие проверки - по взводу //события NeverEvent (от потока контроля) void __fastcall TDirThread::Execute() { while(!Terminated) { //создать Report Report=new TVerDirectory(FForm->ExBox->Items,FForm->AddDirButton->Caption,this); //сбросить DirectoryNever WaitForSingleObject(NeverMutex,INFINITE); DirectoryNever=false; ReleaseMutex(NeverMutex); //отметить начало проверки Synchronize(CheckStep); //проверка Report->Fill(); if (!Terminated)//если поток не завершен { //передать отчет главному окну Synchronize(SetLists); //ожидание взвода события NeverEvent WaitForSingleObject(NeverEvent,INFINITE); } else delete Report;//удаление отчета при завершении потока } } //--------------------------------------------------------------------------- //------------------------------TNotifyThread-------------------------------------- //функция потока автоматического контроля файлов каталогов (переименование, добавление, удаление файлов) //работает через механизм FindFirstChangeNotification - FindNextChangeNotification. //предусмотрен механизм завершения потока - по взводу события NeverEvent void __fastcall TNotifyThread::Execute() { THandleArray Handles=THandleArray(2); HANDLE Handle; int i; unsigned int Num; Handles.Add(NeverEvent); //поставить каталог на контроль, получить дескриптор ожидания Handle=FindFirstChangeNotification(FForm->AddDirButton->Caption.c_str(), true,FILE_NOTIFY_CHANGE_FILE_NAME); if (Handle!=INVALID_HANDLE_VALUE) Handles.Add(Handle);
while(!Terminated) { //ожидание событий (NeverEvent или Handles[1..Handles.Count-1]) Num=WaitForMultipleObjects(Handles.Count,&(Handles[0]),false,INFINITE); if(Num==WAIT_OBJECT_0)//взвод события NeverEvent - предполагается завершение потока {}else if(Num>WAIT_OBJECT_0 && Num<WAIT_OBJECT_0+Handles.Count) { //взвод Handles[1..Handles.Count-1] - изменение файлов одного из каталогов Num-=WAIT_OBJECT_0;//номер сработавшего HANDLE Sleep(100);//подождать 100 мс //взвести DirectoryNever (для перезапуска проверки, если проверка (в другом потоке) еще не закончена) WaitForSingleObject(NeverMutex,INFINITE); DirectoryNever=true; ReleaseMutex(NeverMutex); //взвести-сбросить событие NeverEvent (для запуска проверки в потоке проверки файлов) PulseEvent(NeverEvent); //снова поставить сработавший каталог на контроль if(!FindNextChangeNotification(Handles[Num])) { //если на проверку не ставится FindCloseChangeNotification(Handles[Num]); Handles.Delete(Num); } } } //освободить дескрипторы ожидания for(i=1;i<Handles.Count;i++) FindCloseChangeNotification(Handles[i]); }
//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //-------------------------------TFForm-------------------------------------------- //конструктор формы __fastcall TFForm::TFForm(TComponent* Owner) : TForm(Owner) { Report=NULL; AppClose=false; } //--------------------------------------------------------------------------- //обновляет содержимое списка DirBox при выборе файла в списке NameBox void __fastcall TFForm::NameBoxClick(TObject *Sender) { if(Report && NameBox->ItemIndex>=0) Report->SetDirList(NameBox->ItemIndex,DirBox->Items); SetExButton->Enabled=(NameBox->Items->Count>0 && NameBox->ItemIndex>=0); ResetExButton->Enabled=(ExBox->Items->Count>0 && ExBox->ItemIndex>=0); } //--------------------------------------------------------------------------- //обновляет содержимое списка DirBox при выборе файла в списке ExBox void __fastcall TFForm::ExBoxClick(TObject *Sender) { if(Report && ExBox->ItemIndex>=0) Report->SetDirListEx(ExBox->ItemIndex,DirBox->Items);
SetExButton->Enabled=(NameBox->Items->Count>0 && NameBox->ItemIndex>=0); ResetExButton->Enabled=(ExBox->Items->Count>0 && ExBox->ItemIndex>=0); } //--------------------------------------------------------------------------- //создание запуск потоков проверки и контроля файлов каталогов void __fastcall TFForm::CallThreads(void) { DirectoryNever=false; DirThr=new TDirThread(false); NotifyThr=new TNotifyThread(false); } //--------------------------------------------------------------------------- //остановка и удаление потоков проверки и контроля файлов каталогов void __fastcall TFForm::StopThreads(void) { //взвести Terminated у обоих потоков NotifyThr->Terminate(); DirThr->Terminate(); //взвести-сбросить событие NeverEvent для завершения потоков (для выхода из функций ожидания) PulseEvent(NeverEvent); DirThr->WaitFor();//дождаться завершения потока DirThr delete DirThr; //удалить DirThr NotifyThr->WaitFor();//дождаться завершения потока NotifyThr delete NotifyThr; //удалить NotifyThr //отключить мигание надписи "Запущена проверка" Timer1->Enabled=false; Label5->Visible=false; } //--------------------------------------------------------------------------- //обработчик OnActivate формы (работает только при запуске программы) //регистрирует значок в System Tray, инициализирует переменные, запускает потоки void __fastcall TFForm::FormActivate(TObject *Sender) { NotifyData.cbSize=sizeof(NotifyData); NotifyData.hWnd=Handle; NotifyData.uID=0; NotifyData.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP; NotifyData.uCallbackMessage=WM_SHELLMESS; NotifyData.hIcon=Application->Icon->Handle; strncpy(&(NotifyData.szTip[0]),"Контроль одноименных файлов",sizeof(NotifyData.szTip)); Shell_NotifyIcon(NIM_ADD,&NotifyData); Application->Title="Контроль файлов"; OnActivate=NULL; NeverMutex=CreateMutex(NULL,false,""); NeverEvent=CreateEvent(NULL,true,false,""); if(FileExists(ChangeFileExt(ParamStr(0),".inf")))//если есть файл параметров {//прочитать файл параметров TStringList *S=new TStringList; S->LoadFromFile(ChangeFileExt(ParamStr(0),".inf")); AddDirButton->Caption=S->Strings[0]; //контролируемый каталог for(int i=1;i<S->Count;i++) ExBox->Items->Add(S->Strings[i]);//список исключений delete S; } else AddDirButton->Caption=ExtractFilePath(ParamStr(0)); SetExButton->Enabled=(NameBox->Items->Count>0 && NameBox->ItemIndex>=0); ResetExButton->Enabled=(ExBox->Items->Count>0 && ExBox->ItemIndex>=0); CallThreads(); } //--------------------------------------------------------------------------- /* Msg.LParam= 512 - кнопки мыши не нажаты 513, 514 - нажать, отпустить левую кнопку..001,..010 516, 517 - нажать, отпустить правую кнопку..0100,..0101 519, 520 - нажать, отпустить среднюю кнопку..0111,..1000 */ //обработчик событий от значка в System Tray - //показывает всплывающее меню при щелчке мышью на значке в System Tray void __fastcall TFForm::WMShellMess(TMessage &Message) { if(Message.WParam ==0) switch(Message.LParam) { case 513: case 516:if(!SDForm->Visible) { TPoint tp; SetForegroundWindow(Handle); GetCursorPos(&tp); N1->Enabled=!Visible || IsIconic(Application->Handle); PopupMenu1->Popup(tp.x,tp.y); PostMessage(Handle,WM_NULL,0,0); } break; } } //--------------------------------------------------------------------------- //обработчик сообщения от второй копии приложения - для открытия и показа главного окна void __fastcall TFForm::ShowMyWin(TMessage &Message) { ShowWindow(Application->Handle, SW_SHOWNORMAL); Show(); } //--------------------------------------------------------------------------- //обработчик пуккта всплывающего меню "Отчет, настройки программы" //открывает и показывает главное окно void __fastcall TFForm::N1Click(TObject *Sender) { ShowWindow(Application->Handle, SW_SHOWNORMAL); Show(); } //--------------------------------------------------------------------------- //обработчик OnClose (при закрытии) формы void __fastcall TFForm::FormClose(TObject *Sender, TCloseAction &Action) { Timer2->Enabled=false; if(AppClose) {//закрытие программы разрешено - выполняет деинициализирующие действия StopThreads();//остановка-удаление потоков if(Report) delete Report; //удаление отчета CloseHandle(NeverMutex); //освобождение объектов CloseHandle(NeverEvent); // Shell_NotifyIcon(NIM_DELETE,&NotifyData); //удаление значка из System Tray //сохранение параметров в файл "FileNames.inf" TStringList *S = new TStringList(); S->Add(AddDirButton->Caption);//контролируемый каталог for(int i=0;i<ExBox->Items->Count;i++) S->Add(ExBox->Items->Strings[i]);//список исключений S->SaveToFile(ChangeFileExt(ParamStr(0),".inf")); delete S; } else {//закрытие программы запрещено - только скрывает окно Action=caNone; Hide(); ShowWindow(Application->Handle, SW_HIDE); } } //--------------------------------------------------------------------------- //обработчик пуккта всплывающего меню "Закрыть программу" //взводит признак AppClose и закрывает главное окно void __fastcall TFForm::N2Click(TObject *Sender) { if(!SDForm->Visible) { AppClose=true; Close(); } } //--------------------------------------------------------------------------- //обработчик кнопки "Скрыть окно" - скрывает главное окно void __fastcall TFForm::Button1Click(TObject *Sender) { Timer2->Enabled=false; Hide(); ShowWindow(Application->Handle, SW_HIDE); } //--------------------------------------------------------------------------- //обработчик таймера - осуществляет мигание надписи "Запущена проверка..." void __fastcall TFForm::Timer1Timer(TObject *Sender) { Label5->Visible=!Label5->Visible; } //--------------------------------------------------------------------------- //Обработчик кнопки AddDirButton - //открывает окно SDForm для смены контр-го каталога, и перезапускает потоки void __fastcall TFForm::AddDirButtonClick(TObject *Sender) { AnsiString Dir=AddDirButton->Caption; if(Dir.Length() > 3) Dir.SetLength(Dir.Length()-1); SDForm->DriveComboBox1->Drive=Dir[1]; SDForm->DirectoryListBox1->Directory=Dir; if(SDForm->ShowModal()==mrOk) { Dir=SDForm->DirectoryListBox1->Directory; if(Dir.Length() > 3) Dir=Dir+'\\'; StopThreads(); AddDirButton->Caption=Dir; CallThreads(); } } //--------------------------------------------------------------------------- //Обработчик кнопки "Стрелка вниз" - передает файл из списка одноименных в список исключений void __fastcall TFForm::SetExButtonClick(TObject *Sender) { if(Report->SetEx(NameBox->ItemIndex)) { Report->SetNameList(NameBox->Items); Report->SetExNames(ExBox->Items); DirBox->Items->Clear(); SetExButton->Enabled=false; ResetExButton->Enabled=false; if(Report->NameList->Count>0) Panel2->Caption="Обнаружены одноименные файлы!"; else Panel2->Caption="Одноименные файлы отсутствуют."; } } //--------------------------------------------------------------------------- //Обработчик кнопки "Стрелка верх" - передает файл из списка исключений в список одноименных // или удаляет файл из списка исключений void __fastcall TFForm::ResetExButtonClick(TObject *Sender) { if(Report->ResetEx(ExBox->ItemIndex)) { Report->SetNameList(NameBox->Items); Report->SetExNames(ExBox->Items); DirBox->Items->Clear(); SetExButton->Enabled=false; ResetExButton->Enabled=false; if(Report->NameList->Count>0) Panel2->Caption="Обнаружены одноименные файлы!"; else Panel2->Caption="Одноименные файлы отсутствуют."; } }
Воспользуйтесь поиском по сайту: ©2015 - 2025 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|