Главная » Статьи » C++ » Статьи по С++ |
Скачивать материалы с сайта, могут только зарегистрированные пользователи.
Для регистрации заполните два поля ниже!
Через минуту Вы получите "Гостевой доступ"
Написание маленьких приложений на Borland C++ Builder
Натыкаясь в Интернете на довольно интересные программы, я часто не решался их закачивать после того, как узнавал их размер. Какую ни возьми - все огромные. Да и ресурсов системных потребляют немало. В этой статье я расскажу о том, как сделать программу в среднем в 10 - 100 раз меньше размером, чем попадаются аналогичные. ЦельНаписать очень быструю и маленькую программу, скрывающую по CTRL+F12 заданные окна. При нажатии комбинации CTRL+F10 она должна показать спрятанные окна. Входные данные: TXT Файл вида Если будут найдены окна, содержащие в своем заголовке указанные строки, они
будут спрятаны. Итак, писать будем на чистом Win32 API. Создадим окно, привяжем к нему горячие клавиши. По требованию будем осуществлять перебор видимых окон в системе и в заголовке каждого будем искать заданные комбинации символов. Опции линкераЕсли ничего не предпринимать, то нам не удастся получить в итоге файл менее 32 КБ(примерно). Поэтому пишем: #pragma comment(linker,"/MERGE:.rdata=.text") На что теперь стоит обратить особое внимание? Обычно точка входа в программу
выглядит так: 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 Размер буффера, куда будет считываться заголовок окна функцией
GetWindowText. #define SSZZ 256 Размер буфера, куда будет считываться файл со стоками фильтрации (используется в объявлении char FilterStrings[MAXFIL];) #define MAXFIL 1024 (Примечание: При желании можно сделать и выделение памяти динамически - найти файл, узнать его размер и выделить блок. Приблизительный пример: // ..................... Зададим глобальные переменныеМассив хендлов окон (вряд ли будет у нас более 300 окон) HWND aHwnd[300]; Кол-во инициализированных элементов в этом массиве unsigned int cHwnd=0; Дескрипторы окон - главное и два дочерних - кнопка "Hide" и кнопка "Edit
filter strings" HWND hwndMain, hwndButtonHide, hwndButtonEditFilter; Тут будет что-то типа "c:programswinhiderwinhider.settings.txt" char szFilterStringsFile[MAX_PATH]="(с)2002 KMiNT21"; Соответственно, хендл файла с именем "что-то типа" HANDLE hFile; А это место, куда будем считывать все из этого файла char FilterStrings[MAXFIL]; ФункцииОбработка сообщений главного окна LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); Функция, которая будет вызываться для каждого окна при переборе всех окон static BOOL FAR PASCAL my_EnumWindowsProc(HWND hwnd, DWORD lParam); Проверка наличия строки str2 в str1 BOOL Contain(char* str1, char* str2); Скрывание с экрана очередного окна inline void HideNext(HWND hwnd){ ShowWindow(aHwnd[cHwnd++]=hwnd,SW_HIDE); } Возврат всех спрятанных окон на экран inline void ShowAll(void) { while(cHwnd) ShowWindow(aHwnd[--cHwnd],SW_SHOW);} Пройдемся по главным строкам функции NewWinMain* Получим INSTANCE модуля. Это нам нужно для регистрации оконного класса HINSTANCE hInst=GetModuleHandle(NULL); * Зарегистрируем оконный класс WNDCLASS wc; Создаем главное окно приложения hwndMain=CreateWindow(wc.lpszClassName,"Small windows hider!", И помещаем на него две кнопки. Как видим, кнопки имеют класс "BUTTON". Они являются дочерними окну hwndMain. hwndButtonHide=CreateWindow("BUTTON","Hide!", WS_VISIBLE | WS_CHILD, Наконец, показываем главное окно ShowWindow(hwndMain,SW_SHOW), UpdateWindow(hwndMain); Примечание: Так как кто-то этого может не знать, хочу отметить, что в языке С++ есть "операция следования" - запятая. Т.е. просто последовательно выполнятся обе функции ShowWindow и UpdateWindow (как отдельный блок). В вышеуказанной строке можно было бы и просто поставить ";", а вообще иногда это помогает избавиться от огромного количества фигурных скобок {}, в тексте программы. * Затем регистрируем в системе HotKeys. Они будут привязаны к главному окну, которому будут передаватся сообщения WM_HOTKEY. RegisterHotKey(hwndMain,HOTKEYHIDE,MOD_CONTROL,VK_F12) Затем считываем настройки из файла и запускаем главный цикл обработки оконных сообщений для текущего процесса. MSG msg; Оконная процедура// Тут все довольно стандартно. Делаем switch (msg). Рассмотрим функцию my_EnumWindowsProcПропустим все невидимые окна if (!IsWindowVisible(hwnd)) return TRUE; Получим TITLE очередного окна GetWindowText(hwnd, szWindowsTitle, SSZZ) Затем перебираем все стоки из файла настроек for(i=0;i// если это начало строки, то Продолжаем дальнейший перебор окон return TRUE; (Если бы было return FALSE, перебор бы закончился.) В остальных функциях особо описывать нечего. FAQ, возникший в результате множества заданных мне вопросов.Q: Почему программа не линкуется? A: Попробуйте собрать не debug, а release версию. А если вам нужна возможность отладки, воспользуйтесь обычными #define. И все-таки есть еще одни вариант. В отладочной версии линкер не может собрать файл потому, что не находит "__chkesp", которая содержится в "CHKESP.OBJ". Что мы можем сделать? Да взять и заменить тот obj на свой, который будет меньше размером и не будет содержать ненужный нам код. Q: Как теперь получить переданную командную строку? A: Ну тут все просто. Пользуйтесь стандартными API. То же самое и для Instance приложения. Вот они - GetCommandLine, GetModuleHandle. Q: А какой минимальный align возможен? A: Для того, чтобы ваша программа запускалась нормально в любой версии Windows, используйте 512 байт. Q: А можно ли делать такими маленькими DLL? A: Да. Назначьте свою точку входа вместо _DllMainCRTStartup. Вот пример. Q: А почему пропали функции strcmp, strlen и т.п.? A: Так как они были реализованы в RTL, теперь вы не можете их использовать. Но это не беда. В модуле kernel есть отличная замена этим функциям. Названия те же, но с буквой "l" вначале. Например - lstrlen, lstrcmp, lstrcat. Q: А теперь стали недоступны функции работы с памятью - memset, CopyMemory? A: RTL сам предоставляет интефейс для работы с памятью. Во-первых, чтобы соблюдать снандарт, во-вторых, чтобы упростить работу с памятью в среде Win32. Вот посмотрите на функцию CopyMemory - она на самом деле не является настоящей API функцией. Попробуйте слинковать проект без RTL, в котором используется эта функция. Результат - неудачная попытка линковки - ссылка на _memcpy. Еще один пример - функция new. В среде Win32 вы должы воспользоваться функциями GlobalAlloc, GlobalLoc и т.п. Однако вы можете просто заменить RTL функции своими. В файле add.txt вы можете взять уже готовые функции, если не хотите писать их сами. Q: У меня есть один вопрос, которого нет в этом FAQ, что делать? A: В таком случае вы можете задать вопрос на нашем форуме. www.uinc.ru/forum/ Links:
Статья с сайта www.ishodniki.ru | |
Просмотров: 1094 | | |
Выразить благодарность - Поделиться с друзьями!
Всего комментариев: 0 | |