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="Одноименные файлы отсутствуют.";

}

}


Информация о работе «Системное программирование для операционных систем»
Раздел: Информатика, программирование
Количество знаков с пробелами: 55779
Количество таблиц: 3
Количество изображений: 6

Похожие работы

Скачать
33466
1
7

... объекта в виде окна. Последним действием кода главной функции является создание цикла обработки сообщений. После его создания приложение становится пассивным и начинает взаимодействовать с операционной системой посредством сообщений. Обработка поступающих сообщений осуществляется специальной функцией, называемой оконной. Особенность оконной функции заключается в том, что она вызывается из ...

Скачать
148576
34
0

... элементов, глобальное пространство имен, а также лавинообразную первоначальную загрузку сети. Таким образом ОСРВ SPOX имеет необходимые механизмы для создания отказоустойчивой распределенной операционной системы реального времени, концепция построения которой описана в главе 2. 4.3 Аппаратно-зависимые компоненты ОСРВ Модули маршрутизации, реконфигурации, голосования реализованы как аппаратно- ...

Скачать
57423
0
0

... доступа к данным препятствует как несанкционированному использованию информации, так и распространению вредоносных кодов в системе. Глава 2. Производители программного обеспечения Разумеется, многофункциональность ПК определяет не операционная система, а программное обеспечение, используемое на нем. Именно эти продукты позволяют использовать компьютер в различных производственных сферах. И, ...

Скачать
216821
0
4

... система обеспечивает совместное функционирование всех устройств ПК и предоставляет пользователю доступ к его ресурсам. WINDOWS 95, WINDOWS 98, WINDOWS ME, WINDOWS XP. Состав Операционной системы: 13)      Программный модуль, управляющий файлами. 14)      Командный процессор (выполняет команды пользователя). 15)      Программы, обеспечивающие управление работой различных устройств (ввода, ...

0 комментариев


Наверх