Универсальный конвертер текста 1.0
Очередной релиз от меня – программка для конвертации текста в разные представления и вычисления хэшей, написанная на ассемблере (masm32).
Имеется быстрое копирование и вставка текста, сохранение и открытие текстовых файлов.
Поддерживает конвертацию:
* Text -> URLEncode
* Text -> String.fromCharCode (ascii)
* Text -> String.fromCharCode (utf)
* Text -> base64
* Text -> MySQL char
* Text -> HEX
* Text -> BIN
* Text -> chr()
* Text -> MSSQL char
* Text -> PostgreSQL
* Text -> MD5
* Text -> SHA1
* Text -> &#xxx; (ascii)
* Text -> &#xxx; (utf)
* Text -> \xhh
* Text -> %XX
* Text -> VB chr$()
* Text -> C# (char)
* Text -> Транслит
* URLEncoded -> Text
* base64 -> Text
Скриншот:
Скачать exe (10кб) и исходные коды: ZIP
В общем исходный код программки ничем не отличается от тех, что я выкладывал раньше, но есть несколько интересных особенностей, которые я опишу дальше.
Я рассмотрю:
[+] как создавать формы в стиле XP (современный вид элементов управления) с помощью программы ResEd
[+] как создавать и использовать в программе Unicode-строки, в том числе на русском языке
[+] как делать всплывающие подсказки к текстовым полям
[+] как использовать Windows CryptoAPI для генерации хэшей
[+] как использовать буфер обмена Windows для копирования и вставки текста
Напомню, что я использую в коде некоторые удобные макросы из файла macros/macros.asm, входящего в пакет masm32.
1. Как создавать формы в стиле XP (современный вид элементов управления) с помощью программы ResEd?
ResEd – маленькая бесплатная утилита для удобного создания файлов ресурсов.
Скачать его можно отсюда: ResEd.
Открываем редактор, создаем новый проект (File – New Project), добавляем к нему новое диалоговое окно (Project – Add Dialog).
Устанавливаем желаемые параметры окна во вкладке справа внизу, добавляем необходимые элементы управления, устанавливаем их параметры.
Чтобы все элементы выглядели в стиле XP, нужно добавить XP Manifest (Project – Add XP Manifest).
Сохраняем проект – получаем два файла – сам проект *.rc и манифест (xpmanifest.xml).
После того, как мы сохранили проект и вышли из редактора, надо немного подготовить файл ресурсов перед его использованием.
Открываем файл ресурсов (*.rc) в блокноте и добавляем в начало строку:
#include "\masm32\include\resource.h"
После этого удаляем строку (необязательно, но без этого у меня проект не запускался):
#define имя_нашей_формы 1000
Сохраняем файл – он готов к использованию в проекте.
Как же скомпилировать исходный код в asm вместе с файлом ресурсов в exe?
Для этого я использовал такой bat-файл (допустим, назовем его COMPILE.bat):
@echo off cls SET PATH=C:\Masm32\bin SET INCLUDE=C:\Masm32\INCLUDE SET LIB=C:\Masm32\LIB Rc.exe /v %1.rc ML /nologo -c -coff %1.asm if errorlevel 1 goto terminate LINK /nologo %1.obj %1.res /SUBSYSTEM:WINDOWS /STUB:64stub.exe /FILEALIGN:512 /VERSION:4.0 /RELEASE /BASE:0x400000 if errorLevel 1 goto terminate echo OK :terminate
Вызывается этот батник так:
– положите его в папку вместе с исходным кодом и файлом ресурсов *.rc (файлы *.rc и *.asm должны называться одинаково, например, converter.asm и converter.rc, в той же папке должен лежать xpmanifest.xml)
– в командной строке (cmd) перейдите в директорию с этими файлами (с помощью команды cd)
– выполните команду COMPILE имя_проекта (например COMPILE converter)
Если будет выведено “OK” – exe-файл был успешно создан в той же директории.
2. Как создавать и использовать в программе Unicode-строки,, в том числе и на русском языке?
В последней версии пакета masm32 имеется поддержка Unicode-строк и функций, но вот создать с его помощью русскую
Unicode-строку проблематично. Я для этого использовал набор макросов с wasm.ru, который позволяет делать русские Unicode-строки.
К сожалению, макрос создания строк содержит недостаток – каждый 120-й символ просто убирается из строки.
Я поправил недочет этого макроса, скачать исправленный можно тут: windows.asm.
Теперь, чтобы создать русскую Unicode-строку, подключаем макрос с помощью include к коду и пишем так:
.data $$$STRINGW имя_переменной,"текст" dw 0 ;терминирующие два нулевых байта ;или можно так: $$$ZSTRINGW имя_переменной,"текст"
Соответственно, такие строки сожно использовать в любых Unicode-функциях (с постфиксом W, например, MessageBoxW).
3. Как делать всплывающие подсказки к текстовым полям?
Начиная с Win XP, у элементов управления Edit появилась возможность создавать всплывающие подсказки, как на первом скриншоте, я покажу, как такое реализовать.
Для показа такой подсказки необходимо послать текстовому полю сообщение EM_SHOWBALLOONTIP, а самой подсказкой управляет структура EDITBALLOONTIP.
Странно, но в inc-файлах масма32 такой структуры не оказалось, поэтому приходится задавать ее самим:
EDITBALLOONTIP STRUCT cbStruct dd ? ;размер структуры в байтах = 16 pszTitle dd ? ;указатель на Unicode-строку с заголовком pszText dd ? ;указатель на Unicode-строку с текстом ttiIcon dd ? ;иконка структуры - TTI_INFO, TTI_WARNING, TTI_ERROR, TTI_NONE или TTI_INFO_LARGE, TTI_WARNING_LARGE, TTI_ERROR_LARGE EDITBALLOONTIP ENDS
Далее, если у нас есть Edit-контрол с id=1003, то отобразить подсказку можно так:
.data $$$STRINGW pszTitle,"Заголовок" ;эти макросы описаны в п.2 dw 0 $$$STRINGW pszText,"Текст подсказки" dw 0 .data? btt EDITBALLOONTIP <> .code mov btt.pszTitle,offset ;заполняем структуру mov btt.pszText,offset pszText mov btt.ttiIcon,TTI_INFO mov btt.cbStruct,16 invoke SendDlgItemMessage,hWnd,1004,EM_SCROLLCARET,0,0 ;скроллим поле ввода, чтобы была видна каретка - подсказка отображается именно в этом месте invoke SendDlgItemMessage,hWnd,1004,EM_SHOWBALLOONTIP,0,offset btt ;отображаем подсказку
4. Как использовать Windows CryptoAPI для генерации хэшей?
Для примера я покажу, как генерировать хэши MD5 и SHA1 для заданных строк.
Во-первых, для работы с крипто апи необходимо подключить inc-файл advapi32.inc и lib-файл advapi32.lib.
Приведу пример с комментариями из кода конвертора:
;здесь я определяю типы данных и константы, которых почему-то не оказалось в windows.inc HCRYPTHASH equ dd HCRYPTPROV equ dd ALG_CLASS_HASH equ 32768 ;... .data? ;в секции неинициализированных данных определяю несколько переменных hHash HCRYPTHASH ? hProv HCRYPTPROV ? hash_size dd ? ;сюда будет возвращаться размер хэша hash db 41 dup(?) ;а сюда сам хэш ;... .code ;... .if eax==9 || eax==10 ;если мы генерируем MD5 или SHA1 хэш push eax mov textlen,FUNC(lstrlen,membuf) ;записываем длину введенного текста в первое поле ввода invoke CryptAcquireContext,offset hProv, NULL, NULL, PROV_RSA_FULL, 0 ;создаем контекст для создания хэшей ;PROV_RSA_FULL как раз позволяет генерировать мд5 и sha1 (тут - подроблее). pop eax ;создаем хэш .if eax==9 ;если генерируем md5 invoke CryptCreateHash,hProv,CALG_MD5,0,0,offset hHash ;тут мы указываем провайдер для криптования - hProv, для которого ранее создали контекст .else ;если sha1 invoke CryptCreateHash,hProv,CALG_SHA1,0,0,offset hHash .endif invoke CryptHashData,hHash,membuf,textlen,0 ;генерируем хэш из строки в памяти membuf с длиной textlen invoke CryptGetHashParam,hHash,HP_HASHSIZE,offset hash_size,offset dwSize,0 ;получаем длину хэша invoke CryptGetHashParam,hHash,HP_HASHVAL,offset hash,offset hash_size,0 ;получаем его значение invoke CryptDestroyHash,hHash ;удаляем хэш invoke CryptReleaseContext,hProv,0 ;освобождаем контекст mov esi,membuf2 mov edi,offset hash mov ecx,0 hash_get: ;начинаем преобразовывать хэш в приемлемый текстовый вид push ecx movzx eax,byte ptr [edi] invoke wsprintf,esi,chr$("%2.2x"),eax inc edi add esi,2 pop ecx inc ecx cmp ecx,hash_size jne hash_get ;теперь в памяти membuf2 содержится хэш в текстовом виде, и его можно вывести или использовать по своему усмотрению
5. Как использовать буфер обмена Windows для копирования и вставки текста?
Опять-таки приведу пару примеров из кода конвертора.
Копирование текста из текстового поля с id=1004:
invoke OpenClipboard,hWnd ;откроем буфер обмена test eax,eax jz endcopy ;если не удалось открыть - выходим invoke EmptyClipboard ;очищаем буфер обмена invoke GetDlgItemText,hWnd,1004,membuf,buflen-1 ;получаем текст из текстового поля в память membuf inc eax mov clipboard,FUNC(GlobalAlloc,GMEM_MOVEABLE,eax) ;выделяем память для копирования test eax,eax jz endcopy2 ;если не удалось выделить - выходим и закрываем буфер обмена invoke GlobalLock,clipboard ;блокируем память и получаем указатель на первый байт этой памяти invoke lstrcpy,eax,membuf ;копируем туда текст invoke GlobalUnlock,clipboard ;разблокируем память invoke SetClipboardData,CF_TEXT,clipboard ;записываем данные в буфер обмена endcopy2: invoke CloseClipboard ;закрываем буфер обмена endcopy:
Вставка текста в поле с id=1003:
invoke IsClipboardFormatAvailable,CF_TEXT ;есть ли в буфере обмена текстовые данные в ASCII? test eax,eax jz endpaste ;если нет - выходим invoke OpenClipboard,hWnd ;откроем буфер обмена test eax,eax jz endpaste ;если не удалось открыть - выходим mov clipboard,FUNC(GetClipboardData,CF_TEXT) ;получаем указатель на первый байт памяти test eax,eax jz endpaste2 ;если не удалось - выходим и закрываем буфер invoke GlobalLock,eax ;блокируем память и получаем указатель на первый байт этой памяти test eax,eax jz endpaste2 ;если не удалось - выходим и закрываем буфер invoke SetDlgItemText,hWnd,1003,eax ;устанавливаем текст в поле для ввода из этой памяти invoke GlobalUnlock,clipboard ;разблокируем память endpaste2: invoke CloseClipboard ;закрываем буфер обмена endpaste: