![]() |
Библиотека Интернет Индустрии I2R.ru |
||
Написание экстра-маленьких Win32 приложений на С++ от 1 КБ используя лишь API, на примере программы Windows HiderВведение Натыкаясь в Интернете на довольно интересные программы, я часто не решался их закачивать после того, как узнавал их размер. Какую ни возьми - все огромные. Да и ресурсов системных потребляют немало. В этой статье будет рассказано о том, как сделать программу в среднем в 10 - 100 раз меньше размером, чем попадаются аналогичные. Цель Написать очень быструю и маленькую программу, скрывающую по CTRL+F12 заданные окна. При нажатии комбинации CTRL+F10 она должна показать спрятанные окна. Входные данные: TXT Файл вида ------------ Internet Explorer The Bat! Visual C++ 911 ------------
Если будут найдены окна, содержащие в своем заголовке указанные строки, они будут спрятаны. Опции линкера Если ничего не предпринимать, то нам не удастся получить в итоге файл менее 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")
На что теперь стоит обратить особое внимание? Обычно точка входа в программу выглядит так: Но(!)... Так как мы отключили "Runtime library", нам теперь передается в этих параметрах
разный мусор. Поэтому называем точку входа не WinMain а New_WinMain, которую объявим, как
void New_WinMain(void), чтобы не забыть о том, что нам ничего не передается. А параметр
HINSTANCE получаем функцией GetModuleHandle(NULL). Ах да, и выходить из программы будем
функцией ExitProcess.
Объявим кое-какие константы Это понадобится для регистрации "горячих" клавиш функцией RegisterHotKey. // .....................
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 окон) Функции Обработка сообщений главного окна Пройдемся по главным строкам функции NewWinMain * Получим INSTANCE модуля. Это нам нужно для регистрации оконного класса WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW ;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.hInstance = hInst;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszClassName = "CKMINT21WINDOWSHIDERPRO";
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.lpszMenuName=NULL;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
if (!RegisterClass(&wc)) MessageBox(0,"I can't register window
class.","Error:",0), ExitProcess(0);
* Создаем главное окно приложения Примечание: Так как кто-то этого может не знать, хочу отметить, что в языке С++ есть "операция следования" - запятая. Т.е. просто последовательно выполнятся обе функции ShowWindow и UpdateWindow (как отдельный блок). В вышеуказанной строке можно было бы и просто поставить ";", а вообще иногда это помогает избавиться от огромного количества фигурных скобок {}, в тексте программы. * Затем регистрируем в системе HotKeys. Они будут привязаны к главному окну, которому
будут передаватся сообщения WM_HOTKEY. * Затем считываем настройки из файла и запускаем главный цикл обработки оконных
сообщений для текущего процесса. Оконная процедура // Тут все довольно стандартно. Делаем switch (msg).
// ...
case WM_HOTKEY:
if (HOTKEYSHOW == (int)wParam)
// показываем все, что мы до этого прятали, а так же главное
// окно программы
ShowAll(), ShowWindow(hwnd,SW_SHOW);
if (HOTKEYHIDE == (int)wParam)
// Скрываем наше главное окно и запускаем перебор всех окон в
// системе - EnumWindows. Теперь будет вызываться функция
// my_EnumWindowsProc для каждого обнаруженного в системе окна.
ShowWindow(hwnd,SW_HIDE), EnumWindows((int (__stdcall *)(struct
HWND__ *,long))my_EnumWindowsProc, 0);
break;
// ...
// Если программу пытаются минимизировать, просто скрываем ее
// .........................
case WM_SYSCOMMAND:
if(SC_MINIMIZE == wParam) { ShowWindow(hwnd,SW_HIDE); return 0; }
break;
// Внимание, после ShowWindow(hwnd,SW_HIDE) мы пишем return 0,
// вместо break. Почему? Да потому что не хотим, чтобы это
// сообщение пошло дальше в систему. Мы его уже обработали
// по-своему.
// ...
// А затем обрабатываем нажатия на кнопки.
case BN_CLICKED:
if (hwndButtonHide==(HWND)lParam)ShowWindow(hwndMain,SW_HIDE);
if (hwndButtonEditFilter==(HWND)lParam)ShellExecute(NULL,"open",
szFilterStringsFile,NULL,NULL,SW_SHOWMAXIMIZED);
break;
Рассмотрим функцию my_EnumWindowsProc Пропустим все невидимые окна for(i=0;i<MAXFIL;i++)
if (FilterStrings[i]) // если это начало строки, то
{
if (Contain(szWindowsTitle, FilterStrings+i)) HideNext(hwnd);
// скроем окно, если эта строка содержится в szWindowsTitle
while(FilterStrings[i]) i++;
// сместим указатель на следующий 0
}
Продолжаем дальнейший перебор окон return TRUE;
(Если бы было return FALSE, перебор бы закончился.) |
|
| 2000-2008 г. Все авторские права соблюдены. |