среда, 8 сентября 2010 г.

Как создать приложения с диалогом на WinAPI в Visual C++

Создать простое оконное приложение в Visual C++ с использованием только WinAPI, можно с помощью готового мастера следующим образом:
Создать новый проект File -> New Project -> Visual C++ -> Win32 -> Win32 Project.
В появившемся мастере сразу жмем Finish. При этом будут сгенерирован исходный код приложения с одним основным окном и одним диалогом About.
Для того чтобы создать более простое приложение на основе диалога из ресурса (в Visual C++ Professional и выше, т. к. в Express версии нету редактора ресурсов), проще всего создать пустой проект (для этого, при создании проекта, в мастере перейти на вкладку Application Settings и поставить галочку Empty Project) и добавить нужные файлы вручную. В простейшем приложении с одним диалогом достаточно будет добавить один файл main.cpp и файл ресурса. В редакторе ресурсов создаем новый диалог. В созданный файл main.cpp добавляем следующий код:
#include <windows.h>
#include "resource.h"
INT_PTR CALLBACK WndProc(HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
INT_PTR ret = DialogBoxA(hInstance,
MAKEINTRESOURCEA(IDD_DIALOG_MAIN), NULL, WndProc);
int err = GetLastError();
return 0;
}
INT_PTR CALLBACK WndProc(HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
break;
case IDC_BUTTON2:
break;
}
}
return (INT_PTR)FALSE;
}

среда, 1 сентября 2010 г.

Перехват событий Windows

Для перехвата событий в Windows, предусмотрена API-функция SetWindowsHookEx. С помощью нее можно перехватить как события отдельной нити, так и глобальные события Windows. Функция SetWindowsHookExA имеет следующую сигнатуру:
HHOOK WINAPI SetWindowsHookEx(
__in int idHook,
__in HOOKPROC lpfn,
__in HINSTANCE hMod,
__in DWORD dwThreadId
);

С помощью этой API-функции можно перехватывать различные события, в том числе и событие от мыши и клавиатуры. Подробное описание функции лежит в MSDN.

Для того чтобы перехватить событие текущей нити, достаточно определить функцию, соответствующую сигнатуре HOOKPROC и вызвать функцию SetWindowsHookEx, как приведено в примере ниже:
LRESULT CALLBACK hook_proc(int code, WPARAM wParam,
LPARAM lParam)
{
MessageBoxA(NULL, "Key Pressed", "Key Pressed", MB_OK);
return CallNextHookEx(NULL, code, wParam, lParam);
}

//Где-то в программе {
HHOOK hHook = SetWindowsHookExA(WH_KEYBOARD, hook_proc, NULL,
GetCurrentThreadId());
if (hHook == NULL)
{
DWORD err = GetLastError();
char chr[20];
itoa(err, chr, 10);
MessageBoxA(hWnd, chr, "Error", MB_OK | MB_ICONERROR);
}
else
{
MessageBoxA(hWnd, chr, "Keyboard Evend Hooked!",
MB_OK | MB_ICONERROR);
}
//}
Исходный код приведенного примера лежит тут.

Перехват глобального события требует создания DLL с функцией-обработчиком события. Подробно о создании DLL написано здесь.
Исходный код примера можно загрузить по этой ссылке.