当前位置: 首页 > 工具软件 > rc-arrow > 使用案例 >

PW系列 | 用windres 编译.rc 资源文件

严成礼
2023-12-01

版权

本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/127183433.

Original

最近在学习Charles Petzold 的《Programming Windows》第五版. 第10 章"Menus and Other Resources" 开始用到资源文件(用来定义界面布局元素, 图标, 国际化字符串等). 但书中是Visual Studio, 而本地是mingw-w64 + Eclipse CDT. 经摸索可以如下使用资源文件(用10-1 ICONDEMO 程序做试验).

test.rc 资源文件

在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.

改用int 标志资源

test.rc:

1 ICON "ICONDEMO.ICO"

C:

......
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));
......
hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1));

.RC常见问题

忘记include 头文件

例如"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

头文件里忘记define 常量

例如11-11 POPPAD3 的头文件"RESOURCE.H" 里没有定义常量"IDC_STATIC", 而在"POPPAD.RC" 里用到了:

......
    ICON "POPPAD",IDC_STATIC,7,7,20,20

用windres 编译时将总是出错.

DIALOG x/y 坐标为-1

例如11-9 HEXCALC 的"HEXCALC.DLG" 里:

HexCalc DIALOG −1, −1, 102, 122
......

编译将报错. 改成0 后可以.

附录

代替的资源编辑器

可以尝试resource hacker:
http://www.angusj.com/resourcehacker/

ICONDEMO.C 源码

/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
 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);
}
 类似资料: