Библиотека Интернет Индустрии 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 г. Все авторские права соблюдены. |
|