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就能非常方便的实现拖放效果了.最近在园子见 ...
随机推荐
- 讯搜问题排查xunsearch
mysql导入数据不成功,开始重建索引后提示 [XSException] ../local/xunsearch/sdk/php/lib/XS.php(1898): DB- 可打印的版本 开始重建索引 ...
- daily_journal_3 the game of thrones
昨晚追完了最爱的美剧(the game of thrones),哇,看到结局有点崩溃.果然还是美帝淫民开放,各种乱伦,在七夕收到的万点暴击就祝天下有情人就像剧中一样终是血亲. 昨天算是完成了git的复 ...
- 用 jQuery 实现简单倒计时功能
问题场景:假设某个活动截止时间给定了,现在需要开发一个页面可以自动刷新距离活动截止时间还剩多少天? <!DOCTYPE html> <html xmlns="http:// ...
- 386 Lexicographical Numbers 字典序排数
给定一个整数 n, 返回从 1 到 n 的字典顺序.例如,给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] .请尽可能的优化算法的时间复杂度和空间复杂度. 输入 ...
- mvc使用linq to sql进行sum统计遇到查询为null的问题
mvc linq to sql,linq to entity,sum,null 昨天写了段sum的统计语句, decimal sums sums = ( from fac in db.Apply wh ...
- Android开发: 关于性能需要考虑的
刚做Android开发时,只管完成任务,将需求完成,以能完成一款界面酷炫的app为自豪.然而,随着代码量的增加,越来越意识到,一款成功的移动端产品,光有酷炫的外衣还不够,还需要在各方面都优秀. 试想, ...
- 安卓TV盒子常见问题以及解决方法
1.为什么requestfocus无效 原因:requestfocus不支持在Touch模式下的Focus; 解法方案:再加一个requestFocusFromTouch函数. 2.摄像头打开问题,调 ...
- LDA主题模型(理解篇)
何谓“主题”呢?望文生义就知道是什么意思了,就是诸如一篇文章.一段话.一个句子所表达的中心思想.不过从统计模型的角度来说, 我们是用一个特定的词频分布来刻画主题的,并认为一篇文章.一段话.一个句子是从 ...
- Windows Server 2008不能Ping改为允许的方法
用了Windows Server 2008朋友肯定都知道,2008在很多设置方面与2003不同,尤其在安全上进行了加强,例如:默认情况下Windows 2008是不允许PING的,那么如何打开允许PI ...
- 在eclipse里如何快速定位到某一行?
使用快捷键ctrl+L讲每一行的行号显示出来:在eclipse的某一行的最左边,右键——show Line Numbers就可以将行数都显示出来.