《Windows API每日一练》9.1.5 自定义资源

自定义资源(Custom Resources)是在 Windows 程序中使用的一种资源类型,用于存储应用程序特定的数据、图像、音频、二进制文件等。通过自定义资源,开发者可以将应用程序所需的各种资源文件集中管理和存储,便于在程序中访问和使用。

以下是一些关于自定义资源的要点:

●自定义资源的类型:

1.自定义资源可以是任何应用程序特定的数据或文件,如图像、音频、XML 配置文件、文本文件等。

2.自定义资源可以使用自定义的资源类型标识符进行标识,例如 "MY_CUSTOM_RESOURCE"。

●创建和编辑自定义资源:

1.自定义资源通常包含在应用程序的资源文件(.rc)中。

2.使用资源编辑器(如 Visual Studio 的资源视图)可以创建和编辑自定义资源。

3.在资源文件中,可以为每个资源指定唯一的资源标识符和对应的资源文件路径。

●引用和使用自定义资源:

1.在代码中引用和使用自定义资源时,可以使用资源标识符来加载或访问对应的资源。

2.使用相应的 API 函数(如 LoadResource、FindResource、LockResource 等)来加载和操作自定义资源。

3.根据自定义资源的类型,可以使用不同的 API 函数(如图像资源可以使用 GDI 函数、音频资源可以使用 DirectSound 函数)来处理自定义资源。

■下面是一个示例代码片段,展示了如何加载和使用自定义资源:

#include <Windows.h>

int main()

{

    HINSTANCE hInstance = GetModuleHandle(NULL);  // 获取当前实例句柄

    HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(IDR_MY_RESOURCE), "MY_CUSTOM_RESOURCE");  // 查找自定义资源

    HGLOBAL hResData = LoadResource(hInstance, hResource);  // 加载自定义资源

    LPVOID pData = LockResource(hResData);  // 锁定自定义资源

    // 使用自定义资源...

    return 0;

}

在上述示例中,IDR_MY_RESOURCE 是自定义资源的标识符,在资源文件中定义了对应的资源文件路径。使用 FindResource 函数查找自定义资源,然后使用 LoadResource 函数加载自定义资源,最后使用 LockResource 函数锁定自定义资源以获取指向资源数据的指针。随后,可以根据资源的类型和需求,使用指针 pData 进行后续的处理和操作。

需要注意的是,自定义资源的具体使用方式取决于资源类型和应用程序的需求。开发者可以根据实际需求选择合适的资源类型和对应的 API 函数来处理自定义资源。

自定义资源为应用程序提供了一种灵活的资源管理方式,可以将应用程序所需的各种数据和文件统一管理,并方便地在程序中访问和使用。通过使用自定义资源,可以使应用程序更加模块化、可维护和可扩展。

       ■在VS中添加自定义资源

1、添加资源

 2、点击“自定义”,填写资源类型“TEXT"

 3、导入资源,自动生成text1.bin文件,资源ID:IDR_TEXT1

 4、VS中直接在自定义编译器中输入资源文件名并修改ID报错:无法加载外部资源——可能的原因是资源未导入。

5、在资源视图框中添加资源。

6、导入外部资源文件。

7、重新填写资源文件名和ID,注意ID名称需要填写带引号的字符串"ANNABELLEE"。

8、保存设置之后就可以了

 

还有一种更简单的方法,直接修改资源文件POEPOEM.rc。TEXT下方画线处添加资源即可。

      

9.1.6 第57练:字符串资源表和自定义资源

/*------------------------------------------------------------------------

 057 WIN32 API 每日一练

     第57个例子POEPOEM.C:字符串资源表和自定义资源

     LoadString 函数   

     LoadResource 函数 

     FindResource 函数 

     LockResource 函数 

     AnsiNext 宏定义

 (c) www.bcdaren.com 编程达人

-----------------------------------------------------------------------*/

#include <windows.h>

#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

HINSTANCE hInst ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{   //资源文件名,标题和错误信息

     TCHAR szAppName[16], szCaption[64], szErrMsg[64];

     HWND hwnd;

     MSG msg;

     WNDCLASS wndclass;

     //加载字符串资源

     LoadString(hInstance, IDS_APPNAME, szAppName,

          sizeof(szAppName) / sizeof(TCHAR));

     LoadString(hInstance, IDS_CAPTION, szCaption,

          sizeof(szCaption) / sizeof(TCHAR));

     wndclass.style = CS_HREDRAW | CS_VREDRAW;

     wndclass.lpfnWndProc = WndProc;

     wndclass.cbClsExtra = 0;

     wndclass.cbWndExtra = 0;

     wndclass.hInstance = hInstance;

//添加图标

     wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

     //wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

//自定义鼠标指针

     wndclass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));

     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

     wndclass.lpszMenuName = NULL;

     wndclass.lpszClassName = szAppName;

     //hInst = hInstance;//原代码中没有,且不会报错

     if (!RegisterClass(&wndclass))

     {

          //LoadStringA(hInstance, IDS_APPNAME, (char *)szAppName,

          //     sizeof(szAppName));

          LoadStringA(hInstance, IDS_ERRMSG, (char *)szErrMsg,

               sizeof(szErrMsg));

          MessageBoxA(NULL, (char *)szErrMsg,

               (char *)szAppName,

               MB_ICONERROR);

          return 0;

     }

     hwnd = CreateWindow(szAppName, szCaption,

          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,

          CW_USEDEFAULT, CW_USEDEFAULT,

          CW_USEDEFAULT, CW_USEDEFAULT,

          NULL, NULL, hInstance, NULL);

     ShowWindow(hwnd, iCmdShow);

     UpdateWindow(hwnd);

     while (GetMessage(&msg, NULL, 0, 0))

     {

          TranslateMessage(&msg);

          DispatchMessage(&msg);

     }

     return msg.wParam;

}

LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM

lParam)

{

     //static char * pText;

     static LPCSTR pText;

     static HGLOBAL hResource;//资源句柄-指向内存块的句柄

     static HWND hScroll;

     static int iPosition, cxChar, cyChar, cyClient,

          iNumLines, xScroll;

     HDC hdc;

     PAINTSTRUCT ps;

     RECT rect;

     TEXTMETRIC tm;

     switch (message)

     {

     case WM_CREATE:

          hdc = GetDC(hwnd);

          GetTextMetrics(hdc, &tm);

          cxChar = tm.tmAveCharWidth;

          cyChar = tm.tmHeight + tm.tmExternalLeading;

          ReleaseDC(hwnd, hdc);

//垂直滚动条的宽度,以像素为单位

          xScroll = GetSystemMetrics(SM_CXVSCROLL);

          //生成滚动条

          hScroll = CreateWindow(TEXT("scrollbar"), NULL,

               WS_CHILD | WS_VISIBLE | SBS_VERT,

               0, 0, 0, 0,

               hwnd, (HMENU)1, hInst, NULL);

          //获取文本句柄

          hResource = LoadResource(hInst,

               FindResource(hInst, TEXT("AnnabelLee"),//确定具有指定类型和名称

的资源在指定模块中的位置

                    TEXT("TEXT")));

          //检索指向内存中指定资源的指针

          pText = (LPCSTR)LockResource(hResource);

          iNumLines = 0;//读取文本行数

          //获取文本行数

          while (*pText != '\\' && *pText != '\0')//遇\或\0结束

          {

               if (*pText == '\n')

                    iNumLines++;

                //返回ansi字符串中的下一个位置(指针),AnsiNext为16位Windows上

//的一个宏定义,Win32使用CharNext代替(AnsiNext只能处理ansi字符

//串;而CharNext可以ansi,也可以unicode字符串)

                //pText = AnsiNext(pText);

               pText = (LPCSTR)CharNext((LPCWSTR)pText);

          }

     //*pText = '\0';//此处原代码中说明以空字符结尾---实际文本不是以空字符结尾

          //设置滚动条

          SetScrollRange(hScroll, SB_CTL, 0, iNumLines, FALSE);

          SetScrollPos(hScroll, SB_CTL, 0, FALSE);

          return 0;

     case WM_SIZE:

          MoveWindow(hScroll, LOWORD(lParam) - xScroll, 0,

               xScroll, cyClient = HIWORD(lParam), TRUE);

          SetFocus(hwnd);//设置焦点

          return 0;

     case WM_SETFOCUS:

          SetFocus(hScroll);//捕捉滚动条滑块焦点

          return 0;

     case WM_VSCROLL:

          switch (LOWORD(wParam))  //须加LOWORD,因为通知码在低位字

          {

          case SB_TOP:

               iPosition = 0;

               break;

          case SB_BOTTOM:

               iPosition = iNumLines;

               break;

          case SB_LINEUP:

               iPosition -= 1;

               break;

          case SB_LINEDOWN:

               iPosition += 1;

               break;

          case SB_PAGEUP:

               iPosition -= cyClient / cyChar;

               break;

          case SB_PAGEDOWN:

               iPosition += cyClient / cyChar;

               break;

          case SB_THUMBTRACK:

               iPosition = HIWORD(wParam);

               break;

          }

          iPosition = max(0, min(iPosition, iNumLines));

          if (iPosition != GetScrollPos(hScroll, SB_CTL))

          {

               SetScrollPos(hScroll, SB_CTL, iPosition, TRUE);

               InvalidateRect(hwnd, NULL, TRUE);

          }

          return 0;

     case WM_PAINT:

          hdc = BeginPaint(hwnd, &ps);

          pText = (char *)LockResource(hResource);

          GetClientRect(hwnd, &rect);

          rect.left += cxChar;//从第2列开始显示

          rect.top += cyChar * (1 - iPosition);

          //包括字体外部行首高度。通常,外部行首不包括在一行文本的高度中。

          DrawTextA(hdc, pText, -1, &rect, DT_EXTERNALLEADING);

          EndPaint(hwnd, &ps);

          return 0;

     case WM_DESTROY:

          FreeResource(hResource);

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd, message, wParam, lParam);

}

/******************************************************************************

LoadString 函数:加载字符串资源,然后将字符串复制到带有终止空字符的缓冲区中,

或者返回指向字符串资源本身的只读指针。

*******************************************************************************

LoadResource 函数:检索可用于获取指向内存中指定资源的第一个字节的指针的句柄

HGLOBAL LoadResource(

  HMODULE hModule,//其可执行文件包含资源的模块的句柄。如果hModule为NULL,则系统将从用于创建当前进程的模块中加载资源

  HRSRC   hResInfo//要加载的资源的句柄

);

*******************************************************************************

FindResource 函数:确定具有指定类型和名称的资源在指定模块中的位置

HRSRC FindResourceA(

  HMODULE hModule,//包含资源的模块的句柄

  LPCSTR  lpName,//资源的名称

  LPCSTR  lpType//资源的类型

);

*******************************************************************************

LockResource 函数:检索指向内存中指定资源的指针

LPVOID LockResource(

  HGLOBAL hResData//要访问的资源的句柄

);

*******************************************************************************

AnsiNext 宏定义:

16位Windows上的一个api函数(准确地说是一个宏定义),只能处理ansi字符串;

后来Win32出现的时候,微软为了兼容,封装就是通过CharNext来实现的。

CharNext可以ansi,也可以unicode字符串。

该函数的就是返回ansi字符串中的下一个位置(指针)。

*/

Resource.h头文件

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 057_POEPOEM.rc 使用

//

#define IDS_APPNAME                     1

#define IDS_Caption                     2

#define IDS_CAPTION                     3

#define IDS_ERRMSG                      4

#define IDI_ICON1                       1

#define IDC_CURSOR1                     2

#define IDR_TEXT1                       107

#define IDR_TEXT2                       108

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        126

#define _APS_NEXT_COMMAND_VALUE         40002

#define _APS_NEXT_CONTROL_VALUE         1001

#define _APS_NEXT_SYMED_VALUE           101

#endif

#endif

057_POEPOEM.rc资源脚本文件包含4种类型资源:

1.图标资源:

// Icon

//

IDI_ICON1 ICON     "D:\\code\\windows5.0\\A daily

practice\\057_POEPOEM\\057_POEPOEM\\icon1.ico"

2.鼠标指针位图资源:

// Cursor

//

IDC_CURSOR1             CURSOR                  "cursor1.cur"

3.字符串资源表:

// String Table

//

STRINGTABLE

BEGIN

    IDS_APPNAME             "PoePoem"

    IDS_CAPTION             """Annabel Lee"" by Edgar Allan Poe"

    IDS_ERRMSG              "This program requires Windows NT!"

END

4.自定义资源:

// TEXT

//

ANNABELLEE              TEXT                    "POEPOEM.TXT"

运行结果:

图9-9 字符串资源表和自定义资源

 

总结

在POEPOEM.RC资源脚本中,用户定义资源被指定为TEXT类型,文本名字为 "ANNABELLEE" :ANNABELLEE TEXT POEPOEM.TXT

在WndProc中处理WM_CREATE消息时,该资源的句柄通过FindResource和LoadResource 来获得。LockResource将该资源锁定,一个小的例程将文件尾部的反斜杠(\)替换为0。这是为了方便在后面的WM_PAINT消息中使用DrawText函数。

【注意】我们使用了子窗口滚动条控件而不是窗口滚动条。该子窗口滚动条控件有一个自动键盘接口,所以在POEPOEM中不需要处理WM_KEYDOWN消息。

POEPOEM还使用了三个字符串,它们的ID在RESOURCE.H头文件中定义。在程序的开始,IDS_APPNAME和IDS_CAPTION字符串被LoadString加载到内存:

LoadString (hlnstance, IDS_APPNAME, szAppName,

sizeof (szAppName) /sizeof (TCHAR));

LoadString (hlnstance, IDS_CAPTION, szCaption,

sizeof (szCaption) /sizeof (TCHAR));

【注意】这两个调用在RegisterClass之前。程序用LoadStringA加载IDS_APPNAME和 IDS_ERRMSG字符串,并用MessageBoxA来显示自定义消息框:

if (!RegisterClass (&wndclass))

{

LoadStringA (hInstance, IDS_APPNAME, (char *) szAppName,

sizeof (szAppName)) ;

LoadStringA (hInstance, IDS_ERRMSG, (char *) szErrMsg,

sizeof (szErrMsg)) ;

MessageBoxA (NULL, (char *) szErrMsg,

(char *) szAppName, MB_ICONERROR) ;

return 0 ;

}

【注意】从TCHAR字符串变量到char指针的强制转换。

AnsiNext为16位Windows上的一个宏定义,Win32使用CharNext代替(AnsiNext只能处理ansi字符串;而CharNext可以ansi字符串,也可以unicode字符串)。

pText = AnsiNext(pText);

替换为:

pText = (LPCSTR)CharNext((LPCWSTR)pText);

由POEPOEM使用的所有字符串都被定义为资源,所以程序很容易就能够被翻译人员转换为非英语版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/791287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为HCIP Datacom H12-821 卷34

1.单选题 防火墙默认已经创建了一些安全区域,以下哪一个安全区域不是防火墙上默认存在的? A、Trust B、DMZ C、Internet D、Local 正确答案&#xff1a; C 解析&#xff1a; 防火墙默认情况下为我们提供了三个安全区域&#xff0c;分别是 Trust、DMZ和Untrust 2.判断题 …

【RHCE】实验(HTTP,DNS,SELinux,firewalld的运用)

一、题目 二、主服务器配置 1.下载HTTP服务&#xff0c;DNS服务 [rootlocalhost ~]# yum install -y httpd bind 2.开启防火墙&#xff0c;放行服务 # 开启防火墙 [rootlocalhost ~]# systemctl start firewalld # 放行服务 [rootlocalhost ~]# firewall-cmd --add-service…

日常学习-20240710

1、一次一千万条数据插入和删除案例&#xff1a; 第一次&#xff1a;插入--批量插入&#xff0c;每次插入5000条数据&#xff0c;总耗时28min,数据无异常 删除--通过sql语句一次性删除&#xff0c;总耗时1h52min;一次删除的数据过多导致mysql的备份恢复文件极其庞大&#xff0…

在CentOS7虚拟机上使用Ollama本地部署Llama3大模型中文版+Open WebUI

一、创建虚拟机 1.1按照常规的CentOS教程来安装就行&#xff0c;我用的是以下版本&#xff1a; VMware版本&#xff1a;VMware Workstation Full v12.1.0-3272444 中文正式版 镜像版本&#xff1a;CentOS-7-x86_64-DVD-2009 1.2虚拟机配置参数&#xff0c;如下&#xff1a; 二…

彩虹小插画:成都亚恒丰创教育科技有限公司

彩虹小插画&#xff1a;色彩斑斓的梦幻世界 在繁忙的生活节奏中&#xff0c;总有一抹温柔的色彩能悄然触动心弦&#xff0c;那就是彩虹小插画带来的梦幻与宁静。彩虹&#xff0c;这一自然界的奇迹&#xff0c;被艺术家们巧妙地融入小巧精致的插画之中&#xff0c;不仅捕捉了瞬…

Camera Raw:直方图

Camera Raw 的直方图 Histogram面板不仅提供了照片亮度和色彩分布信息&#xff0c;还具备多项实用功能&#xff0c;辅助评估和调整照片。 ◆ ◆ ◆ 直方图的构成 直方图是一个二维坐标系统&#xff0c;横坐标表示不同程度的像素亮度&#xff0c;从左到右通常对应的是 0 ~ 255…

14-60 剑和诗人34 - Kubernetes 是部署 LLM 的首选平台

​​​​ 介绍 近年来&#xff0c;大型语言模型 (LLM) 一直在彻底改变自然语言处理领域。从 GPT-3 到 PaLM 等&#xff0c;这些模型可以生成类似人类的文本、回答问题、总结文档等等。然而&#xff0c;训练和部署 LLM 需要大量的计算。随着这些模型的规模和能力不断增长&#…

three完全开源扩展案例01-三角形渐变

演示地址 import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.client…

Golang | Leetcode Golang题解之第227题基本计算器II

题目&#xff1a; 题解&#xff1a; func calculate(s string) (ans int) {stack : []int{}preSign : num : 0for i, ch : range s {isDigit : 0 < ch && ch < 9if isDigit {num num*10 int(ch-0)}if !isDigit && ch ! || i len(s)-1 {switch preS…

免杀笔记 ---> Session0--DLL注入

刚更新完上一篇&#xff0c;于是我们就马不停蹄的去跟新下一篇&#xff01;&#xff01; Session0注入 &#xff1a;&#xff1a; 各位看官如果觉得还不错的可以给博主点个赞&#x1f495;&#x1f495; 这次&#xff0c;我把这个脚本直接传到Github上了 喜欢的师傅点个Star噢…

VScode代码对齐快捷键

解决复制过来代码对齐格式问题。 左对齐&#xff1a;Ctrl[ 右对齐&#xff1a;Ctrl]

科普文:jvm笔记

一、JVM概述# 1. JVM内部结构# 跨语言的平台&#xff0c;只要遵循编译出来的字节码的规范&#xff0c;都可以由JVM运行 虚拟机 系统虚拟机 VMvare 程序虚拟机 JVM JVM结构 HotSpot虚拟机 详细结构图 前端编译器是编译为字节码文件 执行引擎中的JIT Compiler编译器是把字节…

WPF Menu实现快捷键操作

很多小伙伴说&#xff0c;在Menu中&#xff0c;实现单个快捷键操作很简单&#xff0c;怎么实现多个快捷键操作和&#xff0c;组合快捷键呢&#xff0c;今天他来了。 上代码和效果图 一、Ctrl Shift 任意子母键实现快捷键组合 <Window x:Class"XH.TemplateLesson.M…

Collections集合工具类简介

Collections集合工具类 特点&#xff1a;构造私有&#xff0c;方法都是静态的&#xff0c;通过类名直接调用 static <T> boolean addAll(Collection<? super T> c, T... elements) 作用&#xff1a;批量添加元素 public class Test {public static void main(S…

如何将若依vue升级到springboot3.x?

为了确保项目符合要求,Spring Boot 3.x 要求Java版本为17或更高。 1、修改根目录下的pom.xml文件 <!-- java.version版本8更换为17 --> <java.version>17</java.version><!-- 新增节点 --> <mybatis-spring-boot.version>3.0.3<

线性代数|机器学习-P22逐步最小化一个函数

文章目录 1. 概述2. 泰勒公式3. 雅可比矩阵4. 经典牛顿法4.1 经典牛顿法理论4.2 牛顿迭代法解求方程根4.3 牛顿迭代法解求方程根 Python 5. 梯度下降和经典牛顿法5.1 线搜索方法5.2 经典牛顿法 6. 凸优化问题6.1 约束问题6.1 凸集组合 Mit麻省理工教授视频如下&#xff1a;逐步…

初识C++语言(1)

目录 C语言简介 C 语言概述 C 语言的特点 语言简洁紧凑&#xff0c;使用灵活方便 运算符丰富 数据结构丰富 结构化语言 生成的代码质量高 可移植性强 C程序结构 C语言系统的使用 一.启动Dev-C 二、新建源程序 三…

华为ensp实现防火墙的区域管理与用户认证

实验环境 基于该总公司内网&#xff0c;实现图片所在要求 后文配置请以本图为准 接口配置与网卡配置 1、创建vlan 2、防火墙g0/0/0与云页面登录 登录admin,密码Admin123&#xff0c;自行更改新密码 更改g0/0/0口ip&#xff0c;敲下命令service-manage all permit 网卡配置…

什么是平值、实值、虚值期权合约?有哪些区别?

今天带你了解什么是平值、实值、虚值期权合约&#xff1f;有哪些区别&#xff1f;期权按执行价格与标的物市价的关系可分为实值期权、平值期权和虚值期权。 平值期权、实值期权和虚值期权是描述期权合约相对于标的资产当前价格的位置的术语&#xff1a; 1.平值期权&#xff0…

11计算机视觉—语义分割与转置卷积

目录 1.语义分割应用语义分割和实例分割2.语义分割数据集:Pascal VOC2012 语义分割数据集预处理数据:我们使用图像增广中的随机裁剪,裁剪输入图像和标签的相同区域。3.转置卷积 上采样填充、步幅和多通道填充步幅多通道转置卷积是一种卷积:重新排列输入和核转置卷积是一种卷…