作为一个可执行的应用程序文件,应该包含2部分,一部分是数据区,另一部分是程序代码区。数据区一般可分为2类:读写数据和只读数据。对于windows程序,有大量的只读数据。所谓资源就是应用程序运行期间通常不能更改或不需要更改的数据。
windows程序资源有以下几种:
- 加速键 Accelerator
- 位图 Bitmap
- 光标 Cursor
- 对话框 Dialog
- HTML
- 图标 Icon
- 菜单 Menu
- 字符串表 String Table
- 工具条 ToolBar
- 版本 version
- 以及用户自定义的资源。
1.资源的使用方法
- 定义资源
- 加载资源
- 使用资源
定义资源:资源出的创建和用户的程序时分离的,资源是以rc为扩展名的资源描述文件中,而再以cpp作为扩展名的源代码文件中,资源需要使用定义语句描述后才能使用.
资源描述问价语句,并不是c/c++语句,而是特殊的资源语句.你可以新建一个win32程序,然后用VS打开该程序的.rc文件.一旦创建了.rc文件,就可以使用资源编辑器将其译成.res文件,然后被链接到.exe文件中.
加载资源:尽管资源数据也是作为应用程序文件的一部分,但在程序装入内存是,它并不自动装入,而是由程序根据需要,通过调用API函数来装入,这个过程称为资源的加载.
每种资源的加载函数不同,但是大致的格式相似.资源加载函数都是以load加上具体的资源名来命名的,如加载图标的函数是LoadIcon(),加载光标是LoadCursor().
使用资源:每种资源的定义和加载过程大同小异,但是资源的使用就不尽相同了.每种资源使用的概念、使用的具体方法和步骤都有可能不同,需要结合具体的情况讲解.
1.图标的使用
当你打开一个人应用程序是,应用程序的左上角会有一个图标,对应于下面的任务栏也会有一个图标,这两个图标分别对应以下两句:
wcex.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));//IDI_ICON1是我自己的图标。
wcex.hIconSm = LoadIcon(NULL, IDI_QUESTION);
那么就给我们指明了修改应用程序图标的方向:在窗口类注册的时候修改。如果你想动态修改图标,那么可能还需要用到WM_SETICON消息。
- 一个Icon就是一个小的位图,一般是代表一个应用程序的特殊最小位图。同常用的资源一样,你可以使用系统预定义资源和你自己定义的,系统预定义的图标是一些常见的形状,用宏定义方式,所以使用的时候不需要使用转换宏:MAKEINTERSOURCE。但是要注意,使用系统预定义的图标时,LoadIcon的第一个参数要设为NULL。下面是IDI_QUESTION的图标截图:
可以看到变成了一个问号。 - vs是集成了资源编辑器的,所以你也可以自己编一个图标。具体操作是:视图->资源视图->Icon->右键->添加资源->Icon->新建。系统会自动生成一个名为IDI_ICON1的图标。利用编辑工具可以编辑自己的图标,如下:
注意如果你只是选择了其中的一种格式进行编辑,则需要删除其它的格式。右键删除图标类型即可。
然后去ATOM MyRegisterClass(HINSTANCE hInstance)函数里面将wcex.Icon改为IDI_ICON1即可。
- 在新建资源的时候,我们也看到还有其它的选项,其中有一个是导入,我们自己画的可能不那么好,这是可以导入别人创建的,如下:
导入了一个256*256的彩色图片,导入后,直接在原来的地方改一下名字即可,效果如下:
2.光标的使用
光标是表示当前鼠标的形状,从本质上来说也是一个图像,作为资源Cursor,其使用方法和和Icon的使用类似。在注册窗口类时,同样有这一句:wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
也就是说我们可以在这儿修改,系统预定义的光标类型有箭头,十字形,手型,沙漏型等等比如改为手型,就将IDC_ARROW改为IDC_HAND。
- 当使用系统光表时,LoadCursor的第一个参数需要设置为NULL。这种改变只在客户窗口区有效,如果要在整个框架内都有效,需要在创建消息WM_CREATE中设置。
- 当然也可以自己绘制一个光标,如下是我绘制的一个光标:
绘制完成后,将原来的IDC_ARROW修改为IDC_CURSOR1,注意还要将LoadCursor的第一个参数改为当前的实例,即hInstance,否则LoadCursor会加载失败。加载成功后的例子:
- 同样自己绘制的效果有限,可以导入别人绘制好的光标,不要将一个位图强行改为.cur格式,去网上下吧,有很多好看的。例如我导入一个如下:
然后直接替换第二个参数就可以了
3.位图的使用
位图是一种数字化的图形表示,是表示一个图像目标的具体数据。前面的Icon、Cursor本质上都是 图像,只是文件的存储格式不同。
- 使用位图要定义位图,位图通常是用户自定义的资源,因为系统很难确定用户经常使用的位图资源,它不想光标和图标有大家默认的、熟悉的预定义的图像。同样你可以利用资源编辑器绘制位图,或者加载位图,一般加载位图用的较多,加载位图的函数是
HBITMAP LoadBitmap(HINSTANCE hInstance,LPCTSTR lpBitmaoName);
参数hInstance为包含该位图的应用程序实例句柄,lpBitmapName是资源文件中的位图名字。
注意:位图是一种资源,使用时一定要先加载位图;通常在用户区显示位图,这是一种输出操作,需符合windows应用输出的过程步骤;位图是一种GDI绘图工具对象,必须将该工具选进DC中才能使用,因此位图和Icon,Curson有差别。
3.图像所包含的数据量比较大,所以为了提高刷新速度,位图操作通常必须先在内存中进行,这就是通常说的先画内存,再画图像。因此,用于位图操作的的系统设备描述表通常称为内存设备描素表。先画内存,再画屏幕,即位图最后还是要在某个输出设备上显示,,例如,在屏幕上,那就意味着,这个内存和后面的输出设备是有关系的,故而获取内存设备描述表调用的是CreateCompatibleDC函数,他的原型如下:`HDC CreateCompatibleDC(HDC hDC);参数hDc指定一个已经存在的DC, 通常就是位图最终要现在在哪个设备的DC,NULL表示已经存在的设备就是当前应用窗口的屏幕,函数表示创建一个与hDc所指定的设备描述表相兼容的的内存设备描述表。函数创建成功,返回的是内存设备描述表,失败则返回NULL。显示位图可以调用函数bitblt或StretchBlt,前者按照原图大小进行显示,后者可以对图像进行缩放。
其中StretchBlt函数的原型如下:
BOOL StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);
hdcDest:指向目标设备环境的句柄。
hdcSrc:指向源设备环境的句柄。
nXOriginDest:指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。
nYOriginDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
nWidthDest:指定目标矩形的宽度,按逻辑单位表示宽度。
nHeightDest:指定目标矩形的高度,按逻辑单位表示高度。
nXOriginSrc:指向源矩形区域左上角的X轴坐标,按逻辑单位表示坐标。
nYOriginSrc:指向源矩形区域左上角的Y轴坐标,按逻辑单位表示坐标。
nWidthSrc:指定源矩形的宽度,按逻辑单位表示宽度。
nHeightSrc:指定源矩形的高度,按逻辑单位表示高度。
dwRop:指定要进行的光栅操作。光栅操作码定义了系统如何在输出操作中组合颜色,这些操作包括刷子、源位图和目标位图等对象。
- 下面是具体的代码:
先导入一张位图:
然后我们在WM_PAINT消息里面实现显示。
“`
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HICON hIcon;
//先声明几个全局变量
HDC hMemdc;
BITMAP bitmap;
HBITMAP hbitmap;
switch (message)
{
case WM_COMMAND:
……
……
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
hMemdc=CreateCompatibleDC(hdc);//创建兼容的内存DC
hbitmap=LoadBitmap(hInst,(LPCTSTR)IDB_BITMAP2);//加载位图资源
SelectObject(hMemdc,hbitmap);//将位图选进内存DC。
GetObject(hbitmap,sizeof(BITMAP),&bitmap);//获取位图信息
StretchBlt(hdc,20,20,200,200,hMemdc,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);//显示
DeleteDC(hMemdc);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
效果如下:
我们将其放大试试,不仅改变了大小,还改变了长宽比,可以看到边缘出现了锯齿。
同样你还可以改变参数实现裁剪
BitBlt函数与此类似,就不再赘述。
String资源
String资源使用很简单,在StringTable中定义一个字符串,使用LoadString加载到全局内存中,即可使用。
在以下几处地方涉及代码:
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
TCHAR buff[100];// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SOURCE, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDS_STRING104, buff, MAX_LOADSTRING);- hWnd = CreateWindow(szWindowClass, buff, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
我们完全可以参照系统自动生成的字符串来实现,通过上面几步,标题变为:
未完待续。。。。