Windows-приложение Hello World
Ниже приведен код полнофункциональной и очень простой программы для Windows. Лучше всего просто следовать за кодом. В следующих разделах мы исследуем его строка за строкой. Мы рекомендуем вам в качестве упражнения создать проект в вашей среде разработки, вручную набрать код, скомпилировать его и запустить. Обратите внимание, что выбирая тип проекта надо указать Win32Application, а не Win32 Console Application.
///////////////////////////////////////////////////////////////////// // // Файл: hello.cpp // // Автор: Фрэнк Д. Луна (C) All Rights Reserved // // Система: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, // MSVC++ 7.0 // // Описание: Демонстрация создания приложения для Windows. // /////////////////////////////////////////////////////////////////////
// Включение заголовочного файла, содержащего все объявления структур, // типов данных и функций Win32 API необходимых для Windows-программы. #include <windows.h>
// Дескриптор главного окна. Используется для идентификации // главного окна, которое мы создадим HWND MainWindowHandle = 0;
// Обертка для кода, необходимого для инициализации приложения Windows. // Функция возвращает true если инициализация произведена успешно // и false в ином случае. bool InitWindowsApp(HINSTANCE instanceHandle, int show);
// Обертка для кода цикла сообщений. int Run();
// Оконная процедура, обрабатывающая получаемые нашим окном // сообщения LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Эквивалент main() для Windows int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd) { // Сперва мы создаем и инициализируем наше приложение Windows // Обратите внимание, что значения hInstance и nShowCmd // передаются WinMain в параметрах. if(!InitWindowsApp(hInstance, nShowCmd)) { ::MessageBox(0, "Init - Failed", "Error", MB_OK); return 0; }
// После создания и инициализации приложения мы входим // в цикл обработки сообщений. В нем мы остаемся до тех пор // пока не будет получено сообщение WM_QUIT, говорящее, что // работа приложения должна быть завершена.
return Run(); // вход в цикл сообщений }
bool InitWindowsApp(HINSTANCE instanceHandle, int show) { // Первая задача при создании окна - описать его // характеристики путем заполнения структуры WNDCLASS WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = instanceHandle; wc.hIcon = ::LoadIcon(0, IDI_APPLICATION); wc.hCursor = ::LoadCursor(0, IDC_ARROW); wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)); wc.lpszMenuName = 0; wc.lpszClassName = "Hello";
// Затем мы регистрируем описание класса окна в Windows // чтобы потом мы смогли создать окно с объявленными // характеристиками if(!::RegisterClass(&wc)) { ::MessageBox(0, "RegisterClass - Failed", 0, 0); return false; }
// После регистрации описания нашего класса окна мы можем // создать окно с помощью функции CreateWindow. // Обратите внимание, что функция возвращает значение HWND // для созданного окна, которое мы сохраняем в переменной // MainWindowHandle. В дальнейщем переменная MainWindowHandle // позволит обращаться именно к тому окну, которое мы создали. MainWindowHandle = ::CreateWindow( "Hello", "Hello", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, instanceHandle, 0);
if(MainWindowHandle == 0) { ::MessageBox(0, "CreateWindow - Failed", 0, 0); return false; }
// Теперь мы отображаем и обновляем только что созданное // окно. Обратите внимание, что в качестве параметра обоим // функциям передается значение MainWindowHandle, чтобы они // знали какое именно окно надо отображать и обновлять. ::ShowWindow(MainWindowHandle, show); ::UpdateWindow(MainWindowHandle);
return true; }
int Run() { MSG msg; ::ZeroMemory(&msg, sizeof(MSG));
// Цикл выполняется, пока мы не получим сообщение WM_QUIT. // Функция GetMessage возвращает 0 (false) только когда // получено сообщение WM_QUIT, что приводит к выходу из цикла. while(::GetMessage(&msg, 0, 0, 0)) { // Трансляция сообщения и его перенаправление // соответствующей оконной процедуре. ::TranslateMessage(&msg); ::DispatchMessage(&msg); }
return msg.wParam; }
LRESULT CALLBACK WndProc( HWND windowHandle, UINT msg, WPARAM wParam, LPARAM lParam) { // Обработка заданных сообщений: switch( msg ) { case WM_LBUTTONDOWN: // Если нажата левая кнопка мыши, // отображаем диалоговое окно. ::MessageBox(0, "Hello, World", "Hello", MB_OK); return 0;
case WM_KEYDOWN: // Если нажата клавиша Esc, уничтожаем // главное окно приложения, идентифицируемое // дескриптором MainWindowHandle. if( wParam == VK_ESCAPE ) ::DestroyWindow(MainWindowHandle); return 0;
case WM_DESTROY: // Если получено сообщение о завершении работы, // отправляем сообщение, которое завершит работу // цикла обработки сообщений. ::PostQuitMessage(0); return 0; }
// Переправляем все остальные сообщения, которые // наша программа не обрабатывает сама, системной // процедуре обработки сообщений. return ::DefWindowProc(windowHandle, msg, wParam, lParam); }