link7632 link7633 link7634 link7635 link7636 link7637 link7638 link7639 link7640 link7641 link7642 link7643 link7644 link7645 link7646 link7647 link7648 link7649 link7650 link7651 link7652 link7653 link7654 link7655 link7656 link7657 link7658 link7659 link7660 link7661 link7662 link7663 link7664 link7665 link7666 link7667 link7668 link7669 link7670 link7671 link7672 link7673 link7674 link7675 link7676 link7677 link7678 link7679 link7680 link7681 link7682 link7683 link7684 link7685 link7686 link7687 link7688 link7689 link7690 link7691 link7692 link7693 link7694 link7695 link7696 link7697 link7698 link7699 link7700 link7701 link7702 link7703 link7704 link7705 link7706 link7707 link7708 link7709 link7710 link7711 link7712 link7713 link7714 link7715 link7716 link7717 link7718 link7719 link7720 link7721 link7722 link7723 link7724 link7725 link7726 link7727 link7728 link7729 link7730 link7731 link7732 link7733 link7734 link7735 link7736 link7737 link7738 link7739 link7740 link7741 link7742 link7743 link7744 link7745 link7746 link7747 link7748 link7749 link7750 link7751 link7752 link7753 link7754 link7755 link7756 link7757 link7758 link7759 link7760 link7761 link7762 link7763 link7764 link7765 link7766 link7767 link7768 link7769 link7770 link7771 link7772 link7773 link7774 link7775

Уроки начинающим работать с С++ в Windows

Урок 1. Первая программа на С++ в среде Windows  — "Hello. World !"

Программирование в Операционной Системе Windows основано на событиях и сообщениях.
Операционная система Windows общается с программой путем посылки ей сообщений. Каждый раз при запуске
новой программы, Windows создает новый процесс и выделяет для этого процесса свою очередь сообщений
Когда в системе происходит какое либо событие: нажатие клавиши клавиатуры, кнопки мыши, движение мыши и др.
первой получает сообщение об этом операционная система Windows ! Получив сообщение, ОС посылает сообщение
об этом событии программе или, другими словами, направляет это событие в очередь сообщений для данной
программы, в окне которой это событие произошло.
Все приложения Windows должны иметь цикл обработки этих сообщений ( в функции WinMain() )
Этот цикл читает сообщения из очереди сообщений программы и направляет эти сообщения назад ОС Windows,
которая (ОС) затем вызывает оконную функцию программы, передавая ей это сообщение в качестве параметра
Именно так функционируют все программы под Windows.

По традиции первой программой на С++ выступает программа, выводящая на экран окно с текстом "Hello. World"



Любая программа под Windows состоит минимум из двух функций — WinMain() и оконной функции.
Функция WinMain() должна выполнять следующие операции:

  1. Определять класс окна
  2. Регистрировать класс окна
  3. Создавать окно данного класса
  4. Отображать окно
  5. Запускать цикл обработки сообщений
Оконная функция предназначена для обработки сообщений, относящихся к данному окну

Данный пример в ОС Windows состоит примерно из нескольких десятков строк кода на С++
Итак, начинаем...

#include <windows.h>

int PASCAL WinMain ( HANDLE hInstance, HANDLE hPrevInst, LPSTR lpszCmdParam, int nCmdShow )


Функция WinMain().

Каждая программа для Windows имеет главную функцию — точку входа, с которой начинается программа, и которая
называется WinMain(). Функция WinMain() позволяет передавать аргументы командной строки приложениям Windows
через параметр lpszCmdParam

Функция WinMain() имеет четыре аргумента

hInstance — уникальный идентификатор текущего экземпляра приложения
hPrevInstance — идентификатор последненго из запущенных экземпляров приложения, если запущено несколько экземпляров
приложения, если же запущен один экземпляр приложения, то hPrevInstance равен NULL
lpszCmdParam — указатель на строку, которая заканчивается нулевым байтом и содержит все параметры командной строки,
передаваемые данному экземпляру программы.
nCmdShow — целое число, показывающее как отображать запущенную программу — в виде открытого окна или в виде кнопки
на панели задач

Определяем локальные переменные
{
static char szAppName[] = "WinHel"; // szAppName — имя класса окна приложения
HWND hwnd; // hwnd — дескриптор окна приложения
MSG msg; // msg-сообщение (имеет тип MSG — см. описание ниже)
WNDCLASS wcn; // wcn-структура для передачи параметров, определяющая
вид главного окна приложения<
Регистрация класса окна

Здесь возможны два варианта, в зависимости от значания аргумента hPrevInstance.
Первый — в настоящий момент активен хотя бы один экземпляр программы, и тогда регистрировать класс окна не нужно.
Второй — нет ни одного запущенного экземпляра программы, что чаще всего и бывает, т.е. hPrevInstance == NULL, и значит
мы должны зарегистрировать класс окна , в котором хотим вывести надпись "Hello, World".
Заполняем структуру wcn
if(!hPrevInst) // проверяем — если нет ни одного запущенного экземпляра приложения -
// т.е. наш класс окна еще не зарегистрирован — регистрируем класс окна
{
wcn.style = CS_HREDRAW | CS_VREDRAW; // определяем стиль окна приложения
wcn.lpfnWndProc = WndProc; // указатель на функцию WndProc
wcn.cbClsExtra = 0; // целые числа, зарезервированные для
wcn.cbWndExtra = 0; // дополнительной информации о стилях
wcn.hInstance = hInstance; // значение параметра hInstance
wcn.hIcon = LoadIcon(NULL, IDI_APPLICATION); // дескриптор значка приложения
wcn.hCursor = LoadCursor(NULL, IDC_ARROW); // дескриптор указателя мыши
wcn.hbrBackground = GetStockObject(WHITE_BRUSH); // цвет и узор фона главного окна
wcn.lpszMenuName = NULL; // т.к. меню у нас нет, значит NULL
wcn.lpszClassName = szAppName; // имя класса окна, определенное выше
RegisterClass ( &wcn ); // и наконец — регистрируем класс окна
}
wcn.style — в этом поле определяется стиль окна. Установленные флаги CS_HREDRAW и CS_VREDRAW означают,
что всякий раз при изменении ширины или высоты окна будет производиться полная перерисовка рабочей области
окна
wcn.lpfnWndProc — указатель на экспортируемую функцию, обрабатывающую все сообщения. которые Windows посылает
приложению.
wcn.cbClsExtra и wcn.cbWndExtra — целые числа, зарезервированные для указания дополнительной информации о стилях
класса или окна.
wcn.hInstance — значение параметра hInstance, определенного Windows при инициализации первого экземпляра программы,
неизменное для всех последующих экземпляров приложения
wcn.Icon — дескриптор значка приложения (у нас например IDI_APPLICATION - белый квадрат в черной рамке)
wcn.hCursor — дескриптор указателя мыши (у нас например IDC_ARROW — вид стрелки, направленной вверх и влево)
wcn.hbrBackground — дескриптор кисти, определяет цвет и узор фона главного окна (белый фон окна — WHITE_BRUSH)
wcn.lpszMenuName — указатель на строку, содержащую имя меню (у нас нет меню, поэтому NULL)
wcn.lpszClassName — указатель на строку с именем класса окна (как у нас будет назван наш класс окна)
И наконец, вызов API-функции Windows RegisterClass(), предназначенной для регистрации класса окна в Windows

Создание окна приложения

Создается окно приложения функцией CreateWindow()
Функция CreateWindow() возвращает дескриптор созданного окна hwnd, который в дальнейшем может использоваться в
качестве аргумента при вызове других функций, работающих с нашим окном.
hwnd = CreateWindow(
szAppName, // имя класса окна
"My First Window", // заголовок окна-если окно будет без заголовка, то NULL
WS_OVERLAPPEDWINDOW, // стиль окна
CW_USEDEFAULT, // начальная Х-координата окна (или введите значение)
CW_USEDEFAULT, // начальная У-координата окна (или введите значение)
CW_USEDEFAULT, // начальный горизонтальный размер(или введите значение)
CW_USEDEFAULT, // начальный вертикальный размер (или введите значение)
NULL, // дескриптор родительского окна
NULL, // дескриптор меню окна — NULL — меню по умолчанию
hInstance, // дескриптор экземпляра программы
NULL); // параметры создания
Значениями по умолчанию CW_USEDEFAULT являются для начального положения окна — левый верхний угол экрана,
для начального размера окна — размеры по умолчанию.
Дескриптор меню окна — дескриптор системного меню, которое активизируется при нажатии кнопки,
расположенной в левом углу строки заголовка.(а не главное меню программы)

Отображение окна

Итак, окно было создано, теперь его надо отобразить на экране монитора. Делается это функцией ShowWindow(),
которой в качестве параметра передается дескриптор окна, возвращенный функцией CreateWindow() и аргумент
nCmdShow переданный функции WinMain() (см. выше)
ShowWindow( hwnd , nCmdShow ); // отобразить окно на экране
UpdateWindow( hwnd ); // вывести на экран рабочую область окна.
Цикл обработки сообщений

Как уже было сказано ранее, для каждого приложения Windows создает отдельную очередь сообщений.
Каждый раз, когда происходит событие, Windows преобразует это событие в сообщение и помещает это
сообщение в очередь сообщений приложению. Сообщение находится в очереди до тех пор, пока не будет обработано.
Для обработки этих сообщений и нужен цикл обработки сообщений.
Сообщение выбирается из очереди сообщений, принадлежащих данному приложению с помощью функции GetMessage()
 while( GetMessage( &msg, NULL, 0, 0 )) // ф-ция возвращает true пока не выберет WM_QUIT
{
TranslateMessage( &msg ); // ф-ция преобразования сочетания клавиш в другие события
DispatchMessage( &msg ); // распределяет сообщения по функциям окна, именно здесь
} // происходит "вызов" оконной функции
return msg.wParam; // когда цикл обработки сообщений заканчивается, поле
// wParam последнего сообщения возвращается вызывающему
// приложению — рабочему столу системы
} // конец функции WinMain()
&msg — указатель на структуру сообщения, в которой хранятся данные о полученном сообщении, msg имеет тип MSG.
Тип сообщения MSG определен следующим образом:
typedef struct tagMSG {
HWND hwnd; // дескриптор окна, которому адресуется ссобщение
UINT message; // тип Windows-сообщения (например WM_RBUTTONDOWN — нажатие правой кнопки мыши)
WPARAM wparam; // параметр сообщения, зависит от типа сообщения, например координаты указателя мыши
LPARAM lparam; // параметр сообщения, зависит от типа сообщения
DWORD time; // время постановки сообщения в очередь
POINT pt; // координаты мыши в момент time, имеет тип struct ( int x, int y; }
} MSG;
Функция WndProc()

С этой функции и начинается работа нашего приложения. Функция WndProc (ей можно присвоить другое имя)
получает сообщения из операционной системы и определяет реакцию приложения на эти сообщения
Итак, окно создано и выведено, теперь начинается работа приложения.
Мы хотим Давайте сделаем это в нашей оконной функции WndProc()
long FAR PASCAL WndProc ( HWND hwnd, UINT msg, UINT wParam, LONG lParam )
{
HDC hdc; // дескриптор контекста устройства для доступа к рисованию на экран
PAINTSTRUCT ps; // структура для рисования
RECT rect; // структура для указания области рисования switch( msg ) { case WM_PAINT: // выводим надпись "Hello, World !", для этого: hdc = BeginPaint( hwnd, &ps ); // получаем дескриптор(контекст) экрана GetClientRect( hwnd , &rect ); // получаем координаты рабочей области окна DrawText( hdc, "Hello, World !", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ); // выводим надпись EndPaint( hwnd, &ps); // освобождаем дескриптор return 0; case WM_LBUTTONDOWN: // нажатие левой кнопки мыши — выводим "*" hdc = GetDC( hwnd ); TextOut( hdc, LOWORD(lParam), HIWORD(lParam), "*", 1); ReleaseDC( hwnd, hdc ); break; case WM_DESTROY: // завершение приложения PostQuitMessage(0); // помещает в очередь сообщение WM_QUIT, необходимое для break; // прекращения цикла обработки в функции WinMain() default: // если сообщение не обработано в switch, вернуть его Windows return DefWindowProc ( hwnd, msg, wParam, lParam); } return NULL; } // завершение оконной функции
case WM_PAINT: Как правило, сообщение WM_PAINT генерируется неявным образом, например всякий раз, когда окно
приложения создается, перемещается, меняет размер, или например наше окно было закрыто частично или
полностью окном другого приложения (например, программой "Проводник") и требуется перерисовать
рабочую область окна.

case WM_DESTROY: сообщение возникает при попытке закрыть окно приложения, может появляться
и в других случаях
DefWindowProc() — обработчик необработанных или нераспознанных сообщений
В нашей программе мы обрабатываем сообщения WM_PAINT, WM_DESTROY и WM_LBUTTONDOWN
а все другие сообщения передаем обратно в Windows для обработки по умолчанию

case WM_LBUTTONDOWN: сообщение возникает при нажатии левой кнопки мыши
(работа с мышью будет описана в последующих уроках, здесь лишь как пример)
LOWORD(lParam) — координата X мыши
HIWORD(lParam) — координата Y мыши


Краткие итоги:

Итак, ма завершили создание первой программы на С++ в среде Windows "Hello. World !"
Текст и проект для C++Builder 6 получившейся программы можно скачать здесь. ( 7Кб )
Запустите программу, посмотрите как она работает, поэкспериментируйте

В следующих уроках мы поговорим о типах данных в Windows, работе с полосами прокрутки, выводе текста.