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

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

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

相关文章

SpringBoot3+Redis实现分布式锁

SpringBoot3RedisLua脚本实现分布式锁 相关依赖包 <spring-boot.version>3.0.2</spring-boot.version> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </depende…

训练营第九天 | 151.翻转字符串里的单词、55.右旋转字符串、总结回顾

一、题目 151.翻转字符串里的单词 做题思路 代码细节 卡码网&#xff1a;55.右旋转字符串 做题思路 代码细节 二、总结回顾 &#xff08;一&#xff09;字符串总结 代码随想录 &#xff08;二&#xff09;双指针回顾 代码随想录

python多进程刻画进度

问题 python多进程启动4个任务&#xff0c;当前共20个任务&#xff0c;如何刻画当前进度&#xff1f; 解决方案 在 Python 中使用多进程处理多个任务并刻画当前进度&#xff0c;你可以使用 multiprocessing 模块和一个共享变量&#xff08;如 multiprocessing.Value 或 multi…

imx6ull/linux应用编程学习(17)利用mqtt上传开发板数据,和控制开发板led(基于正点)

1.关于如何创建自己的服务器&#xff0c;可看上篇文章 imx6ull/linux应用编程学习&#xff08;16&#xff09;emqx &#xff0c;mqtt创建连接mqtt.fx-CSDN博客 2.实现任务&#xff1a;&#xff08;正点原子教程源码改&#xff09; (1)用户可通过手机或电脑远程控制开发板上的…

小白的OS Copilot 产品测评

背景 通过群友介绍才知OS Copilot 。不想错过任何优秀的AI产品。随着互联网的发展和时代的进步&#xff0c;要紧跟时代&#xff0c;了解市面上的优秀的AI科技产品。 OS Copilot 产品体验评测 1&#xff09;您的角色是什么&#xff1f;开发、运维、学生&#xff1f;如果使用O…

Unity中短路法在背包系统的应用

一、计数法 int counter 0;foreach(GameObject slot in slotList) {if(slot.transform.childCount > 0){counter 1;} }return counter 21;计数法的复杂度为 O(n)&#xff0c;其中n 是插槽的数量。无论插槽是否已满&#xff0c;都会遍历所有插槽。 二、短路法 foreach (…

服务器怎么进PE系统?

服务器进PE是指将服务器的操作系统切换到预安装环境&#xff08;Pre-Installation Environment&#xff09;的状态。在PE环境下&#xff0c;可以进行一些系统管理和故障排除的操作。在进入PE&#xff08;Preinstall Environment&#xff09;之前&#xff0c;首先需要确保你的服…

类和对象——【const成员】【static成员】【友元】【内部类】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件iostream的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

WPF 框架 Prism IActiveAware接口使用

目的 在Prism框架中&#xff0c;IActiveAware接口是一个重要的接口&#xff0c;它允许开发者实现组件或视图的激活和失活逻辑。这通常在需要响应用户界面的可见性或激活状态变化时非常有用&#xff0c;比如在选项卡式界面中切换标签页时。 如何使用IActiveAware IActiveAwar…

css文字自适应宽度动态出现省略号...

前言 在列表排行榜中通常会出现的一个需求&#xff1a;从左到右依次是名次、头像、昵称、徽标、分数。徽标可能会有多个或者没有徽标&#xff0c;徽标长度是动态的&#xff0c;昵称如果过长要随着有无徽标进行动态截断出现省略号。如下图布局所示&#xff08;花里胡哨的底色是…

SpringSecurity中文文档(Servlet OAuth 2.0 Login)

OAuth 2.0 Login OAuth 2.0 Login 功能允许应用程序让用户通过使用 OAuth 2.0 Provider (如 GitHub)或 OpenID Connect 1.0 Provider (如 Google)的现有帐户登录到应用程序。OAuth 2.0 Login 实现了两个用例: “ Login with Google”或“ Login with GitHub”。 OAuth 2.0 Lo…

若依vue集成electron实现打包exe应用程序

一、修改package.json文件,加入相关依赖和配置 {"name": "ruoyi","version": "3.8.6","description": "若依管理系统","author": "若依","license":

分层图最短路,CF 1725M - Moving Both Hands

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1725M - Moving Both Hands 二、解题报告 1、思路分析 题意看似很简单&#xff0c;就是问我们两个人分别处于1, p两个点上&#xff0c;二者同时出发&#xff0c;相遇时二者所用路径之和的最小值 不难想到求…

mysql默认开启索引下推,减少回表的数据

目的&#xff1a;在回表前就进行where多个条件的判断&#xff0c;从而回表到服务器层的数据量足够小 索引下推的工作原理 在没有索引下推优化的情况下&#xff0c;当 MySQL 使用索引进行查询时&#xff0c;它会从索引中获取符合条件的索引条目&#xff0c;然后回表&#xff0…

Ubuntu中如何设置IP地址

在 Ubuntu 中&#xff0c;可以通过几种方式设置 IP 地址&#xff1a;使用网络管理器图形界面、命令行工具&#xff08;如 nmcli 或 nmtui&#xff09;、或直接编辑网络配置文件。以下是这几种方法的详细步骤。 方法一&#xff1a;使用图形界面&#xff08;Network Manager&…

Git协作

文章目录 Git协作冲突冲突的发生情况解决冲突如何处理冲突 1 分支1.1 什么是Git分支1.2 创建分支 2 切换分支2.1 指向分支2.2 暂存分支切换分支与未提交更改的处理使用 Stash 临时保存更改Stash 的工作原理&#xff1a;场景设定使用 Git Stash 3 远程分支3.1 快进合并快进合并的…

13. 求余

问题描述 在 C/C/Java/Python 等语言中, 使用 % 表示求余, 请问 2021 % 20 的值是多少? 答案提交 这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。 运行限制 最大运行时间&#xff1…

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…

Qt基础控件总结—多页面切换(QStackWidget类、QTabBar类和QTabWidget类)

QStackedWidget 类 QStackedWidget 类是在 QStackedLayout 之上构造的一个便利的部件,其使用方法与步骤和 QStackedLayout 是一样的。QStackedWidget 类的成员函数与 QStackedLayout 类也基本上是一致的,使用该类就和使用 QStackedLayout 一样。 使用该类可以参考QStackedL…

Perl 语言进阶学习

Perl 语言进阶学习 在掌握 Perl 的基础知识后&#xff0c;进一步学习 Perl 的高级特性和应用&#xff0c;将有助于提升编程效率和解决复杂问题的能力。本文将详细介绍 Perl 语言的高级功能、最佳实践以及实际应用案例。 目录 高级数据结构 多维数组复杂数据结构 引用与匿名数…