В одной из заметок был описан пример создания окошка с помощью WinAPI C++. Возникающие в VSCode ошибки мы устранили. Затем я перешёл к примеру, в первой части которого к окошку добавили меню, а к исполняемому файлу был добавлен значок программы. Всё бы хорошо, но теперь мы стали использовать ресурсы (значок и меню), а для этого пришлось кое-что переделать в настройках VSCode. Но обо всём по порядку.
Файл resource.h
Чтобы не было путаницы, я создал новую папку проекта. Затем добавил в неё новый файл resource.h:
#define IDR_MYMENU 101
#define IDI_MYICON 201
#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002
Файл menu_one.rc
Далее мы создаём файл ресурсов проекта. Мы создаём его вручную, поэтому он текстовый, а не двоичный. У файла должно быть расширение .rc. Содержимое файла menu_one.rc будет таким:
#include "resource.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
IDI_MYICON ICON "menu_one.ico"
Меню мы сделали совсем простым и тут должно быть всё понятно. На сайте оригинальной статьи я не нашёл файл со значком, поэтому использовал иконку своего сайта:
https://dentnt.trmw.ru/favicon.ico
Просто переименовал его на новое имя: menu_one.ico
При компиляции этого файла ресурсов мы можем получить такую ошибку:
The terminal process «C:\Windows\System32\cmd.exe /d /c «C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\rc.exe» menu_one.rc» terminated with exit code: 1.
Порывшись в инете я обнаружил, что это проблема компилятора ресурсов rc.exe.
Настройка VSCode для компиляции файла ресурсов
Чтобы было проще компилировать файлы ресурсов, я добавил ещё одну задачу в файл tasks.json:
{
"label": "C/C++: convert to RES file",
"detail": "Convert current file from .rc to .res",
"type": "shell",
"command": "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\rc.exe",
"args": ["${fileBasenameNoExtension}.rc"]
}
Это был фрагмент кода для задачи. Чтобы её легко можно было вызвать, я добавил новую комбинацию клавиш
{
"key": "ctrl+shift+c",
"command": "workbench.action.tasks.runTask",
"args": "C/C++: convert to RES file"
},
Файл menu_one.cpp
Изменим наш файл window_click.cpp для работы с файлом ресурсов. Теперь в программе будет отображаться значок и меню. Файл menu_one.cpp:
#define UNICODE
#pragma comment(lib, "user32.lib")
#include <windows.h>
#include "resource.h"
const wchar_t g_szClassName[]= L"myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
{
wchar_t szFileName[MAX_PATH];
HINSTANCE hInstance = GetModuleHandle(NULL);
GetModuleFileName(hInstance, szFileName, MAX_PATH);
MessageBox(hwnd, szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
/* Adding menu and icon */
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0);
/******/
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Здесь мы добавили такую строчку:
#pragma comment(lib, "user32.lib")
Это позволило нам избавится от таких ошибок компилятора:
C:\Users\Denis\source\repos\WinAPI\Sample04\build\menu_one.exe : fatal error LNK1120: 14 unresolved externals
Сборка проекта
А всё потому, что мы собирали проект без учёта файлов ресурсов. Чтобы прилинковать файлы ресурсов, нам потребуется новая задача. Я не знаю, нужно ли мне это будет в будущем, поэтому создам задачу только для данного проекта. Для этого я в папке с проектом создам папку .vscode. В ней я создам новый файл tasks.json:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "C/C++: cl.exe build active file and link resources",
"detail": "Compile and build selected C++ project with Visual Studio cl.exe and link resources",
"type": "shell",
"command": "${config:buildCommand}",
"args": [
"/Zi",
"/EHsc",
"/Fe:",
"${config:buildDir}\\${fileBasenameNoExtension}.exe",
"/Fo${config:buildDir}\\",
"/Fd${config:buildDir}\\",
"${file}",
"/link",
"/SUBSYSTEM:WINDOWS",
"${workspaceFolder}\\${fileBasenameNoExtension}.res"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": ["$msCompile"],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": [
"Set dependencies for build"
]
}
]
}
Как видно, здесь мы добавили пару новых ключей для добавления к проекту файла ресурсов .res.
Всвязи с этим нужно подправить данную настройку в следующем файле:
«C:\Users\Denis\AppData\Roaming\Code\User\settings.json»
Здесь нам нужно закомментировать, либо удалить строчку:
"preLaunchTask": "C/C++: cl.exe build active file"
Таким образом мы не будем перекомпилировать файл перед выполнением «Start Debugging» либо «Start without Debugging.
Для запуска сборки проекта можно задать горячие клавиши в файле keybindings.json:
{
"key": "ctrl+shift+b",
"command": "workbench.action.tasks.runTask",
"args": "C/C++: cl.exe build active file and link resources"
},
- C#: Сравнить два массива - 12.12.2024
- EVE-Online: Фильтры каналов - 23.11.2024
- Не приходит СМС для авторизации на сайте Госуслуги - 01.11.2024