1. Майкл Хаймен, Боб Арнсон. Visual C++: Учеб. Пособие. – М.: Диалектика, 2002. – 289 с.: ил.
2. А. Корера, С. Фрейзер, С. Маклин, Н. Кумар, С. Робинсон, П.Г. Саранг, С. Джентайл. Visual C++. Пособие для разработчиков. Изд-во «Лори», 2003. – 417 с.: ил.
Рисунок А.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="Одноименные файлы отсутствуют.";
}
}
... объекта в виде окна. Последним действием кода главной функции является создание цикла обработки сообщений. После его создания приложение становится пассивным и начинает взаимодействовать с операционной системой посредством сообщений. Обработка поступающих сообщений осуществляется специальной функцией, называемой оконной. Особенность оконной функции заключается в том, что она вызывается из ...
... элементов, глобальное пространство имен, а также лавинообразную первоначальную загрузку сети. Таким образом ОСРВ SPOX имеет необходимые механизмы для создания отказоустойчивой распределенной операционной системы реального времени, концепция построения которой описана в главе 2. 4.3 Аппаратно-зависимые компоненты ОСРВ Модули маршрутизации, реконфигурации, голосования реализованы как аппаратно- ...
... доступа к данным препятствует как несанкционированному использованию информации, так и распространению вредоносных кодов в системе. Глава 2. Производители программного обеспечения Разумеется, многофункциональность ПК определяет не операционная система, а программное обеспечение, используемое на нем. Именно эти продукты позволяют использовать компьютер в различных производственных сферах. И, ...
... система обеспечивает совместное функционирование всех устройств ПК и предоставляет пользователю доступ к его ресурсам. WINDOWS 95, WINDOWS 98, WINDOWS ME, WINDOWS XP. Состав Операционной системы: 13) Программный модуль, управляющий файлами. 14) Командный процессор (выполняет команды пользователя). 15) Программы, обеспечивающие управление работой различных устройств (ввода, ...
0 комментариев