Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Новости ИТ Программы Книги Games   Обои   Экспорт RSS E-Books
 
Поиск по сайту

TOP-10 программ
Symantec Norton Ghost 9.0
Partition Magic 8.0.2 Pro
Xilisoft 3GP Video Converter v3.1.7.0616b
Norton AntiVirus 2005
Xilisoft 3GP Video Converter v2.1.52.831b
Антивирус Касперского Personal 5.0.303 beta 2
RAR Password Cracker 4.12
ABBYY PDF Transformer v1.00.820
MP3 To Ringtone Gold v3.02
Mobtime Cell Phone Manager v5.3.1
 
Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
 
 

   Программирование -> C / C++ -> Когда измененяются папки


Когда измененяются папки

Перевод А.И. Легалова, SoftCraft


Англоязычный оригинал находится на сервере компании Reliable Software


Вы когда-либо задались вопросом: каким оразом Проводник (Explorer) узнает о том, что некоторое действие должно модифицировать его окно, потому что был добавлен или удален файл в текущей папке некоторым внешним приложением? Больше этому можно не удивляться, потому что использование нашего Активного Объекта позволяет делать то же самое и даже больше. Есть несколько простых вызовов API, с помощью которых Вы можете запросить у файловой системы, чтобы она избирательно сообщила Вам относительно изменений для файлов и папок. Как только Вы устанавливаете такую вахту, ваш поток может отправляться спать, ожидая прихода событий. Файловая система отреагирует на событие, как только она обнаружит вид изменения, за которым вы наблюдаете.

Загрузка исходных текстов приложения FolderWatcher (zip архив 11K).


Без дальнейшей суеты унаследуем FolderWatcher из ActiveObject. Зададим в качестве источника уведомления - событие, а в каяестве приемника уведомления - дескриптор к окна, отвечающего на уведомление. Исходное событие установлено в конструкторе FolderWatcher. Важно также запустить удерживаемый поток в конце конструктора.



class FolderWatcher : public ActiveObject

{

public:

    FolderWatcher (char const * folder, HWND hwnd)

        : _notifySource (folder),

          _hwndNotifySink (hwnd)

    {

        strcpy (_folder, folder);

        _thread.Resume ();

    }

    ~FolderWatcher ()

    {

        Kill ();

    }



private:

    void InitThread () {}

    void Loop ();

    void FlushThread () {}



    FolderChangeEvent _notifySource;

    HWND _hwndNotifySink;

    char _folder [MAX_PATH];

};

Все действия в ActiveObject происходят внутри метода Loop. Здесь мы устанавливаем "бесконечный" цикл, в котором поток должен ожидать событие. Когда событие происходит, мы проверяем флажок _isDying (как обычно) и посылаем специальное сообщение WM_FOLDER_CHANGE окну, которое имеет дело с уведомлениями. Это - не предопределенное сообщение Windows. Оно специально определено нами для передачи уведомления о папке от одного потока другому.

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



UINT const WM_FOLDER_CHANGE = WM_USER;



void FolderWatcher::Loop ()

{

    for (;;)

    {

        // Wait for change notification

        DWORD waitStatus = WaitForSingleObject (_notifySource, INFINITE);

        if (WAIT_OBJECT_0 == waitStatus)

        {

            // If folder changed

            if (_isDying)

                return;



            PostMessage (_hwndNotifySink,

                          WM_FOLDER_CHANGE,

                          0,

                          (LPARAM) _folder);



            // Continue change notification

            if (!_notifySource.ContinueNotification ())

            {

                // Error: Continuation failed

                return;

            }

        }

        else

        {

            // Error: Wait failed

            return;

        }

    }

}

Рассмотрим, что происходит в оконной процедуре в ответ на наше специальное сообщение. Мы вызываем метод Контроллера OnFolderChange. Этот метод может делать все, что мы захотим. В Проводнике (Explorer) он регенерирует отображение содержимого папки, которую мы наблюдаем. В нашем примере он только вызывает простое окно сообщения. Обратите внимание, что мы передаем имя измененной папки как LPARAM. Совершенно неважно, как определить WPARAM и LPARAM, в сообщении, определяемом пользователем .

Между прочим, Наблюдатель Папки - только часть Контроллера.



    case WM_FOLDER_CHANGE:

        pCtrl->OnFolderChange (hwnd, (char const *) lParam);

        return 0;





void Controller::OnFolderChange (HWND hwnd, char const * folder)

{

    MessageBox (hwnd, "Change Detected, "Folder Watcher",

                 MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);

}



class Controller

{

public:

    Controller(HWND hwnd, CREATESTRUCT * pCreate);

    ~Controller ();

    void    OnFolderChange (HWND hwnd, char const *folder);



private:

    FolderWatcher _folderWatcher;

};

Теперь, когда мы знаем, как иметь дело с уведомлением, давайте взглянем на их источники, События изменяющие файлы. Объект события создан файловой системой в ответ на FindFirstChangeNotification. Дескриптор этого события возвращен из вызова. Мы запоминаем этот дескриптор и используем его позже, чтобы или осуществить восстанавление или отказаться от нашего интереса к дальнейшим уведомлениям. Обратите внимание, что мы можем устанавливать наблююдение рекурсивно, то есть, наблюдать данную папку и все ее подпапки и под-подпапки. Мы можем также выражать интерес к специфическим изменениям, передавая поразрядное ИЛИ для любой комбинации следующих флажков:

  • FILE_NOTIFY_CHANGE_FILE_NAME (переименование, создание или удаление файла)
  • FILE_NOTIFY_CHANGE_DIR_NAME (создание или удаление каталога (папки))
  • FILE_NOTIFY_CHANGE_ATTRIBUTES
  • FILE_NOTIFY_CHANGE_SIZE
  • FILE_NOTIFY_CHANGE_LAST_WRITE (сохранение файла)
  • FILE_NOTIFY_CHANGE_SECURITY

Для удобства мы определили несколько подклассов от FileChangeEvent, которые соответствуют к некоторым полезным комбинациям этих флажков. Один из них - FolderChangeEvent, который мы использовали в нашем FolderWatcher.





class FileChangeEvent

{

public:

    FileChangeEvent(char const *folder, BOOL recursive, DWORD notifyFlags)

    {

        _handle = 

            FindFirstChangeNotification (folder, recursive, notifyFlags);

        if (INVALID_HANDLE_VALUE == _handle)

           throw WinException("Cannot create change notification handle");

    }

    ~FileChangeEvent ()

    {

        if (INVALID_HANDLE_VALUE != _handle)

            FindCloseChangeNotification (_handle);

    }



    operator HANDLE () const { return _handle; }

    BOOL ContinueNotification ()

    {

        return FindNextChangeNotification (_handle);

    }



private:

    HANDLE _handle;

};



class FolderChangeEvent : public FileChangeEvent

{

public:

    FolderChangeEvent (char const * folder)

        : FileChangeEvent (folder, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME)

    {}

};



class TreeChangeEvent : public FileChangeEvent

{

public:

    TreeChangeEvent (char const * root)

        : FileChangeEvent (root, TRUE,

                           FILE_NOTIFY_CHANGE_FILE_NAME

                         | FILE_NOTIFY_CHANGE_DIR_NAME)

    {}

};

Должно быть теперь просто обобщить этот пример, чтобы сделать некоторую действительно полезную работу в ваших программах. Не забудьте посмотреть API, который мы используем в этих обучающих программах, в интерактивной справке, которая идет с вашим компилятором.



 
Популярные книги

Технология программирования на C++. Начальный курс

Подробнее

Photoshop CS2. Настоящий самоучитель

Подробнее

SQL для "чайников", 5-е издание

Подробнее

 

 
Новости ИТ
01.12.2008  Buffalo выпустил миниатюрные USB-накопители
01.12.2008  VENTO TA-U1 - стильный корпус представлен Asus
01.12.2008  Fujitsu-Siemens выпускает в продажу внешний ускоритель для ноутбуков
01.12.2008  Оригинальные чехлы для ноутбуков от Choiix
01.12.2008  Опубликован код драйвера для беспроводных карт Atheros
01.12.2008  Лучший блог 2008
01.12.2008  Linux запустили на Apple iPhone
01.12.2008  LG KC780
01.12.2008  MSI дополнит линейку Wind-нетбуков двумя моделями
01.12.2008  Nikon D3X - 24,5 млн пикселей для профессионалов
01.12.2008  Киловаттник HIPER M1000 с КПД выше 85%
01.12.2008  AMD впервые снизила цены линейки Radeon HD 4800
01.12.2008  Чистильщики: Wise Registry Cleaner v.3.8.2
01.12.2008  Антивирусы: RemoveIT Pro v4 SE (30.11.2008)
01.12.2008  Корпус ASUS Vento TA-U1 можно поставить вместо новогодней ёлки
01.12.2008  Диагностика: PC Wizard 2008 v.1.871
01.12.2008  Диагностика: NextSensor v.2.7.6.0 Build 1130
01.12.2008  Тестовые приложения: PassMark BurnInTest v.6.0 Build 1000 Beta 15
01.12.2008  Неофициальные драйверы для модемов Motorola
01.12.2008  Драйверы и утилиты для сетевых хранилищ D-Link
 
Полезно

 
Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100