Win32编程API 基础篇 -- 5.使用资源
使用资源
你可能想参考教程结尾的附近,为了获得跟VC++和BC++资源相关的信息。
在我们讲得更加深入之前,我将大致讲解一下资源的主题,这样在每个小节中我就不必再去重讲一遍了。在这一小节中,你不需要编译任何东西,这里的代码只是个例子。
资源是以二进制的格式存储在你的可执行文件内部的预定义的数据,在资源脚本中我们创建资源,所谓的资源脚本就是有”.rc”扩展名的群文件,商业编译器通常有一个视觉资源编辑器老让你在不需要手动编辑的情况下创建资源,但很多时候手动这是唯一的创建资源的方法,如果你的编译器没有视觉编辑器的话,或者它很糟糕,不支持你所需要的具体功能。
很不幸的是不同的编译器套件处理资源的方式是不一样的,我将竭尽所能来解释一般情况下资源工作的共同特征。
资源编辑器附带MSVC++使它很难手动编辑资源,因为它执行一个专有格式,并且如果你手动创建了一个资源,整个文件都可能被完全损坏,所以一般情况下你不应该打扰资源文件的创建,但是明白如何手动修改它们有时又是很有用的。另一个比较蛋疼的就是MSVC++将默认资源头文件的命名为“resuorce.h”即使你想使用其他命名。为了简单起见我将以这个文档中数据为基础,但在附录中会向您展示如何在编辑器中进行修改。
首先,让我们看一段非常简单的资源脚本,一个图标。
#include "resource.h" IDI_MYICON ICON "my_icon.ico"
这是整个的文件,IDI_MYICON是资源标识符,ICON是类型,“my_icon.ico”包含资源文件的扩展名,在所有的编译器中都应该生效。
#include "resource.h"跟什么相关呢?嗯,你的程序需要一种定义图标的方式,最好的方式就是分配一个唯一的ID(IDI_MYICON),我们可以通过创建一个“resource.h”文件然后在我们的资源脚本文件和源代码文件中引入。
#define IDI_MYICON 101
正如你所看到的,我们指定了IDI_MYICON的值为101,我们可以不使用定义直接使用101当引入图标的时候,但是IDI_MYICON引入的写法更加清爽,并且在大量引入资源文件的时候更容易记住。
现在让我们添加一个菜单资源:
#include "resource.h" IDI_MYICON ICON "my_icon.ico" IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
END
同样的IDR_MYMENU是资源的名称而MENU是资源类型。现在好点,看到了开始和结束了么?一些资源编辑器或编译器使用“{”和“}”分别用来替代BEGIN和END,如果你的编译器两个都支持随意选择其中一种方式。如果它只支持其中一种或者其他方式,你需要进行必要的更换工作保证正常使用。
我们也添加了一个新的标识符ID_FILE_EXIT,所以为了在我们的程序中使用,我们需要把它添加在我们的资源头文件resource.h中。
#define IDI_MYICON 101
#define ID_FILE_EXIT 4001
在大型的项目中生成和跟踪这些ID是一件很蛋疼的事,这就是大多数人使用为你完成这些工作的视觉资源编辑器的原因。但它仍然会时不时弄糟,你可能最终会遇到多个项目相同ID或类似的问题,这时候手动调整有利于解决问题。
现在下面有一个如何在你的程序中使用资源的栗子:
HICON hMyIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
LoadIcon和许多资源使用函数的第一个参数就是当前窗口实例的句柄(这个在我们的WinMain()中被给出了,同时也可以使用我们前面提到的GetModuleHandle()来得到这个句柄)第二个参数就是资源的标识符。
你可能会想MAKEINTRESOURCE()是用来干嘛的,也可能会想当我们要传递给LoadIcon()资源ID参数时,为什么会取一个LPCTSTR类型的参数而不是用UINT。所有的MAKEINTRESOURCE()做的事情就是把一个整型的ID变成LPCTSTR类型,而这是LoadIcon想要的参数类型。这就引出了定义资源的第二种方式,就是直接使用字符串,几乎不会有人再这样做,所以在这里我们简略说说,但是基本上如果你没有用#define的方式为你的资源指定ID,那么这个资源名就会被解析成字符串,在你的程序中可以这样子引用:
HICON hMyIcon = LoadIcon(hInstance, "MYICON");
LoadIcon()和其他加载资源的API可以区分传递的是一个资源ID还是一个指向字符串的指针通过检查这个值的高16位,如果高16位是0(整数的范围是0到65535)将被认定为传入的是一个资源ID,这很有效如果你限定你的资源ID在65535以下,这个应该够用了除非你有超多资源,所以应该没有问题;如果高16位不是0那么就会被认定为是一个指向字符串的指针,加载资源的函数就会通过资源名去查找资源。永远不要依赖于API去实现这个除非它在文档中被明确规定。
例如,这并不适合像ID_FILE_EXIT菜单命令,因为他们只能是整数。
PS.由于本人英文水平所限,只能翻译到这个程度了,有纰漏还望多多指出,附上本篇翻译的英文原版教程地址:http://www.winprog.org/tutorial/resources.html
Win32编程API 基础篇 -- 5.使用资源的更多相关文章
- Win32编程API 基础篇 -- 1.入门指南 根据英文教程翻译
入门指南 本教程是关于什么的 本教程的目的是向你介绍使用win32 API编写程序的基础知识(和通用的写法).使用的语言是C,但大多数C++编译器也能成功编译,事实上,教程中的绝大多数内容都适用于任何 ...
- Win32编程API 基础篇 -- 6.菜单和图标
菜单和按钮 例子:菜单1 本小节仅仅向你展示如果向你的窗口中加入一个基本的菜单,通常你会用到一个提前制作好的菜单资源,这会是一份.rc文件并且会被编译链接进你的.exe可执行程序中.这是具体的流程做法 ...
- Win32编程API 基础篇 -- 4.消息循环
消息循环 理解消息循环 为了编写任何即使是最简单的程序,了解windows程序的消息循环和整个消息发送结构是非常有必要的.既然我们已经尝试了一点消息处理的东西,我们应该对整个程序有更深入的理解,如果你 ...
- Win32编程API 基础篇 -- 3.消息处理 根据英文教程翻译
消息处理 例子:窗口点击 好的,现在我们已经得到一个窗口了,但我们什么也做不了除了DefWindowProc()允许窗口大小被调整,最大最小化等...这不是很激动人心啊 在接下来的一小节中我将向你展示 ...
- Win32编程API 基础篇 -- 2.一个简单的窗口 根据英文教程翻译
一个简单的窗口 例子:简单的窗口 有时人们在IRC提问,”我应该怎样制作一个窗口”...嗯,这恐怕不是完全这么简单好回答!其实这并不难一旦你明白你在做什么,但在你得到一个可展示的窗口之前还有一些事情需 ...
- ASP.NET Web API 基础篇1
ASP.NET Web API 直到我膝盖中了一箭[1]基础篇 无题 蓦然回首,那些年,我竟然一直很二. 小时候,读武侠小说的时候,看到那些猪脚,常常会产生一种代入感,幻想自己也会遭遇某种奇遇,遇到悬 ...
- (转)Android高性能编程(1)--基础篇
关于专题 本专题将深入研究Android的高性能编程方面,其中涉及到的内容会有Android内存优化,算法优化,Android的界面优化,Android指令级优化,以及Android应用内存占 ...
- 【TCP/IP】之Java socket编程API基础
Socket是Java网络编程的基础,深入学习socket对于了解tcp/ip网络通信协议很有帮助, 此文讲解Socket的基础编程.Socket用法:①.主要用在进程间,网络间通信. 文章目录如下: ...
- 我拖拖拖--H5拖放API基础篇
不要搞错,本文不是讲如何拖地的.看过<javascript精粹>朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用H5的新的拖放API就能非常方便的实现拖放效果了.最近在园子见 ...
随机推荐
- 309 Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期
Say you have an array for which the ith element is the price of a given stock on day i.Design an alg ...
- 【转】MySQL常见的运算符及使用
转自:http://www.linuxidc.com/Linux/2016-03/129672.htm MySQL中有4类运算符,它们是: 算术运算符 比较运算符 逻辑运算符 位操作运算符 算术操作符 ...
- 纵横填字map版(初始数据结构)
新数据结构设计: 定义一个map: key是横纵坐标字符串,比如“0,4” value是一个json,包含以下属性:字,横向的词(若 有的话,无的话,空串),纵向的词(若有的话,无的话,空串). 另有 ...
- sql剪切数据
实际项目当中用到的案例,个人笔记. USE [CA-SM]GO/****** Object: StoredProcedure [dbo].[PG_SM_AddSum] Script Date: ...
- java如何区分同时继承的父类和实现的接口中相同的方法
基类代码: public class Father { public Father() { System.out.println("基类构造函数{"); show(); Syste ...
- day16-常用模块I(time、datetime、random、os、sys、json、pickle)
目录 time模块 datetime模块 random模块 os模块 sys模块 json模块与pickle模块 json pickle time模块 time模块一般用于不同时间格式的转换,在使用前 ...
- arx 移动界面到一点
AcDbViewTableRecord view; AcGePoint3d max = acdbHostApplicationServices()->workingDatabase()-> ...
- 前端axios发送的数据后端接收不到(没有自动依赖注入)可能的原因
前端请求头content-type没有进行正确设置,后端无法解析该类型数据,比如说: 后端若想接收json类型的数据,则需要配置相应的转换器,(spring中可使用@RequestBody注解),若没 ...
- 计算机网络(二)--HTTP详解
Web相关内容都是存储在Web服务器上,Web服务器上使用的是http协议,因此也被成为http服务器.http的client.server构成了万维网的 基本组件 一.资源 1.URI: 统一资源标 ...
- java求两个集合的交集和并集,比较器
求连个集合的交集: import java.util.ArrayList; import java.util.List; public class TestCollection { public st ...