本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/127183433.
最近在学习Charles Petzold 的《Programming Windows》第五版. 第10 章"Menus and Other Resources" 开始用到资源文件(用来定义界面布局元素, 图标, 国际化字符串等). 但书中是Visual Studio, 而本地是mingw-w64 + Eclipse CDT. 经摸索可以如下使用资源文件(用10-1 ICONDEMO 程序做试验).
在ICONDEMO.C 同一目录放置编辑好的ICONDEMO.ICO 图标文件; 再创建一个test.rc 资源文件:
desk1 ICON "ICONDEMO.ICO"
在C 中用字符串"desk1" 引用该资源:
......
wndclass.hIcon = LoadIcon(hInstance, TEXT("desk1"));
......
hIcon = LoadIcon(hInstance, TEXT("desk1"));
在该目录:
C:\Users\ASUS\eclipse-workspace\HelloWorld>where windres
C:\msys64\mingw64\bin\windres.exe
C:\Users\ASUS\eclipse-workspace\HelloWorld>windres -i test.rc -o test.o -v --use-temp-file
生成test.o 文件.
注意: 一定要使用"--use-temp-file" 选项, 否则(默认用popen/管道) 总是会报错:
C:\Users\ASUS\eclipse-workspace\HelloWorld>windres -i test.rc -o test.o
windres: test.rc:2: syntax error
test.rc:1: fatal error: when writing output to : Invalid argument
1 | desk1 ICON "ICONDEMO.ICO"
|
compilation terminated.
windres: preprocessing failed.
进入"Debug" 子目录编译:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o ICONDEMO.o "..\\ICONDEMO.C"
g++ -mwindows -o HelloWorld.exe ICONDEMO.o "..\\test.o"
生成HelloWorld.exe.
test.rc:
1 ICON "ICONDEMO.ICO"
C:
......
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));
......
hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));
例如"VK_BACK" 是Windows 常量, 需include windows.h:
#include <windows.h>
......
POPPAD2 ACCELERATORS
BEGIN
VK_BACK, IDM_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
例如"IDM_FILE_NEW" 由程序自定义, 需include 所在头文件(“POPMENU.H”):
#include "POPMENU.H"
......
MENUITEM "&New", IDM_FILE_NEW
例如11-11 POPPAD3 的头文件"RESOURCE.H" 里没有定义常量"IDC_STATIC", 而在"POPPAD.RC" 里用到了:
......
ICON "POPPAD",IDC_STATIC,7,7,20,20
用windres 编译时将总是出错.
例如11-9 HEXCALC 的"HEXCALC.DLG" 里:
HexCalc DIALOG −1, −1, 102, 122
......
编译将报错. 改成0 后可以.
可以尝试resource hacker:
http://www.angusj.com/resourcehacker/
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ICONDEMO.C −− Icon Demonstration Program
(c) Charles Petzold, 1998
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include <windows.h>
//#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow) {
static TCHAR szAppName[] = TEXT("IconDemo");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
// wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));
wndclass.hIcon = LoadIcon(hInstance, TEXT("desk1"));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Icon Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static HICON hIcon;
static int cxIcon, cyIcon, cxClient, cyClient;
HDC hdc;
HINSTANCE hInstance;
PAINTSTRUCT ps;
int x, y;
switch (message) {
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
// hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));
hIcon = LoadIcon(hInstance, TEXT("desk1"));
cxIcon = GetSystemMetrics(SM_CXICON);
cyIcon = GetSystemMetrics(SM_CYICON);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (y = 0; y < cyClient; y+= cyIcon)
for (x = 0; x < cxClient; x += cxIcon)
DrawIcon(hdc, x, y, hIcon);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}