Итак, мы добрались до следующего урока: Dialogs, GUI coders best friend. Здесь мы пытаемся модифицировать наше окошко с меню так, чтобы в меню нам выводилась какая-то информация. Добавим к файлу dlg_one.rc новые строчки:
#include "resource.h"
#include <windows.h>
IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Stuff"
BEGIN
MENUITEM "&Go", ID_STUFF_GO
MENUITEM "G&o somewhere else", 0, GRAYED
END
END
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\nby theForger",
IDC_STATIC,16,18,144,33
END
IDI_MYICON ICON "dlg_one.ico"
Ошибка RC2104
Но, если оставить фрагмент кода IDD_ABOUT DIALOG без изменений, то при компиляции получим ошибку:
Нужное нам определение содержится в файле WinUser.h:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\WinUser.h
Можно было бы дополнить файл resource.h такой строчкой:
#ifndef DS_MODALFRAME
#include <WinUser.h>
#endif
#include <windows.h>
Но увы, пока это не поможет. Сам файл находится в этой папке:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um
Компилятор ресурсов rc.exe не сможет найти нужный файл:
Он его не найдёт даже в том случае, если мы добавим путь в переменную окружения PATH. Чтобы выйти из этого затруднительного положения, придётся создать новую переменную окружения, под названием include. Замечу, что мы создадим переменную окружения для текущего пользователя.
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um
Ошибка RC1015
Хорошо, мы добавили этот путь в новую переменную окружения, но получили новую ошибку:
Этот файл находится в другой папке:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared
А вот здесь есть маленькая проблема, т.к. если мы нажмём кнопку include. Хотя… Сможем, но для этого нужно будет сначала дописать к старому значению символ
Ещё одна ошибка RC1015
Внеся изменения в переменную окружения include и перезапустив VSCode, мы получаем новую ошибку компилятора ресурсов:
С подобным мы уже сталкивались, поэтому сейчас просто добавляем к переменной ещё одно значение:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include
На этот раз диалог редактирования переменной изменился. Благодаря тому, что мы указывали значения через точку с запятой, система понимает, что данная переменная является массивом и, для добавления нового значения теперь появилась кнопка
4. К сожалению, ошибки полностью не устранились. На этот раз мы получаем такую ошибку:
Добавляем новый путь к переменной окружения include, после чего перезапускаем VSCode:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
5. Ещё одна ошибка:
Данное ключевое слово описано в файле afxres.h, который относится к MFC. Но я не устанавливал эти библиотеки, поэтому попробую обойтись без этого. Дополню файл resource.h:
#ifdef IDC_STATIC
#undef IDC_STATIC
#endif
#define IDC_STATIC (-1) // all static controls
Функция обратного вызова Callback
Функция Callback нам уже встречалась в наших ранних примерах, но я на ней не заострял внимание, т.к. занимался исправлением ошибок компилятора. Сейчас мы добрались до того момента, когда ей нужно уделить более пристальное внимание. Итак, добавив файл dlg_one.rc описанием диалогового окна, нам необходимо описать Процедуру Диалога (Dialog Procedure) для обработки событий в диалоговом окне. Здесь ничего нового и всё практически идентично нашему раннему проекту окошка с меню, но не во всём.
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
Между Процедурой Диалога и Процедурой Окна есть несколько важных отличий. Во-первых мы НЕ вызываем дефолтовую Процедуру Окна DefWindowProc() для обработки сообщений, которые не обработаны вручную. С Диалогами это делается автоматически (если это сделать, можно серьёзно налажать).
Во-вторых, вы возвращаете значение FALSE для сообщений, которые не обрабатываются, но только до тех пор, пока нужно вернуть какое-то иное значение. В примере выше это видно.
В-третьих, мы не вызываем уничтожение окна DestroyWindow(), чтобы закрыть диалоговое окно. Мы вызываем EndDialog(). Во втором параметре передаётся значение, которое возвращается в код программы, вызвавшей DialogBox().
Наконец, вместо того, чтобы обрабатывать WM_CREATE, мы обрабатываем WM_INITDIALOG, где происходит описание всего необходимого перед тем, как появится окошко диалога, и затем возвращается TRUE для того, чтобы передать фокус для управления с клавиатуры. (Вообще-то также можно обрабатывать и WM_CREATE, но у вас не будет доступа к элементам управления, т.к. он создаётся раньше их, а в WM_INITDIALOG они уже будут созданы).
Здесь мне пришлось опять поковыряться, т.к. вывалились ошибки связанные с необъявленными идентификаторами. Для их устранения, необходимо добавить в файл resource.h следующие строчки:
#define ID_HELP_ABOUT 9002
#define IDD_ABOUT 100
Правда мы получим новую ошибку:
В файле WinUser.h объявлено, что функция DialogBoxParamW должна возвращать значение типа INT_PTR:
Ну, либо можно посмотреть на MSDN, там то же самое.
Таким образом, данная ошибка устраняется, если объявить CALLBACK-функцию AboutDlgProc по другому:
INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
Ошибки
В оригинальной статье этого раздела нет. Там всё здорово. Там и многих других «букв» тоже небыло, т.к. не было ошибок при компиляции. Тот код компилировали как C-код, а не С++. Там был другой компилятор и, явно другоя операционная система (максимум Windows 7, причём не 64 бита). В итоге, даже устранив все ошибки компиляции, я всё равно не могу корректно запусть программу. Сейчас ошибку выдаёт меню ▶ :
Казалось бы всё правильно, мы всё скопировали согласно той статье. Ну да, только автор почему-то забыл указать, что мы создали новый файл из старого.
В новом проекте у нас в меню теперь ▶ заменён на ▶ ! Но код вызывается старый. Т.е. у нас нет нового кода, отсюда и ошибка.
Исправленный и полный код файла dlg_one.rc будет таким:
#include "resource.h"
#include <windows.h>
IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About", ID_HELP_ABOUT
MENUITEM "G&o somewhere else", 0, GRAYED
END
END
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\nby theForger",
IDC_STATIC,16,18,144,33
END
IDI_MYICON ICON "dlg_one.ico"
Ну вот, вроде всё разгрёб :)
- C#: Сравнить два массива - 12.12.2024
- EVE-Online: Фильтры каналов - 23.11.2024
- Не приходит СМС для авторизации на сайте Госуслуги - 01.11.2024