如何将图片等资源编译进程序,而不是在程序运行时以文件形式载入。
在win32编程中,为方便项目中的资源统一管理,提供了一个格式统一的资源文件.rc,对各种资源进行管理
在vc++中,会使用rc.exe对.rc文件进行编译,生成.res的汇编文件,使用cl.exe编译c/c++文件,生成.obj的汇编文件,由link.exe链接这些文件和user32.lib生成.exe
在mingw编译器中,使用windres.exe对.rc文件进行编译,使用g++/gcc对源文件进行编译再进行链接
使用windres.exe编译rc文件的方法
创建一个res文件夹,包含ico图标和bmp图片资源
res文件夹下创建一个Resource.h,定义资源ID,包括两个图标ID和一个图片ID
res文件夹下创建一个rc文件Resource.rc,编辑内容
//包含头文件
#include <windows.h>
#include "Resource.h"
//包含图片资源的格式,资源id 资源类型 路径
IDI_ICON_0 ICON "appIcon.ico"
IDI_ICON_1 ICON "windowIcon.ico"
IDB_BITMAP_0 BITMAP "bg.bmp"
res文件夹的内容,包含2个ico图标,1个bmp图片,一个Resource.h和Resource.rc
使用windres编译它们
会多了一个Resource.o文件,这就是编译完成的目标文件,其中包含了图标和图片资源
建立一个测试文件
a0118.cpp
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const char CLASS_NAME[] = "test Class";
WNDCLASSA wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassA(&wc);
// Create the window.
HWND hwnd = CreateWindowExA(
0, // Optional window styles.
CLASS_NAME, // Window class
"Window", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
使用命令对其与资源文件编译,进行链接
windres res/Resource.rc -o res/Resource.o
g++ -c a0118.cpp
g++ a0118.o res/Resource.o -o a.exe -lgdi32
结果产生的exe文件图标变成了appIcon.ico这个图标文件,因为会选中资源ID最小的图标作为程序图标
但窗体图标并没有改变
包含Resource.h,通过向窗体发送消息WM_SETICON,设置图标ID
#include "res/Resource.h"
...
//设置窗体图标 IDI_ICON_1
HICON hIcon = LoadIcon((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON_1));
SendMessage(hwnd,WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessage(hwnd,WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
之后再进行编译链接就可以设置窗体图标了
背景的绘制
窗体的WM_PAINT事件处理中绘制窗体背景IDB_BITMAP_0
case WM_PAINT://背景图片绘制
{
HBITMAP hBitmap;
BITMAP bitmap;
hBitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_0));
GetObject(hBitmap, sizeof(bitmap), &bitmap);
PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd, &ps);
HDC memdc = CreateCompatibleDC(dc);
SelectObject(memdc, hBitmap);
RECT rc;
GetClientRect(hwnd,&rc);
SetStretchBltMode(dc,COLORONCOLOR);
int showWidth = rc.right-rc.left;
int showHeight = rc.bottom-rc.top;
StretchBlt(dc,rc.left,rc.top,showWidth,showHeight,memdc,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
DeleteDC(memdc);
EndPaint(hwnd, &ps);
}
程序代码
#include <windows.h>
#include "res/Resource.h"
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const char CLASS_NAME[] = "test Class";
WNDCLASSA wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassA(&wc);
// Create the window.
HWND hwnd = CreateWindowExA(
0, // Optional window styles.
CLASS_NAME, // Window class
"Window", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
//设置图标
HICON hIcon = LoadIcon((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON_1));
SendMessage(hwnd,WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessage(hwnd,WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT://背景图片绘制
{
HBITMAP hBitmap;
BITMAP bitmap;
hBitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_0));
GetObject(hBitmap, sizeof(bitmap), &bitmap);
PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd, &ps);
HDC memdc = CreateCompatibleDC(dc);
SelectObject(memdc, hBitmap);
//BitBlt(dc,0,0,bitmap.bmWidth,bitmap.bmHeight,memdc,0,0,SRCCOPY);
RECT rc;
GetClientRect(hwnd,&rc);
SetStretchBltMode(dc,COLORONCOLOR);
int showWidth = rc.right-rc.left;
int showHeight = rc.bottom-rc.top;
StretchBlt(dc,rc.left,rc.top,showWidth,showHeight,memdc,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
DeleteDC(memdc);
DeleteObject(hBitmap);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}