Меню Новости Программы Статьи Форум Контакты

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Статьи
 

СтатьиПрограммированиеDelphi

 

SysListView32. Сортировка своими руками

Автор: Blacksus

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

Сразу оговорюсь, что пример рассматриваемый в данной статье подходит только для WindowsXP, у Windows Vista и Windows 2000 немного другая структура иерархии окон на пути к SysListView32.

Большая часть кода будет располагаться в DLL, поэтому для начала создадим ее (File - New - Other - DLL Wizard).

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

Рассмотрим код поближе. Если нам нужно установить ловушку, то при помощи функции SetWindowsHookEx устанавливаем ее. В качестве параметров функция принимает тип ловушки, в нашем случае WH_GETMESSAGE, что означает перехват сообщений. Следующий параметр является ссылкой на процедуру, которая будет вызываться каждый раз при срабатывании ловушки. Следующий параметр определяет DLL, в которой располагается функция обработки ловушки. И последний параметр определяет поток, в котором расположена функция. Функция вернет хэндл созданной ловушки, если удалось создать ее, либо вернет 0 при неудаче. Далее мы проверяем возвращенное значение и выдаем соответствующее сообщение.
Если нам нужно снять ловушку, то используем функцию UnhookWindowsHookEx, которая в качестве параметра принимает хэндл ловушки и возвращает True при удачном снятии ловушки или False при неудаче. Проверяем это значение и выдаем соответствующее сообщение.

Вышеописанную процедуру нужно экспортировать из DLL, для этого в самом конце нужно добавить код:

Далее рассмотрим код функции, которая вызывается при срабатывании ловушки:

Сначала нужно вызвать следующую ловушку, т.е. передать ей управление, пока мы тут будем обрабатывать свои данные. Если код равен HC_ACTION, значит мы можем обработать это сообщение. Далее проверяем, чтобы это сообщение было то, которое нам нужно, а именно WM_REFRESH. Стоит отметить, что WM_REFRESH это не стандартная системная константа, а программно заданная:

Это внутреннее сообщение проводника. Не стоит вдаваться в подробности, каким именно образом это сообщение было отсеяно из сотни других, конечно, это было не легко :).
Далее выделяем из сообщения хэндл окна, которое его послало. При помощи этого хэндла узнаем процесс, открываем его и получаем имя его файла. Проверяем что имя файла explorer.exe. Если это так, то получаем хэндл на SysListView32 этого окна:

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

Далее рассмотрим саму функцию сортировки:

Эта функция имеет 3 параметра: lParam1 - ссылка на первый элемент, lParam2 - ссылка на второй элемент, lParamSort - программно заданное значение, которое передается в функцию сортировки. Оно задается при посылке сообщения о сортировке и обычно говорит о виде сортировки, но т.к. у нас только сортировка по имени, то мы его не используем.
Так же эта функция должна возвратить результат. Она возвращает 0, если элементы не нужно менять местами, положительное значение, если первый элемент должен быть впереди второго, и отрицательное значение, если первый элемент должен быть позади второго.
Вначале обнуляем и заполняем структуру, которая будет передана в функцию поиска элемента. Затем при помощи этой функции находим индекс элемента, а по индексу его имя. Делаем тоже самое для поиска второго элемента. Переводим оба элемента в верхний регистр. Выбираем самый короткий элемент, чтобы использовать его длину в цикле сравнения. Присваиваем результату 0, т.е. по-умолчанию оставляем элементы на их местах. Далее в цикле проверяем оба элемента посимвольно до первого различия, и, исходя из этой проверки, присваиваем результату положительное или отрицательное значение.

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

Теперь в DLL надо добавить глобальные переменные:

и на этом создание DLL можно закончить. Сохраняем, компилируем ее и переименовываем файл в "AutoSortByName.dll".

Теперь перейдем к созданию программы, которая будет использовать эту библиотеку.

В разделе implementation указываем экспортируемую функцию:

В этом примере я сделал так, что при запуске программы форма скрывается, а ловушка устанавливается автоматически. Для снятия ловушки или показа окна программы используются горячие клавиши. Естественно, что я так же сделал "облегченную" версию примера, в которой ловушка устанавливается и снимается по нажатию на кнопку.

Рассмотрим более сложную и красивую версию примера.

Для события OnShow формы указываем следующий код:

Это таймер, который будет скрывать форму через 10 миллисекунд. Он сделан потому, что свойство Visible у формы нельзя менять при событии OnShow. Вот код самого таймера:

Этот таймер при срабатывании останавливает себя, а затем скрывает форму.

Код при создании формы:

В этой процедуре регистрируем 2 горячие клавиши, затем устанавливаем ловушку.

Код при уничтожении формы:

При уничтожении формы удаляем горячие клавиши и снимаем ловушку.

Так же нужно добавить процедуру, наследуемую от TForm, которая будет принимать сообщения, посланные форме:

Проверяем, что это сообщение о нажатии горячей клавиши. Далее проверяем, если нажата комбинация Ctrl+X, то закрываем приложение, а если нажаты Ctrl+S, то показываем окно.

Теперь сохраняем проект, компилируем и запускам. При открытии любой папки или при нажатии в этой папке кнопки обновления F5, все элементы отсортируются по имени. Важно отметить, что элементы сортируются независимо от того файл это или папка.

Полная версия примера:

Исходный код примера можно скачать тут, а программу тут.

"Облегченная" версия примера:

Исходный код примера можно скачать тут, а программу тут.

   

Сайт создан в системе uCoz