2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Custom Resources is a type of resource used in Windows programs to store application-specific data, images, audio, binary files, etc. Through custom resources, developers can centrally manage and store various resource files required by the application, making it easier to access and use them in the program.
■Here are some key points about custom resources:
●Custom resource type:
1. Custom resources can be any application-specific data or files, such as images, audio, XML configuration files, text files, etc.
2. Custom resources can be identified using a custom resource type identifier, such as "MY_CUSTOM_RESOURCE".
●Create and edit custom resources:
1. Custom resources are usually contained in the application's resource file (.rc).
2. Use a resource editor (such as Visual Studio's Resource View) to create and edit custom resources.
3. In the resource file, you can specify a unique resource identifier and the corresponding resource file path for each resource.
● Reference and use of custom resources:
1. When referencing and using custom resources in code, you can use resource identifiers to load or access the corresponding resources.
2. Use the corresponding API functions (such as LoadResource, FindResource, LockResource, etc.) to load and operate custom resources.
3. Depending on the type of custom resources, different API functions can be used (eg, image resources can use GDI functions, audio resources can use DirectSound functions) to process custom resources.
■Here is a sample code snippet showing how to load and use a custom resource:
#include <Windows.h>
int main()
{
HINSTANCE hInstance = GetModuleHandle(NULL); // Get the current instance handle
HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(IDR_MY_RESOURCE), "MY_CUSTOM_RESOURCE"); // Find custom resources
HGLOBAL hResData = LoadResource(hInstance, hResource); // Load custom resources
LPVOID pData = LockResource(hResData); // Lock custom resources
// Using custom resources...
return 0;
}
In the above example, IDR_MY_RESOURCE is the identifier of the custom resource, and the corresponding resource file path is defined in the resource file. Use the FindResource function to find the custom resource, then use the LoadResource function to load the custom resource, and finally use the LockResource function to lock the custom resource to obtain a pointer to the resource data. Subsequently, the pointer pData can be used for subsequent processing and operations according to the type and requirements of the resource.
It should be noted that the specific usage of custom resources depends on the resource type and application requirements. Developers can choose the appropriate resource type and corresponding API function to handle custom resources according to actual needs.
Custom resources provide a flexible resource management method for applications. It can manage all kinds of data and files required by applications in a unified way and easily access and use them in programs. By using custom resources, applications can be made more modular, maintainable, and extensible.
■In VSAdd custom resources
1. Add resources
2. Click "Customize" and fill in the resource type "TEXT"
3. Import resources and automatically generate text1.bin file, resource ID: IDR_TEXT1
4. In VS, directly enter the resource file name in the custom compiler and modify the ID. An error message appears: Unable to load external resources - the possible reason is that the resource has not been imported.
5. Add resources in the resource view box.
6. Import external resource files.
7. Re-fill in the resource file name and ID. Note that the ID name needs to be filled in with the quoted string "ANNABELLEE".
8. Save the settings and you're done.
There is also a simpler method, which is to modify the resource file POEPOEM.rc directly and add resources to the line below TEXT.
/*------------------------------------------------------------------------
057 WIN32 API Daily Practice
Example 57 POEPOEM.C: String Resource Table and Custom Resources
LoadString function
LoadResource function
FindResource function
LockResource function
AnsiNext Macro Definition
(c) www.bcdaren.com Programming Master
-----------------------------------------------------------------------*/
#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)
{ //Resource file names, titles, and error messages
TCHAR szAppName[16], szCaption[64], szErrMsg[64];
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
//Loading string resources
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;
//Add Icon
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
//wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
//Customize the mouse pointer
wndclass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
//hInst = hInstance;//There is no such thing in the original code, and no error will be reported
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;//Resource handle - a handle to a block of memory
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);
//The width of the vertical scroll bar in pixels
xScroll = GetSystemMetrics(SM_CXVSCROLL);
//Generate scroll bars
hScroll = CreateWindow(TEXT("scrollbar"), NULL,
WS_CHILD | WS_VISIBLE | SBS_VERT,
0, 0, 0, 0,
hwnd, (HMENU)1, hInst, NULL);
//Get the text handle
hResource = LoadResource(hInst,
FindResource(hInst, TEXT("AnnabelLee"),//Determines the object with the specified type and name
The location of the resource in the specified module
TEXT("TEXT")));
//Retrieves a pointer to a specified resource in memory
pText = (LPCSTR)LockResource(hResource);
iNumLines = 0;//Read the number of lines of text
//Get the number of text lines
while (*pText != '\' && *pText != '0')//Ends when encountering or 0
{
if (*pText == 'n')
iNumLines++;
//Returns the next position (pointer) in an ANSI string. AnsiNext is a 16-bit string on Windows.
//A macro definition, Win32 uses CharNext instead (AnsiNext can only handle ansi characters
//string; CharNext can be either ansi or unicode string)
//pText = AnsiNext(pText);
pText = (LPCSTR)CharNext((LPCWSTR)pText);
}
//*pText = '0';//The original code here states that it ends with a null character --- the actual text does not end with a null character
//Setting the scroll bar
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);//Setting the focus
return 0;
case WM_SETFOCUS:
SetFocus(hScroll);//Capture scroll bar slider focus
return 0;
case WM_VSCROLL:
switch (LOWORD(wParam)) //LOWORD must be added because the notification code is in the low word
{
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;//Start displaying from column 2
rect.top += cyChar * (1 - iPosition);
//Includes the font's outer line header height. Normally, outer line headers are not included in the height of a line of text.
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 Function: Loads a string resource and then copies the string into a buffer with a terminating null character.
Or returns a read-only pointer to the string resource itself.
*******************************************************************************
LoadResource Function: Retrieves a handle that can be used to obtain a pointer to the first byte of a specified resource in memory.
HGLOBAL LoadResource(
HMODULE hModule,//A handle to the module whose executable file contains the resource. If hModule is NULL, the system loads the resource from the module used to create the current process.
HRSRC hResInfo//A handle to the resource to load
);
*******************************************************************************
FindResource Function: Determines the location of a resource with the specified type and name in the specified module
HRSRC FindResourceA(
HMODULE hModule,//A handle to the module containing the resource
LPCSTR lpName,//The name of the resource
LPCSTR lpType//Types of resources
);
*******************************************************************************
LockResource Function: Retrieves a pointer to a specified resource in memory
LPVOID LockResource(
HGLOBAL hResData//A handle to the resource to access
);
*******************************************************************************
AnsiNext Macro definition:
16An API function on Windows (a macro definition to be exact) that can only process ANSI strings;
Later, when Win32 appeared, Microsoft implemented encapsulation through CharNext for compatibility.
CharNextCan be either ANSI or Unicode string.
This function returns the next position (pointer) in the ANSI string.
*/
Resource.hhead File
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ Generated include files.
// For use by 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.rcThe resource script file contains 4 types of resources:
1.Icon resources:
// Icon
//
IDI_ICON1 ICON "D:\code\windows5.0\A daily
practice\057_POEPOEM\057_POEPOEM\icon1.ico"
2. Mouse pointer bitmap resource:
// Cursor
//
IDC_CURSOR1 CURSOR "cursor1.cur"
3. String resource table:
// String Table
//
STRINGTABLE
BEGIN
IDS_APPNAME "PoePoem"
IDS_CAPTION """Annabel Lee"" by Edgar Allan Poe"
IDS_ERRMSG "This program requires Windows NT!"
END
4.Custom resources:
// TEXT
//
ANNABELLEE TEXT "POEPOEM.TXT"
operation result:
Figure 9-9 String resource table and custom resources
Summarize
In the POEPOEM.RC resource script, the user-defined resource is specified as the TEXT type and the text name is "ANNABELLEE": ANNABELLEE TEXT POEPOEM.TXT
When processing the WM_CREATE message in WndProc, the handle to the resource is obtained through FindResource and LoadResource. LockResource locks the resource, and a small routine replaces the backslash () at the end of the file with 0. This is to facilitate the use of the DrawText function in the subsequent WM_PAINT message.
【Note】We use a child window scroll bar control instead of a window scroll bar. The child window scroll bar control has an automatic keyboard interface, so there is no need to process the WM_KEYDOWN message in POEPOEM.
POEPOEM also uses three strings whose IDs are defined in the RESOURCE.H header file. At the beginning of the program, the IDS_APPNAME and IDS_CAPTION strings are loaded into memory by LoadString:
LoadString (hlnstance, IDS_APPNAME, szAppName,
sizeof (szAppName) /sizeof (TCHAR));
LoadString (hlnstance, IDS_CAPTION, szCaption,
sizeof (szCaption) /sizeof (TCHAR));
[Note] These two calls are before RegisterClass. The program uses LoadStringA to load the IDS_APPNAME and IDS_ERRMSG strings, and uses MessageBoxA to display a custom message box:
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 ;
}
【Note】Forced conversion from TCHAR string variable to char pointer.
AnsiNext is a macro definition on 16-bit Windows, and Win32 uses CharNext instead (AnsiNext can only process ansi strings; while CharNext can handle both ansi strings and unicode strings).
pText = AnsiNext(pText);
Replace with:
pText = (LPCSTR)CharNext((LPCWSTR)pText);
All strings used by POEPOEM are defined as resources, so the program can be easily converted to non-English versions by translators.