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

news2024/9/20 1:13:52

自定义资源(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使用的所有字符串都被定义为资源,所以程序很容易就能够被翻译人员转换为非英语版本。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源可视化Flutter图表库:Graphic

Graphic&#xff1a;用Graphic绘制数据的无限可能- 精选真开源&#xff0c;释放新价值。 概览 Graphic&#xff0c;这个基于Flutter的图表库&#xff0c;以其源自《The Grammar of Graphics》的灵感&#xff0c;为数据可视化提供了一种全新的方法。它不仅仅是一个工具&#xf…

安全策略与用户认证综合实验

一、实验拓扑 二、实验需求 1,DMZ区内的服务器,办公区仅能在办公时间内(9:00-18:00)可以访问,生产区的设备全天可以访问. 2,生产区不允许访问互联网,办公区和游客区允许访问互联网 3,办公区设备10.0.2.10不允许访问DMz区的FTP服务器和HTTP服务器,仅能ping通10.0.3.10 4,办公区…

【运维】docker批量删除临时镜像(两种方式)

docker批量删除Tag<none>的临时镜像 在开发的时候&#xff0c;需要经常发布开发包&#xff0c;在使用docker build构建镜像的时候&#xff0c;同一个版本经常会使用相同tag&#xff0c;频繁打包一段时间后&#xff0c;本地会出现很多Tag<none>的临时镜像&#xff…

WordPress知识付费系统+自动采集插件

采集功能&#xff1a; 1.支持分类替换 将主站同步过来的文章分类进行替换 2.支持自定义文章作者&#xff08;选择多个作者则同步到的文章作者将会随机分配&#xff09; 3.支持添加黑名单分类 添加后 如果同步过来的文章包含黑名单分类将不会发布文章 4.自动检测同步&#xf…

禁止使用存储过程

优质博文&#xff1a;IT-BLOG-CN 灵感来源 什么是存储过程 存储过程Stored Procedure是指为了完成特定功能的SQL语句集&#xff0c;经编译后存储在数据库中&#xff0c;用户可通过指定存储过程的名字并给定参数&#xff08;如果该存储过程带有参数&#xff09;来调用执行。 …

wifi ping ip地址可以但是域名失败

需求&#xff1a; 当连接上wifi之后获取&#xff0c;能正常获取IP并且能ping ip地址&#xff0c;但是不能ping域名&#xff0c;比如ping www.baidu.com 会显示坏地址 解决&#xff1a; 在/etc/resolv.conf中添加域名即可

NLP入门——词袋语言模型的搭建、训练与预测

卷积语言模型实际上是取了句子最后ctx_len个词作为上下文输入模型来预测之后的分词。但更好的选择是我们做一个词袋&#xff0c;将所有分词装在词袋中作为上下文&#xff0c;这样预测的分词不只根据最后ctx_len个分词&#xff0c;而是整个词袋中的所有分词。 例如我们的序列是&…

以太网的演变之路:技术进步与应用拓展

最初的以太网是由美国施乐&#xff08;Xerox&#xff09;公司的Palo Alto研究中心&#xff08;简称为PARC&#xff09;于1975年研制成功的。以太网从标准以太网&#xff08;10Mbit/s&#xff0c;也称为传统以太网&#xff09;开始逐步在有线局域网市场中占据了统治地位&#xf…

禁用windows的语音识别快捷键win+ctrl+s

win11组合键winctrls会弹出语音识别提示&#xff0c;即使到设置里禁用了语音识别也没用 解决办法&#xff1a;安装PowerToys&#xff0c;通过“键盘管理器”-“重新映射快捷键”禁用 PowerToys是微软自己的工具&#xff0c;不用担心安全问题&#xff0c;下载地址&#xff1a;h…

游戏视频是后期配音好还是边录边配 游戏视频怎么剪辑制作才能火 视频剪辑免费软件

游戏视频后期配音是先配还是先剪&#xff1f;游戏视频后期配音没有统一的准则&#xff0c;可以先配&#xff0c;也可以后配&#xff0c;主要是根据内容而定。游戏视频剪辑在游戏玩家中十分流行&#xff0c;那么&#xff0c;游戏视频怎么剪辑制作&#xff1f;下面让我们以具体的…

医院门诊预约挂号小程序模板源码

医院门诊预约挂号小程序模板源码,主要有&#xff1a;绿色的医院住院办理&#xff0c;门诊预约挂号微信小程序页面模板。包含&#xff1a;办卡绑定、快速办理预约挂号、门诊缴费、住院服务、医院信息、个人中心、添加就诊人、找医生等等。 医院门诊预约挂号小程序模板源码

zookeeper的shell操作

一&#xff1a;启动拽库的shell命令行 zkCli.sh -server localhost:2181 退出&#xff1a;quit 二&#xff1a;查询所有的命令 help 三&#xff1a;查询对应的节点 --查询zk上的根节点 ls / ls /zookeeper 四&#xff1a;查询对应节点的节点信息&#xff08;节点的元数据&a…

读人工智能全传09神经网络

1. 机器学习 1.1. 人们对人工智能的态度发生突如其来的巨大变化&#xff0c;是由一项核心人工智能技术——机器学习的快速发展所推动的 1.1.1. 机器学习是人工智能的一个分支领域&#xff0c;但在过去60年的绝大部分时间里&#xff0c;它一直在一条独…

MySQL 数据库支持存储emoji表情

当你通过node.js&#xff0c;往mysql存储emoji表情的时候&#xff0c;可能会遇到报错&#xff1a; code: ‘ER_TRUNCATED_WRONG_VALUE_FOR_FIELD’, errno: 1366, sqlMessage: “Incorrect string value: ‘\xF0\x9F\x8D\x94’ for column ‘nick_name’ at row 1”, sqlState…

大数据基础:Hadoop之MapReduce重点架构原理

文章目录 Hadoop之MapReduce重点架构原理 一、MapReduce概念 二、MapReduce 编程思想 2.1、Map阶段 2.2、Reduce阶段 三、MapReduce处理数据流程 四、MapReduce Shuffle 五、MapReduce注意点 六、MapReduce的三次排序 Hadoop之MapReduce重点架构原理 一、MapReduce概…

微积分-导数6(隐式导数)

隐式导数 前面我们学了如何求这些方程的导数&#xff1a; y x 3 1 or y x sin ⁡ x y \sqrt{x^31} \quad \text{or} \quad y x\sin x yx31 ​oryxsinx 但是如果是下面的方程&#xff0c;又该如何求导呢&#xff1f; x 3 y 3 6 x y x^3 y^3 6xy x3y36xy 这个方程的图…

【架构】分布式与微服务架构解析

分布式与微服务架构解析 一、分布式1、什么是分布式架构2、为什么需要分布式架构3、分布式架构有哪些优势&#xff1f;4、分布式架构有什么劣势&#xff1f;5、分布式架构有哪些关键技术&#xff1f;6、基于分布式架构如何提高其高性能&#xff1f;7、如何基于架构提高系统的稳…

企业资产管理系统带万字文档公司资产管理系统java项目java课程设计java毕业设计

文章目录 企业资产管理系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 企业资产管理系统 一、项目演示 企业资产管理系统 二、项目介绍 语言&#xff1a;java 数…

开始性能测试之前的准备工作!

性能测试是软件测试中不可或缺的一部分&#xff0c;它可以帮助我们评估软件系统的性能表现&#xff0c;并找出潜在的性能瓶颈。在进行性能测试之前&#xff0c;需要做好充分的准备工作&#xff0c;以确保测试的有效性和准确性。 1. 确定性能测试的目标和范围 * 明确测试目标:性…

Qt/QML学习-定位器

QML学习 定位器例程视频讲解代码 main.qml import QtQuick 2.15 import QtQuick.Window 2.15Window {width: 640height: 480visible: truetitle: qsTr("positioner")Rectangle {id: rectColumnwidth: parent.width / 2height: parent.height / 2border.width: 1Col…