Give me a long enough lever and I'll move the world. Give me enough string, sash pulleys and door closers and I'll mount EFX for you. -- Kit Lane
ГлавнаяСтатьи Пишем собственный screencapturer для Windows. Часть 1
Пишем собственный screencapturer для Windows. Часть 1
В повседневной работе с Windows иногда , однако, все же возникает потребность в получений копий снимков с текущего рабочего стола
Windows. Для этого есть масса свободных или платных программ, а мы напишем свою. Тем боле, займет это очень мало времени. Для этого нам
нужно только работающий компьютер с установленной операционной системой Windows, MicrosoftVisualStudio 2003иконечно,MSDN. Сама процедура разработка будет описана пошагово,там жебудутте части программногокода, которые будут нами созданы.
Как обычно, создаем шаблон программы. Для этого запускаем MicrosoftVisualStudio 2003 , выбираем “NewProject…”, затем “VisualC++”. В этом меню выбираем “MFCApplication”. Выбираем путь где будет расположен наш проект и вводим название “screencapture”. (Хотя каждый может ввести любое название J ) Жмем «ОК». Дальше мы выбираем «ApplicationType» - “Dialogbased”. Если кто желает подарить другу или подруге свою программу, то нужно выбрать “UseMFCinstaticlibrary”. Все остальные настройки можно оставить без изменений.
Открываем проект. Компилируем его, чтобы увидеть, точто мы имеем сейчас.Для начала удаляем «TODO: Placedialogcontrolshere.» и обе кнопки “OK”и“Cancel”. Увеличим размеры окна, например сделаем их 850x650. Отредактируем заголовок программы и введем туда “Screen Capturer”
Затем, идем в редактор ресурсом и редактируем иконку «IDR_MAINFRAME»
Эта икона в последствии будет нам использована, но поскольку
стандартный вид не совсем удобный, нам надо то-то специфическое.
Рисуем иконку новую на основе существующей или создаем новую.
Теперь создаем в редакторе ресурсов новое меню. Добавляем «AddResource», там выбираем “New-> Menu”. Переименовываемего из “IDR_MENU1”в“IDR_MENU_TRAY”. Затем займемся редактированием самого меню. Назовем его к примеру “Action”, затем добавляем
вподпункты “Get Screen”, “Hide In Tray”, “Restore” и“Exit”. Перед последним пунктомнажмем клавишу «-» для того, чтобы отделить“Exit” от
остальных команд.
4.На этом с ресурсами все, и мы начнем программировать. По логике работы программы, нам нужно, чтобыпрограмма была не видна
в моментполучения снимка экрана. Значит, она должна находится в системном трее, той области, где приложение свернуто до
размеров иконки. Сначала создадимновую переменную типа NOTIFYICONDATA с именем tray_icon для класса CscreencaptureDlg.cpp
Обозначим еекак“public”. Это структура, которая будет использована для хранения данныхдля обработки сообщений системного трея.
Теперь займемся нашим меню. Создадим переменную типа CMenu и назовем ее “menu” опять же для класса CscreencaptureDlg.cpp. Затем в переходим в этом классе к методу OniInitDialog() и послекомментариев// TODO: Addextrainitializationhere
пишем такой код
menu.LoadMenu(IDR_MENU_TRAY);
SetMenu(&menu);
Первая строка загружает в переменную меню из ресурсов, в вторая делает его видимы на окне нашего приложения.
Компилируем программу и видим результат ее работы, - появляется наше меню.
Теперь переходим снова в редактор ресурсов и назначаем обработчики событий для пунктов меню. Сначала
добавляем обработчик к пункту “Exit”. Делаем правый клик мышью на выбранном нами пункте меню и из выпавшего списка опций
выбираем “AddEventHandler…”. Затем выбираем обработчик типа COMMAND и связываем с классом CscreencaptureDlg.cpp.
В открывшемся окне нам нужно ввести код обработчика.
void CscreencaptureDlg::OnActionExit(){
EndDialog(0);
}
Сперва мы создаем переменную типа int и присваиваем ей значение 1. Это сделано скорее с данью традиции,
можно присвоить любое значение этого же типа. Потомучтометод EndDialog (int someresult);
принимаетзначения этого типа. Сам же метод, согласно его описанию и названию, просто уничтожает модальное
диалоговоеокно.
Чтобы создать обработчик сообщений для системного трея, мы должны сделать следующее;ввести в файлRessource.h
добавляем идентификатор иконки:
<span style="font-size: 12pt; font-family: "Times New Roman","serif""><span> </span></span><strong><span style="font-size: 12pt; font-family: "Times New Roman","serif"; color: windowtext">#define ID_TrayIcon<span> </span>135</span></strong>
Число «135» взято произвольно, главное чтобы не совпадало с уже существующими ID ресурсов. Этот ID будет впоследствии использовано для
обращения к иконке. Затем мы создаем обработчик события для системного трея -в классу диалогового окна вводим новое сообщение:
#define WM_TRAYICONNOTIFY WM_USER+1
все сообщения типа WM_USER+1 представляют собой частные сообщения, определяемые самим пользователем.
Затем в карту сообщенийдобавляем собственно обработчик сообщений для трея
ON_MESSAGE(WM_ICON, OnTrayIcon)
После чего она будет выглядеть таким образом:
BEGIN_MESSAGE_MAP(CscreencaptureDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_COMMAND(ID_ACTION_EXIT, OnActionExit)
ON_COMMAND(ID_ACTION_HIDE, OnActionHide)
ON_MESSAGE(WM_ICON, OnTrayIcon)
ON_COMMAND(ID_ACTION_RESTORE, OnActionRestore)
END_MESSAGE_MAP()
И самое главное, надо добавить новый метод, который и собственнобудет обрабатывать это сообщение. Для этого мы добавим к классу CscreencaptureDlg.cpp.
такой метод, кликнув мышью на “ClassView” ( « Вид Классов»)и выбрав класс диалогового окна. В выпавшем меню выберем “Add..-> AddFunction”
Новый методOnTrayIcon будетвозвращать значения типа LRESULT и приниматьWPARAM wp, LPARAM lp. Затем вводим внутрь его такой код:
8. Снова возвращаемся в редактор ресурсов к нашему меню и аналогичным способом добавляем обработчик к пункту“HideInTray”.
Затем редактируем его код:
voidCscreencaptureDlg::OnActionHide()
{
ShowWindow(SW_HIDE);
//окноминимизируется
Shell_NotifyIcon(NIM_ADD, &trray_icon);
// В трее появляется иконка
}
Затем компилируем программу. Мы видим, что после нажатия на пункт меню “HideInTray” появляется иконка в системном трее и окно исчезает.
9. Аналогичным способом добавляем обработчик кпункту меню “Restore”:
void CscreencaptureDlg::OnActionRestore()
{
// Удалениеиконкиизтрея
Shell_NotifyIcon(NIM_DELETE, &tray_icon);
// Отображение главного окна
ShowWindow(SW_NORMAL);
// Теперь фокус будет получать главное окно
::SetForegroundWindow(m_hWnd);
}
10.Компилируем приложение, пробуем. Если не было синтаксических ошибок, то все работает. J. Теперь перейдем к самому главному, тому, для чего мы создали
этупрограмму. Нам потребуется использования класса контекста устройства, для чего мысоздаем новую переменную для класса диалогового окна –