WinAPI. Перемещение и изменение размеров окна

Сегодня я поделюсь демкой, которая демонстрирует как приходят сообщения при изменении размеров и при перемещении окна. Там же есть несколько контрольных вопросов. Обратите внимание на то, в какой системе координат и какие параметры передаются вместе с сообщениями WM_SIZE и WM_MOVE. Также я добавил меню, в котором можно управлять перемещением окна и его размерами. Все операции завязаны на использовании функции MoveWindow.

Демка с исходниками

Контроль знаний по WinAPI

Привет всем, кто волею случая наткнулся на этот блог. Этой статьей я начинаю цикл публикаций, смыслом которого будет заключаться в самоконтроле знаний по WinAPI. Дело в том, что по WinAPI существуют достаточно хорошие книги и все там прекрасно разжевано (книги Петцольда, Щупака, Ганеева, Рихтера, библиотека братьев Фроловых). Чтива навалом, короче. Поэтому, я их содержание повторять здесь не буду. Также я не буду заниматься такой глупой и безнадежной вещью, как объяснение того, зачем нужно изучать WinAPI — это каждый решает для себя сам.

Что я здесь буду описывать и для чего?

Дело в том. что даже от чтения хороших книг особых знаний у вас не прибавится, если вы не будете практиковаться и задавать себе контрольные вопросы. Без этого все прочитанное также быстро улетучивается из памяти как быстро оно туда попало. Если вы просто читаете книги по программированию и не практикуетесь — вы зря теряете время, потому что вы это все опять забудете и придется читать сначала.

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

Итак, начну я с такой банальной вещи как создание простого оконного приложения.

Простое оконное приложение под Windows

1. Напечатайте прототип функции «WinMain». Расскажите об ее параметрах.
2. Что такое класс окна? Зачем он нужен?
Напечатайте прототип и расскажите о смысле параметров функции «RegisterClassEx».
3. Что возвращает функция «RegisterClassEx» в случае ошибки?
4. Напечатайте список членов класса «WNDCLASSEX» и опишите их.
5. Какие идентификаторы стиля класса окна обеспечивают его автоматическую
перерисовку при изменении размеров окна?
6. Как задать в классе окна стандартную иконку?
7. Как задать в классе окна стандартный курсор-стрелку?
8. Как задать в классе окна цвет кисти фона (например, белый)?
9. Напечатайте прототип функции «CreateWindow». Что она возвращает в случае ошибки?
10. Напечатайте стиль перекрывающегося окна.
11. Как задать параметры x,y,nWidth, nHeight по умолчанию?
12. Как вывести созданное окно на экран? Приведите пример и опишите функцию.
13. Приведите пример простейшего цикла сообщений приложения. Расскажите как он работает.
14. Напечатайте прототип функции «GetMessage». Опишите параметры и смысл возвращаемых значений.
15. В чем опасность этого цикла:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

// ? приведите правильный вариант.
16. Напечатайте прототип функции TranslateMessage. Опишите, что она делает.
17. Что делает функция DispatchMessage и какие у нее параметры?
18. Напечатайте прототип функции обработчика сообщений окна.
19. Напечатайте минимальный обработчик сообщений окна.

Тестовое задание — написать приложение windows с одним простым окном, не пользуясь никакими справочниками.

 

Ответы и решения*:
5.  Ответ: CS_HREDRAW, CS_VREDRAW.

6. Решение:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

7. Решение:
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

8. Решение:
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);

10.  Ответ: WS_OVERLAPPEDWINDOW.

11. Ответ: передать константу CW_USEDEFAULT.

12.  Решение:
ShowWindow(hwnd, SW_SHOWNORMAL);

15. Решение:
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0 )
{
if (bRet == -1)
{
// Обработка ошибки, выход
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

19. Решение:

LRESULT CALLBACK

WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

Пример выполнения тестового задания: BaseWindow1


 

Там, где я не указал ответов, они либо устные либо нужно смотреть в MSDN/книгу.

Лайфхак №1. Упрощение ввода макроопределений в Code::blocks

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

Итак. Сегодня я расскажу как быстрее вводить определения макросов на C/C++ в среде разработки Code::Blocks. Статья ориентирована на использование Code::Blocks версии 10.05.

Что ж, начнем! В Code::Blocks существует замечательная возможность написания собственных аббревиатур, которые могут быть заменены блоком кода. Для создания аббревиатуры нужно зайти в Settings…Editor…Abbreviations. Далее следует нажать на кнопку «Add» под колонкой «Keywords». Появится диалоговое окошко, в котором нужно ввести «DF» без кавычек. Это будет именем нашей аббревиатуры для быстрого ввода макроопределений. Теперь нужно выделить эту аббревиатуру в списке других аббревиатур и в правой колонке с названием «Code:» ввести следующий текст:

#define $(ID)        $(ID_value)|

Знак доллара означает что далее в круглых скобках будет имя, которое будет заменено пользователем. При этом будет показан диалог «Macro substitution» с полем ввода «Please enter the text for «слово, что стоит в скобках после знака доллара«. Знак вертикальной черты означает положение каретки.

Чтобы воспользоваться аббревиатурой необходимо напечатать в тексте вашей программы слово «DF» без кавычек и нажать комбинацию клавиш «Ctrl+J». Появится диалог с предложением ввести имя идентификатора для замены слова «ID» — нужно ввести его. После этого появится еще один диалог, в котором нужно ввести значение для этого идентификатора. После чего вы увидите в тексте кода вместо слова «DF» запись макроопределения.

Слова «ID» и «ID_value» можно заменить любыми другими. Это просто названия.

В чем смысл? Обычно макроопределения пишутся с использованием заглавных букв. И как правило их бывает много (например, при создании ресурсов приложения). Можно один раз нажать клавишу «Caps Lock». И далее вместо утомительного ввода символа решетки, слова «define» и постоянного переключения регистра символов, можно просто вводить пару символов DF, комбинацию клавиш «Ctrl+J», название и значение макроопределения. Каретка в конце аббревиатуры позволит просто нажать Enter, чтобы перейти к следующей строке.

На этом все. Плодотворного вам кодинга!