Написание экстра-маленьких Win32 приложений на С++ от 1 КБ
ОГЛАВЛЕНИЕ
Цель
Написать очень быструю и маленькую программу, скрывающую по CTRL+F12 заданные окна. При нажатии комбинации CTRL+F10 она должна показать спрятанные окна. Входные данные:
TXT Файл вида
------------
Internet Explorer
The Bat!
Visual C++
911
------------
Если будут найдены окна, содержащие в своем заголовке указанные строки, они будут спрятаны.
В вышеуказанном примере будут спрятаны все окна IE, окно Microsoft Visual C++, окно почтовой программы "The Bat!" и все окна, в заголовках которых содержится комбинация символов "911".
Итак, писать будем на чистом Win32 API. Создадим окно, привяжем к нему горячие клавиши. По требованию будем осуществлять перебор видимых окон в системе и в заголовке каждого будем искать заданные комбинации символов.
Опции линкера
Если ничего не предпринимать, то нам не удастся получить в итоге файл менее 32 КБ(примерно). Поэтому пишем:
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX
/IGNORE:4078")
#pragma comment(linker,"/ENTRY:New_WinMain")
#pragma comment(linker,"/NODEFAULTLIB")
На что теперь стоит обратить особое внимание? Обычно точка входа в программу выглядит так:
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szCmdLine,int nCmdShow)
(кстати, для Win32 приложений второй параметр всегда NULL)
Но(!)... Так как мы отключили "Runtime library", нам теперь передается в этих параметрах разный мусор. Поэтому называем точку входа не WinMain а New_WinMain, которую объявим, как void New_WinMain(void), чтобы не забыть о том, что нам ничего не передается. А параметр HINSTANCE получаем функцией GetModuleHandle(NULL). Ах да, и выходить из программы будем функцией ExitProcess.
Теперь если собрать нашу пустую программку, которая ничего делать не будет, размер ее будет 1 Кб. Но нам нужно еще дописать 3 Кб кода. Продолжим.
Чтобы все дальнейшее было понятно даже новичку в программировании под Windows, я прокомментирую все.
Объявим кое-какие константы
Это понадобится для регистрации "горячих" клавиш функцией RegisterHotKey.
#define HOTKEYHIDE 1
#define HOTKEYSHOW 2
Размер буффера, куда будет считываться заголовок окна функцией GetWindowText.
#define SSZZ 256
Размер буфера, куда будет считываться файл со стоками фильтрации (используется в объявлении char FilterStrings[MAXFIL];)
#define MAXFIL 1024
(Примечание: При желании можно сделать и выделение памяти динамически - найти файл, узнать его размер и выделить блок. Приблизительный пример:
// .....................
WIN32_FIND_DATA FindData;
HANDLE hFind=FindFirstFile(szFilterStringsFile,&FindData);
if (hFind!=INVALID_HANDLE_VALUE)
{
i=(FindData.nFileSizeHigh * MAXDWORD) + FindData.nFileSizeLow;
HGLOBAL hGA=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE,i+1);
// (+ end-ZERO)
if (hGA!=NULL)
{
LPVOID lpStrings=GlobalLock(hGA);
DWORD dw;
if (lpStrings!=NULL) ReadFile(hFile,lpStrings,i,&dw,NULL);
}
}
FindClose(hFind);
CloseHandle(hFile);
// ...............................
// Но так как вряд ли файл настроек у нас будет больше одного
// килобайта, я оставил статичный массив.
)
Массив хендлов окон (вряд ли будет у нас более 300 окон)
HWND aHwnd[300];
Кол-во инициализированных элементов в этом массиве
unsigned int cHwnd=0;
Дескрипторы окон - главное и два дочерних - кнопка "Hide" и кнопка "Edit filter strings"
HWND hwndMain, hwndButtonHide, hwndButtonEditFilter;
Тут будет что-то типа "c:\programs\winhider\winhider.settings.txt"
char szFilterStringsFile[MAX_PATH]="(с)2002 KMiNT21";
Соответственно, хендл файла с именем "что-то типа"
HANDLE hFile;
А это место, куда будем считывать все из этого файла
char FilterStrings[MAXFIL];