Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

WM_SETTEXT. Это сообщение требует, чтобы окно запомнило текст, переданный в буфере, в качестве своего текста. При обработке WM_SETTEXT функцией DefWindowProc выполняется запоминание и отображение текста окна.

7. Приложение с несколькими циклами обработки сообщений

В рассмотренных ранее примерах (т. е., трех версиях hello. cpp) в приложении был только один цикл обработки сообщений. В первой версии hello. cpp он был скрыт в системной функции MessageBox.

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

Аналогичным образом, вы можете реализовать второй (или третий, или четвертый) цикл обработки сообщений тогда, когда на некотором этапе выполнения вашего приложения требуется обрабатывать сообщения иным способом, нежели это делается при нормальном функционировании.

В качестве примера рассмотрим рисование в режиме захвата мыши. В 4-й версии hello. cpp обеспечивается рисование от руки с помощью мыши. Т. е. пользователь может сам написать "Hello, World!" мышью (рис. 2.4).

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

НЕ нашли? Не то? Что вы ищете?

Освобождение мыши в нашем приложении происходит, когда пользователь отпускает левую кнопку мыши.

В программе 2.4 есть два цикла обработки сообщений, в которых вызывается функция GetMessage. Главный цикл расположен в WinMain, а дополнительный размещен в функции DrawHello.

Рис. 2.4. Графическая версия приложения "Hello, World!".

#include <windows. h>

void AddSegmentAtMessagePos( HDC hDC, HWND hwnd, BOOL bDraw )

{

 DWORD dwPos;

 POINTS points;

 POINT point;

 dwPos = GetMessagePos();

 points = MAKEPOINTS( dwPos );

 point. x = points. x;

 point. y = points. y;

 ScreenToClient( hwnd, &point );

 DPtoLP( hDC, &point, 1 );

 if ( bDraw )

 LineTo( hDC, point. x, point. y );

 else

 MoveToEx( hDC, point. x, point. y, NULL );

}

void DrawHello( HWND hwnd )

{

 if ( GetCapture() != NULL )

 return;

 HDC hDC = GetDC( hwnd );

 if ( hDC!= NULL )

 {

 SetCapture( hwnd );

 AddSegmentAtMessagePos( hDC, hwnd, FALSE );

 MSG msg;

 while( GetMessage( &msg, NULL, 0, 0 ) )

 {

 if ( GetCapture() != hwnd )

 break;

 switch ( msg. message )

 {

 case WM_MOUSEMOVE :

 AddSegmentAtMessagePos( hDC, hwnd, TRUE );

 break;

 case WM_LBUTTONUP:

 goto ExitLoop;

 default:

 DispatchMessage( &msg );

 }

 }

ExitLoop:

 ReleaseCapture();

 ReleaseDC( hwnd, hDC );

 }

}

LRESULT CALLBACK WndProc( HWND hwnd, UINT uMsg,

WPARAM wParam, LPARAM lParam )

{

 switch( uMsg )

 {

 case WM_LBUTTONDOWN : DrawHello( hwnd ); break;

 case WM_DESTROY : PostQuitMessage( 0 ); break;

 default : return DefWindowProc( hwnd, uMsg, wParam, lParam );

 }

 return 0;

}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR d3, int nCmdShow )

{

 if ( hPrevInstance == NULL )

 {

 WNDCLASS wndClass;

 memset( &wndClass, 0, sizeof( wndClass ) );

 wndClass. style = CS_HREDRAW | CS_VREDRAW;

 wndClass. lpfnWndProc = WndProc;

 wndClass. hInstance = hInstance;

 wndClass. hCursor = LoadCursor( NULL, IDC_ARROW );

 wndClass. hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

 wndClass. lpszClassName = "HELLO";

 if ( !RegisterClass( &wndClass ) )

 return FALSE;

 }

 HWND hwnd;

 hwnd = CreateWindow( "HELLO", "HELLO", WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,

NULL, NULL, hInstance, NULL);

 ShowWindow( hwnd, nCmdShow );

 UpdateWindow( hwnd );

 MSG msg;

 while ( GetMessage( &msg, NULL, 0, 0 ) )

 DispatchMessage( &msg );

 return msg. wParam;

}

Программа 2.4. Графическая версия приложения "Hello, World!".

В предыдущей версии функция DrawHello просто выводила текстовую строку "Hello, World!" в контекст устройства, связанный с окном приложения. В новой версии эта функция устроена сложнее. Сначала она проверяет, не захвачена ли мышь каким-либо окном. Затем функция получает дескриптор контекста устройства, связанного с клиентской областью главного окна приложения. Затем выполняется захват мыши с помощью функции SetCapture. В режиме захвата мыши Windows будет посылать сообщения мыши непосредственно в окно, выполнившее захват.

Функция DrawHello также вызывает вспомогательную функцию AddSegmentAtMessagePos, которая в зависимости от своего третьего логического параметра, или перемещает текущую позицию рисования в точку указателя мыши из последнего сообщения, или рисует в эту точку отрезок из текущей позиции. Чтобы узнать координаты указателя мыши от последнего сообщения, применяется функция GetMessagePos. Функция AddSegmentAtMessagePos выполняет преобразование координат из экранной системы координат, в которой заданы координаты указателя мыши, в логическую систему координат окна, в которой выполняется рисование.

После вызова AddSegmentAtMessagePos функция DrawHello входит в цикл обработки сообщений. Пока мышь захвачена, мы ожидаем особого поведения от приложения, а именно, что траектория мыши будет отображаться внутри окна отрезками. Это обеспечивается функцией AddSegmentAtMessagePos, которая вызывается с третьим параметром TRUE при получении каждого сообщения WM_MOUSEMOVE.

Этот цикл обработки сообщений завершается, когда отпускается левая кнопка мыши, или когда приложение теряет захват мыши по какой-то другой причине. Тогда функция DrawHello возвращает управление и возобновляется выполнение главного цикла обработки сообщений в функции WinMain.

Действительно ли необходимы в этом приложении два цикла обработки сообщений? Вполне возможно обрабатывать сообщения WM_MOUSEMOVE в оконной процедуре, получая их в результате диспетчеризации из главного цикла обработки сообщений. Но предложенная структура программы делает исходный текст более понятным и позволяет избежать излишне громоздкой оконной процедуры.

8. Резюме

Каждое Windows-приложение строится на основе цикла обработки сообщений. В нем выполняется вызов функции для получения сообщения (GetMessage или PeekMessage), и последующая диспетчеризация сообщения в соответствующую оконную процедуру с помощью DispatchMessage.

Оконные процедуры приписываются оконным классам в момент регистрации с помощью функции RegisterClass. Типичная оконная процедура содержит оператор switch с ветвями case для всех сообщений, которые интересуют данное приложение. Остальные сообщения передаются оконной процедуре "по умолчанию" с помощью вызова функции DefWindowProc (или DefDlgProc для диалоговых окон).

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

9. Упражнения.

1)  В Visual C++ заведите новый проект типа Win32 Application и добавьте в него исходный файл с текстом программа 2.1. Скомпилируйте и запустите ее.

2)  Повторите действия, аналогичные заданию 1), для остальных версий приложения.

3)  Во 2-й версии "Hello, World!" попробуйте вместо стандартного класса BUTTON ("Кнопка") создать окно класса STATIC ("Статический текст").

4)  Посмотрите разделы справочной системы по функциям API, встречающимся в тексте приложений "Hello, World!".

5)  Разместите комментарии, поясняющие отдельные части 4-й версии "Hello, World!". Например, комментарии должны отмечать такие элементы программы, как цикл обработки сообщений, регистрация оконного класса или пояснять смысл отдельных функций API (назначение неизвестных функций API выясните в справочной системе).

6)  Выясните, сохраняется ли содержимое окна 3-й и 4-й версии "Hello, World!" при перемещении окна приложения по экрану или при изменении его размеров. Объясните, что происходит.

7)  Добавьте в 4-ю версию "Hello, World!" массив для хранения координат точек рисунка (в качестве типа элементов массива удобно использовать структуру из API POINT). Обеспечьте рисование содержимого окна при обработке сообщения WM_PAINT. Теперь при изменении размеров окно не должно очищаться.

Перед написанием функции-обработчика сообщения WM_PAINT проанализируйте содержимое функции DrawHello из п.3 и AddSegmentAtMessagePos из п.4.

8)  Добавьте в одну из программ обработчик события WM_CLOSE, который бы запрашивал у пользователя подтверждение о выходе из программы. Для организации запроса можно использовать стандартное окно сообщения:

MessageBox( hwnd, "Вы хотите завершить работу программы?",

"Завершение работы", MB_YESNO | MB_ICONQUESTION )

Этот вызов создает окно сообщения двумя кнопками "Да" и "Нет" и пиктограммой в виде вопросительного знака. В зависимости от нажатой кнопки, функция вернет IDYES или IDNO. Приложение должно завершать работу только при нажатии пользователем кнопки Да.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32