Win32编程API 基础篇 -- 5.使用资源

使用资源

  你可能想参考教程结尾的附近,为了获得跟VC++和BC++资源相关的信息。

  在我们讲得更加深入之前,我将大致讲解一下资源的主题,这样在每个小节中我就不必再去重讲一遍了。在这一小节中,你不需要编译任何东西,这里的代码只是个例子。

  资源是以二进制的格式存储在你的可执行文件内部的预定义的数据,在资源脚本中我们创建资源,所谓的资源脚本就是有”.rc”扩展名的群文件,商业编译器通常有一个视觉资源编辑器老让你在不需要手动编辑的情况下创建资源,但很多时候手动这是唯一的创建资源的方法,如果你的编译器没有视觉编辑器的话,或者它很糟糕,不支持你所需要的具体功能。

  很不幸的是不同的编译器套件处理资源的方式是不一样的,我将竭尽所能来解释一般情况下资源工作的共同特征。

  资源编辑器附带MSVC++使它很难手动编辑资源,因为它执行一个专有格式,并且如果你手动创建了一个资源,整个文件都可能被完全损坏,所以一般情况下你不应该打扰资源文件的创建,但是明白如何手动修改它们有时又是很有用的。另一个比较蛋疼的就是MSVC++将默认资源头文件的命名为“resuorce.h”即使你想使用其他命名。为了简单起见我将以这个文档中数据为基础,但在附录中会向您展示如何在编辑器中进行修改。

  首先,让我们看一段非常简单的资源脚本,一个图标。

1 #include "resource.h"
2
3 IDI_MYICON ICON "my_icon.ico"

  这是整个的文件,IDI_MYICON是资源标识符,ICON是类型,“my_icon.ico”包含资源文件的扩展名,在所有的编译器中都应该生效。

  #include "resource.h"跟什么相关呢?嗯,你的程序需要一种定义图标的方式,最好的方式就是分配一个唯一的ID(IDI_MYICON),我们可以通过创建一个“resource.h”文件然后在我们的资源脚本文件和源代码文件中引入。

1 #define IDI_MYICON  101

  正如你所看到的,我们指定了IDI_MYICON的值为101,我们可以不使用定义直接使用101当引入图标的时候,但是IDI_MYICON引入的写法更加清爽,并且在大量引入资源文件的时候更容易记住。

  现在让我们添加一个菜单资源:

 1 #include "resource.h"
 2
 3 IDI_MYICON ICON "my_icon.ico"
 4
 5 IDR_MYMENU MENU
 6 BEGIN
 7     POPUP "&File"
 8     BEGIN
 9         MENUITEM "E&xit", ID_FILE_EXIT
10     END
11 END

  同样的IDR_MYMENU是资源的名称而MENU是资源类型。现在好点,看到了开始和结束了么?一些资源编辑器或编译器使用“{”和“}”分别用来替代BEGIN和END,如果你的编译器两个都支持随意选择其中一种方式。如果它只支持其中一种或者其他方式,你需要进行必要的更换工作保证正常使用。

  我们也添加了一个新的标识符ID_FILE_EXIT,所以为了在我们的程序中使用,我们需要把它添加在我们的资源头文件resource.h中。

1 #define IDI_MYICON  101
2 #define ID_FILE_EXIT    4001

  在大型的项目中生成和跟踪这些ID是一件很蛋疼的事,这就是大多数人使用为你完成这些工作的视觉资源编辑器的原因。但它仍然会时不时弄糟,你可能最终会遇到多个项目相同ID或类似的问题,这时候手动调整有利于解决问题。

  现在下面有一个如何在你的程序中使用资源的栗子:

1 HICON hMyIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));

  LoadIcon和许多资源使用函数的第一个参数就是当前窗口实例的句柄(这个在我们的WinMain()中被给出了,同时也可以使用我们前面提到的GetModuleHandle()来得到这个句柄)第二个参数就是资源的标识符。

  你可能会想MAKEINTRESOURCE()是用来干嘛的,也可能会想当我们要传递给LoadIcon()资源ID参数时,为什么会取一个LPCTSTR类型的参数而不是用UINT。所有的MAKEINTRESOURCE()做的事情就是把一个整型的ID变成LPCTSTR类型,而这是LoadIcon想要的参数类型。这就引出了定义资源的第二种方式,就是直接使用字符串,几乎不会有人再这样做,所以在这里我们简略说说,但是基本上如果你没有用#define的方式为你的资源指定ID,那么这个资源名就会被解析成字符串,在你的程序中可以这样子引用:

1 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

时间: 2024-10-29 10:46:24

Win32编程API 基础篇 -- 5.使用资源的相关文章

Win32编程API 基础篇 -- 1.入门指南 根据英文教程翻译

入门指南 本教程是关于什么的 本教程的目的是向你介绍使用win32 API编写程序的基础知识(和通用的写法).使用的语言是C,但大多数C++编译器也能成功编译,事实上,教程中的绝大多数内容都适用于任何可以连接API的语言,包括Java.Assembly和Visual Basic:我不会向你呈现任何跟这些语言相关的代码,这需要你在本教程的指导下自己去完成,有一些人在本API的基础上使用其他语言进行编程取得了相当的成功. 本教程不会教你C语言,也不会告诉你怎样去运行你特定的编译器(Borland C

Win32编程API 基础篇 -- 6.菜单和图标

菜单和按钮 例子:菜单1 本小节仅仅向你展示如果向你的窗口中加入一个基本的菜单,通常你会用到一个提前制作好的菜单资源,这会是一份.rc文件并且会被编译链接进你的.exe可执行程序中.这是具体的流程做法,而商业编译器将会有一个资源编辑器,你可以通过这个编辑器来创建菜单,但是在这个例子中我会向你展示如何用.rc文件的手动写法.通常我会配合使用一个头文件,在资源文件和源文件中我们需要引入这个头文件,这个头文件中包含了控制和菜单选项等的标识符. 在本小节的栗子中,你可以按照指示在simple_windo

Win32编程API 基础篇 -- 3.消息处理 根据英文教程翻译

消息处理 例子:窗口点击 好的,现在我们已经得到一个窗口了,但我们什么也做不了除了DefWindowProc()允许窗口大小被调整,最大最小化等...这不是很激动人心啊 在接下来的一小节中我将向你展示如何修改现有的程序,让它做一些新的事情,这样我就可以告诉你,“处理消息然后这样做...”,我会明白我的意思是什么并且在不需要看完完整的栗子的基础上完成它.所以不管怎样,集中注意力 OK,对初学者来说拿最近的一个窗口程序的代码,保证编译通过并且正常运行,然后你就可以在这份代码的基础上进行一些小修改,或

Win32编程API 基础篇 -- 4.消息循环 根据英文教程翻译

理解消息循环 为了编写任何即使是最简单的程序,了解windows程序的消息循环和整个消息发送结构是非常有必要的.既然我们已经尝试了一点消息处理的东西,我们应该对整个程序有更深入的理解,如果你没有理解消息是怎么发生的和它们运行的机制,那接下来的内容你会感到很蛋疼. 什么是消息? 一条消息是一个整数值,如果你查阅你的头文件(这是个好的查阅API的工作惯例)你会发现像下面的东西: 1 #define WM_INITDIALOG 0x0110 2 #define WM_COMMAND 0x0111 3

Win32编程API 基础篇 -- 2.一个简单的窗口 根据英文教程翻译

一个简单的窗口 例子:简单的窗口 有时人们在IRC提问,”我应该怎样制作一个窗口”...嗯,这恐怕不是完全这么简单好回答!其实这并不难一旦你明白你在做什么,但在你得到一个可展示的窗口之前还有一些事情需要我们去做,我们只需要简单地聊聊快速做下笔记,这个问题就能被很简单的回答. 我很喜欢先动手再学习...一下就是一个简单的窗口的程序,我们将会简短的对它进行解释说明. 1 #include <windows.h> 2 3 const char g_szClassName[] = "myWi

shell脚本编程之基础篇(二)

shell脚本编程之基础篇(二) ============================================================================== 概述: ============================================================================== 退出状态 ★进程使用退出状态来报告成功或失败 ◆0 代表成功,1-255代表失败 ◆$? 变量保存最近的命令退出状态 (查看:echo $?)

(转)Android高性能编程(1)--基础篇

关于专题     本专题将深入研究Android的高性能编程方面,其中涉及到的内容会有Android内存优化,算法优化,Android的界面优化,Android指令级优化,以及Android应用内存占用分析,还有一些其他有关高性能编程的知识.    随着技术的发展,智能手机硬件配置越来越高,可是它和现在的 PC 相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于 PC 的桌面应用程序.以上理由,足以需要开发人员更加专心去实现和优化你的代码了.选择合适的算

Java socket编程API基础

Socket是Java网络编程的基础,深入学习socket对于了解tcp/ip网络通信协议很有帮助, 此文讲解Socket的基础编程.Socket用在哪里:①.主要用在进程间,②.网络间通信. 文章目录如下: 一.Socket通信基本示例 二.消息通信优化 2.1 双向通信,发送消息并接受消息 2.2 使用场景 2.3 如何告知对方已发送完命令 2.3.1 通过Socket关闭 2.3.2 通过Socket关闭输出流的方式 2.3.3 通过约定符号 2.3.4 通过指定长度 三.服务端优化 3.

Java中基于UDP协议的的网络编程(基础篇)

---恢复内容开始--- 一:什么是网络编程? 通俗的来说, 网络编程就是编写程序,让联网的两个或多个设备(例如计算机)之间进行数据传输.Java语言也支持网络编程,JDK提供的 java.net包提供了很多于网络编程相关的类,来支持网络编程方面的学习. 二:java网络编程所使用的协议? 有了计算机网络的基础,我们不难理解,在java中,网络编程是基于网络传输协议的. java网络编程,可以是基于TCP协议的,也可以基于UDP协议的.那么首先我们得知道tcp协议和udp两种协议的区别. 区别: