Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Устраняем косяки функций PathRemoveExtension и PathRenameExtension

24.10.2023 | Категория: Образ мышления: Assembler | Автор: ManHunter
В комментариях к статьям иногда проскакивают мысли, мол, зачем изобретать велосипед, если уже существуют готовые WinAPI. Ну так вот, в библиотеке shlwapi помимо кучи других полезных функций есть две функции для работы с расширениями файлов. PathRemoveExtension служит для удаления расширения из строки с путем файла, а PathRenameExtension для замены имеющегося расширения на другое. Это очень удобно в случае, когда, например, надо сгенерировать имя файла данных или файла с настройками по имени исполняемого файла. Но, к сожалению, у них есть фатальные косяки в реализации. Это проще показать на примерах. Вот удаление расширения:

c:\test\file1.txt -> PathRemoveExtension -> c:\test\file1
c:\test\file2 -> PathRemoveExtension -> c:\test\file2
c:\test\.htaccess -> PathRemoveExtension -> c:\test\
c:\test\.htaccess.bak -> PathRemoveExtension -> c:\test\.htaccess

И аналогично для замены расширения, например, на ".ini":

c:\test\file1.txt -> PathRenameExtension -> c:\test\file1.ini
c:\test\file2 -> PathRenameExtension -> c:\test\file2.ini
c:\test\.htaccess -> PathRenameExtension -> c:\test\.ini
c:\test\ -> PathRenameExtension -> c:\test\.ini
c:\test\.htaccess.bak -> PathRenameExtension -> c:\test\.htaccess.ini

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

Читать статью целиком »
Просмотров: 265 | Комментариев: 0

Как сделать перетаскиваемый курсор-прицел

21.10.2023 | Категория: Образ мышления: Assembler | Автор: ManHunter
У многих программ для работы с окнами приложений есть такая фича, как перетаскиваемый указатель-прицел, с помощью которого можно выбрать определенное окно. Когда-то у меня в комментариях спросили, как можно сделать что-то подобное. Что ж, лучше поздно, чем никогда.

Начнем с теории, как это все должно работать. На форме программы сперва рисуется значок прицела, это самая обычная статическая картинка. При клике на нее активируется процесс перетаскивания. Системный курсор меняется на этот же прицел, а значок на форме скрывается. Тем самым достигается визуальный эффект, что перетаскивается именно прицел с формы. Пока кнопка мыши нажата, обрабатываются координаты курсора и выполняются нужные действия с этой информацией. При отпускании кнопки мыши курсор меняется на дефолтный системный, а на форме снова отображается картинка. Таким образом нам надо отслеживать три сообщения окна: WM_LBUTTONDOWN для нажатия левой кнопки мыши, WM_LBUTTONUP для ее отпускания и WM_MOUSEMOVE для перемещения мыши.
  1.         cmp     [msg],WM_LBUTTONDOWN
  2.         je      .wmsetcursor
  3.         cmp     [msg],WM_LBUTTONUP
  4.         je      .wmreleasecursor
  5.         cmp     [msg],WM_MOUSEMOVE
  6.         je      .wmmousemove
Теперь разберем каждый обработчик более подробно. При нажатии левой кнопки мыши сперва проверяется координата, по которой было произведено нажатие. Если она находится внутри области, занимаемой картинкой прицела на форме, то загружается курсор, прячется картинка, как написано выше.
  1. .wmsetcursor:
  2.         ; Получить координаты события
  3.         invoke  GetMessagePos
  4.         ; Координата Y
  5.         mov     ebx,eax
  6.         shr     ebx,16
  7.         mov     [pt.y],ebx
  8.         ; Координата X
  9.         mov     ebx,eax
  10.         and     ebx,0FFFFh
  11.         mov     [pt.x],ebx
  12.  
  13.         ; Получить границы иконки
  14.         invoke  GetWindowRect,[hStatic],img
  15.  
  16.         ; Клик произошел в области иконки?
  17.         invoke  PtInRect,img,[pt.x],[pt.y]
  18.         or      eax,eax
  19.         jz      .processed
  20.  
  21.         ; Установить захват событий мыши
  22.         invoke  SetCapture,[hwnddlg]
  23.  
  24.         ; Загрузить наш курсор
  25.         invoke  SetCursor,[hCursor]
  26.  
  27.         ; Скрыть иконку на форме
  28.         invoke  SendMessage,[hStatic],STM_SETIMAGE,IMAGE_CURSOR,0
  29.  
  30.         mov     [state],1
Но главное, надо обязательно установить захват мыши для окна программы при помощи функции SetCapture. Иначе события перемещения перестанут передаваться, как только курсор покинет пределы окна. Также надо взвести флаг, что теперь выполняется перемещение прицела.

Читать статью целиком »
Просмотров: 470 | Комментариев: 2

Как отследить смену питания на ноутбуке

15.10.2023 | Категория: Образ мышления: Assembler | Автор: ManHunter

Как отследить смену питания на ноутбуке

Дополнение к статье о получении информации об оставшемся заряде батареи ноутбука. Запрос состояния батареи по мере надобности - это хорошо, но будет гораздо правильнее, если система сама будет уведомлять наше приложение об изменении типа электропитания, а также об оставшемся заряде аккумулятора. Сегодня я расскажу, как это делается.

Читать статью целиком »
Просмотров: 384 | Комментариев: 0

Конвертирование строки из КОИ-8 в cp1251 и обратно

03.10.2023 | Категория: Образ мышления: Assembler | Автор: ManHunter

Кодировка KOI8-R

КОИ-8 - код обмена информацией - восьмибитовая кодовая страница, разработанная для кодирования букв кириллических алфавитов. КОИ-8 в свое время была широко распространена как основная русская кодировка в UNIX-совместимых ОС и в электронной почте. Существует несколько вариантов КОИ-8, в этой статье я расскажу, как можно конвертировать строку из KOI8-R (русская) в стандартную виндовую кодировку cp1251 и обратно.

Читать статью целиком »
Просмотров: 496 | Комментариев: 2

Отслеживание изменения метки тома

27.09.2023 | Категория: Образ мышления: Assembler | Автор: ManHunter
Несколько лет назад я демонстрировал, как можно легко и просто отслеживать изменения в каком-нибудь каталоге. Кроме отслеживания подобных глобальных движений, система позволяет отслеживать изменения более точечно, например, на отдельных объектах файловой системы. Для этого есть функция SHChangeNotifyRegister. В качестве примера я разберу, как можно отслеживать изменение метки тома. На самом деле функция SHChangeNotifyRegister обладает гораздо более широкими возможностями по отслеживанию различных системных уведомлений.

Сперва небольшое количество данных для работы, которые отсутствуют в инклудах FASM.
  1. struct SHChangeNotifyEntry
  2.         pidl       dd ?
  3.         fRecursive dd ?
  4. ends
  5.  
  6. SHCNRF_ShellLevel  = 0x0002
  7. SFGAO_FILESYSTEM   = 0x40000000
  8. SHCNE_RENAMEFOLDER = 0x00020000
Первым делом преобразуем имя отслеживаемого файла, диска или каталога в объект, для этого вызовем функцию SHParseDisplayName. После этого надо заполнить массив отслеживаемых объектов. У нас только один объект - диск C:\, но можно добавить любое их количество.
  1.         ; Настроить отслеживаемый объект
  2.         invoke  SHParseDisplayName,szWatch,NULL,\
  3.                 pidl,SFGAO_FILESYSTEM,NULL
  4.  
  5.         ; Заполнить массив отслеживаемых объектов
  6.         mov     eax,[pidl]
  7.         mov     [shentry.pidl],eax
  8.         mov     [shentry.fRecursive],FALSE
  9.  
  10.         ; Зарегистрировать обработчик уведомлений
  11.         invoke  SHChangeNotifyRegister,\
  12.                 [hwnddlg],\
  13.                 SHCNRF_ShellLevel,\
  14.                 SHCNE_RENAMEFOLDER,\
  15.                 WM_LABEL_CHANGED,\
  16.                 1,\
  17.                 shentry
  18.         mov     [cookie],eax
  19.  
  20.         ; Освободить неиспользуемую память
  21.         invoke  CoTaskMemFree,[pidl]
Так как мы отслеживаем изменение метки тома, а метка тома по сути является разновидностью каталога, то нам достаточно типа уведомления SHCNE_RENAMEFOLDER. Но никто не мешает скомбинировать типы уведомлений для отслеживания или вообще подписаться на все подряд, указав флаг SHCNE_ALLEVENTS.

Код WM_LABEL_CHANGED - это пользовательское сообщение окну приложения, его можно описать, например, как WM_LABEL_CHANGED = WM_USER + 200. При поступлении уведомления от системы именно это сообщение будет отправлено целевому окну обработчика. В параметре lParam находится код события, что очень полезно, когда приложение подписано сразу на несколько событий.

Читать статью целиком »
Просмотров: 375 | Комментариев: 0

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 3 (0.0127 сек.) / Память: 4.5 Mb
Наверх