Смекни!
smekni.com

Системное программирование для операционных систем (стр. 5 из 5)

//события 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);

}

elsedeleteReport;//удаление отчета при завершении потока

}

}

//---------------------------------------------------------------------------

//------------------------------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=newTNotifyThread(false);

}

//---------------------------------------------------------------------------

//остановка и удаление потоков проверки и контроля файлов каталогов

void __fastcall TFForm::StopThreads(void)

{

//взвести Terminated у обоих потоков

NotifyThr->Terminate();

DirThr->Terminate();

//взвести-сбросить событие NeverEvent для завершения потоков (для выхода из функций ожидания)

PulseEvent(NeverEvent);

DirThr->WaitFor();//дождаться завершения потока DirThr

deleteDirThr; //удалить DirThr

NotifyThr->WaitFor();//дождаться завершения потока NotifyThr

deleteNotifyThr; //удалить NotifyThr

//отключить мигание надписи "Запущена проверка"

Timer1->Enabled=false;

Label5->Visible=false;

}

//---------------------------------------------------------------------------

//обработчик OnActivate формы (работает только при запуске программы)

//регистрирует значок в SystemTray, инициализирует переменные, запускает потоки

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

*/

//обработчик событий от значка в SystemTray -

//показывает всплывающее меню при щелчке мышью на значке в SystemTray

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 __fastcallTFForm::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) deleteReport; //удаление отчета

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"));

deleteS;

}

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+'&bsol;';

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="Обнаружены одноименные файлы!";

elsePanel2->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="Обнаружены одноименные файлы!";

elsePanel2->Caption="Одноименные файлы отсутствуют.";

}

}