Здравствуй уважаемыйин!
Это мой дебют на Хабре!
Я достаточно долгое время читаю статьи с хабра мне они все нравятся. Но вот в чем загвоздка, я сам захотел попробовать что то свое сделать, так сказать сделать свой вклад в развитие данного проекта, хотя мой вклад будет достаточно мал и ничтожный.
Предусловие
Я хотел бы показать, рассказать более простым языком новичкам о GUI-приложениях на WinAPI.
GUI — (Graphic User Interfrace) графический пользовательский интерфрейс.
Для новичков это будет может более понятно, тем листать мануалы по WinAPI. Для более опытных программистов С++, моя статья
не содержит никакой полезной и интересной информации, так что смело можете давить Alt + Left, если нет тогда читаем до конца
Чтобы писать GUI-приложения нужно иметь хоть малейшее представление что такое GUI.
Что такое GUI ?
Смотрим всем известную Wikipedia — GUI!
GUI, грубо говоря это — окна. Рассмотрим пример окна блокнота в котором я писал эту статью
Основные:
1 — Кнопка системного меню
2 — Системные кнопки (сворачивание/максимализация/закрытие)
3 — Меню
4 — Панель инструментов
5 — Полосы просмотра
6 — Строка состояния
7 — Рабочая область
Этот демонстрируется в качестве примера.
Знакомимся с WinAPI:
WinAPI это — Windows_API
Еще не долго и мы сделаем свое первое приложение, но как на примере у нас оно точно не получится
Для разработчика окно — это большое количество элементов, функционирующих под управлением приложенния и операционной системы.
А для программирование, окна — это переменные, над которыми выполняют некоторые действия.
Для создания окна операционной системе нужно указать к какому классу оно принадлежитф.
Немножко теории:
Набор используемых ресурсов класса задают в структуре типа WNDCLASS. Она имеет следующий вид:
typedef struct
{ UINT style;
WNDPRO lpfnWndProc;
Int cbClsExtra;
Int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS;
Небольшой разбор:
— style — стиль окна,
— lpfnWndProc — указывает на функцию окна,
— hInstance — указывает на дескриптор текущего приложения,
— hIcon — указывает на иконку,
— hCursor — указывает курсор,
— hbrBackground — задает дескриптор кисти закрашивания фона окна,
— lpszMenuName — указывает на имя ресурса главного меню окон этого класса,
— lpszClassName — указывает на текстовою строку, содержащую имя регистрируемого класса.
Думаю теории достаточно, если что-то конкретное будет интересовать, то поисковики никто не отменял.
Приступаем к практике:
И так друзья, сейчас будет самое интересное, сейчас мы будем делать свое первое GUI-приложение
Для начала объявим заголовочный файл «windows.h»
#include <windows.h>
В нем содержаться все необходимые WinAPI функции.
Теперь нужно объявить функции которые мы будем использовать.
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
Сейчас будет самая важная функция, вообще, всей программы!
Всем программистам на С++ известна функция
int main ()
Для приложений на WinAPI наша функция называется WinMain(!)
Модификатор WINAPI указывает на то, что функция должна сама откорректировать расположение аргументов в стеке.
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
Едем дальше!
Давайте назовем свой будущий класс
LPCTSTR lpzClass = ("My Window Class!");
Проверим регистрацию этого класса
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
Небольшая, но удобная мелочь. Вычисляем координаты центра экрана
RECT screen_rect;
GetWindowRect(GetDesktopWindow(),&screen_rect); // разрешение экрана
int x = screen_rect.right / 2 - 300;
int y = screen_rect.bottom / 2 - 75;
Создание окна, с помощью CreateWindow, она имеет следующую структуру:
HWND CreateWindow(
LPCTST lpClassName, //Указатель на имя класса
LPCTST lpWindowName, //Указатель на имя окна
DWORD dwStyle, //Стиль окна
int x, //Координата левого края окна
int y, //Координата верхнего края окна
int nWidth, //Ширина окна
int nHeight, //Высота окна
HWND hWndParent, //Дескриптор окна-родителя или окна-владельца
HMENU hMenu, //Дескриптор меню или идентификатор дочернего окна
HANDLE hInstance, //Дескриптор приложения
LPVOID lpParam //Указатель на данные окна
)
Ну, мы делаем тоже самое!
HWND hWnd = CreateWindow(lpzClass, TEXT("Hello Habr!"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 600, 300, NULL, NULL,
hInstance, NULL);
Если окно не создано, описатель будет равен 0.
if(!hWnd) return 2;
/* Теперь делаем цикл обработки сообщений
Именно здесь происходит «вызов» функции окна */
MSG msg = {0}; // структура сообщения
int iGetOk = 0; // переменная состояния
while ((iGetOk = GetMessage(&msg, NULL, 0, 0 )) != 0) // цикл сообщений
{
if (iGetOk == -1) return 3; // если GetMessage вернул ошибку - выход
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam; // возвращаем код завершения программы
}
Теперь нам еще нужно зарегистрировать класс окна
Что мы сейчас и сделаем!
ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
WNDCLASS wcWindowClass = {0};
// функция обработки сообщений
wcWindowClass.lpfnWndProc = (WNDPROC)WndProc;
// стиль окна
wcWindowClass.style = CS_HREDRAW|CS_VREDRAW;
// дескриптор экземпляра приложения
wcWindowClass.hInstance = hInst;
// название класса
wcWindowClass.lpszClassName = lpzClassName;
// загрузка курсора
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
// загрузка цвета окон
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClass(&wcWindowClass); // регистрация класса
}
В каждом приложении нужна функция обработки сообщения, это в своем роде некоторое место где происходит обработка
взаимодействия между пользователем и самим приложением.
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// выборка и обработка сообщений
switch (message)
{
case WM_LBUTTONUP:
// реакция на сообщение
MessageBox(hWnd, ("У нас все получилось!"), ("My GUI Program"), 0);
break;
case WM_DESTROY:
PostQuitMessage(0); // реакция на сообщение
break;
default:
// все сообщения не обработанные Вами обработает сама Windows
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
И это все!!! Надеюсь всем было интересно!
Все достаточно ясно. Никаких сложностей возникнуть не должно.
Да, от себя я добавил маленькую обработку событий, а именно реакцию на нажатие левой кнопки мышки.
И так, подобьем итоги:
— готовая первая программа на WinAPI,
— набрались немножко опыта(новички),
— я также набрался опыта.
Спасибо всем кто дочитал до конца, строго не судите и не ругайте за ошибки(я их по ходу написания много исправил ),
может изложил мысль не так как хотелось бы но все же, как мне кажется на нормальном языке и понятном языке. Если будет нужно, то и возможно продолжение.
Всем удачи, всем спасибо!
P.S Если возникли проблемы с кодом, вот выложил исходники + статья(html) (писал в CodeBlocks)
Автор: GraF_DOS