10.1 图标、鼠标指针、字符串和自定义资源
10.1.1 向程序添加图标
(1)加载图标:(注意:第1个参数为hInstance,不能为NULL表示从程序本身加载)
图标ID为数字 |
①wndclass.hIcon = LoadIcon(hInstance,MAXINTRESOURCE(IDI_ICON); ②wndclass.hIcon = LoadIcon(hInstance,MAXINTRESOURCE(125) |
图标ID为字符串 |
①wndclass.hIcon = LoadIcon(hInstance,TEXT(“ICONDEMO”)); //须在资源视图中将图标ID输入为字符串“ICONDEMO”,要加引号 ②wndclass.hIcon = LoadIcon(hInstance,TEXT(“#125”)); //windows将起始的#字符识别为ASCII格式的数字前缀 |
①第1个参数:为hInstance而不是NULL,表示从程序自身的资源加载
②第2个参数:可以是MAKEINTERSOURCE(数字标识符)或字符串标识符,但当为字符串标识符时,必须把图标ID改变字符串,如”ICONDEMO”。注意,须加引号。
(2)获取图标的大小
大图标 |
小图标 |
cxIcon = GetSystemMetrics(SM_CXICON) cyIcon = GetSystemMetrics(SM_CYICON) |
cxIcon = GetSystemMetrics(SM_CXSMSIZE) cyIcon = GetSystemMetrics(SM_CYSMSIZE) |
(3)绘制图标:DrawIcon(hdc,x,y,hIcon);
10.1.2 在应用程序中使用图标
(1)窗口类WNDCLASSEX和WNDCLASS
WNDCLASSEX |
WNDCLASS |
hIcon ——大图标句柄(EXE程序图标) |
hIcon:大小图标从单文件中自动提取或缩放 |
hIconSm——小图标句柄(标题和任务栏) |
无 |
用RegisterClassEx注册 |
用RegisterClass注册 |
(2)动态改变图标
①SetClassLong(hwnd,GCL_HCION,LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON)));
②DrawIcon(hdc,x,y,GetClassLong(hwnd,GCL_HICON)); //直接从窗口类取出图标句柄
10.1.3 自定义鼠标指针
(1)加载鼠标指针
wndclass.hCursor= LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR);//ID为数字
wndclass.hCursor= LoadCursor(hInstance,szCursor);//鼠标ID为字符串
(2)定义鼠标热点——使用最右边的工具在鼠标图标上点一下(没明显变化,但己起作用)
(3)子窗口中改变鼠标:
SetClassLong(hwndChild,GCL_HCURSOR,LoadCursor(hInstance,Text(“childCursor”)));
(4)在WM_MOUSEMOVE消息中调用SetCursor(hCursor)重绘图标;
【ICONDEMO】程序
/*------------------------------------------------------------ ICONDEMO.C -- Icon Demonstration Program (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("IconDemo"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); wndclass.hCursor = LoadCursor(hInstance, szAppName); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Icon Demo"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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) { HDC hdc; PAINTSTRUCT ps; static HICON hIcon; static int cxIcon, cyIcon, cxClient, cyClient; HINSTANCE hInstance; switch (message) { case WM_CREATE: hInstance = ((LPCREATESTRUCT)lParam)->hInstance; hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); cxIcon = GetSystemMetrics(SM_CXICON); cyIcon = GetSystemMetrics(SM_CYICON); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (int x = 0; x < cxClient; x += cxIcon) for (int y = 0; y < cyClient; y += cyIcon) { DrawIcon(hdc, x, y, hIcon); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 IconDemo.rc 使用 // #define IDI_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//IconDemo.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON ICON "ICONDEMO.ICO" #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
【IconDemo2程序】——大、小图标
/*------------------------------------------------------------ ICONDEMO2.C -- Icon Demonstration Program (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("IconDemo2"); HWND hwnd; MSG msg; WNDCLASSEX wndclass; //为了用上大、小图标,这里用WNDCLASSEX,而不用WNDCLASS wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, TEXT("ICONBIG")); //ICONBIG从本程序中获取,第1个参数不能为NULL,第2个参数 wndclass.hIconSm = LoadIcon(hInstance, TEXT("ICONSMALL"));//直接用字符串表示,不用MAKEINTRESOURCE了。但须把图标ID //改成字符串的ID,即加引号,如"ICONBIG",而不用IDI_ICONBIG wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Icon Demo2"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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) { HDC hdc; PAINTSTRUCT ps; static HICON hIcon; static int cxIcon, cyIcon, cxClient, cyClient; HINSTANCE hInstance; switch (message) { case WM_CREATE: hInstance = ((LPCREATESTRUCT)lParam)->hInstance; hIcon = LoadIcon(hInstance, TEXT("ICONBIG")); cxIcon = GetSystemMetrics(SM_CXICON); cyIcon = GetSystemMetrics(SM_CYICON); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (int x = 0; x < cxClient; x += cxIcon) for (int y = 0; y < cyClient; y += cyIcon) { DrawIcon(hdc, x, y, hIcon); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 IconDemo2.rc 使用 // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//IconDemo2.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. ICONBIG ICON "ICONBIG.ico" ICONSMALL ICON "ICONSMALL.ico" #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
10.1.4 字符串资源
(1)所有的资源文本(包括字符串中的文本)都是以Unicode格式保存,并编译成.RES
(2)使用\t和\n代表制表符和换行
(3)加载字符串资源到数据缓存区中
LoadString(hInstance,id,szBuffer,iMaxLength);
//参数:iMaxLength为szBuffer接收的最大字符数。返回值:字符串中字符的数目
(4)LoadStringW直接加载Unicode,LoadStringA会从Unicode到本地代码页的文本转换。
10.1.5 自定义资源
(1)自定义:如资源类型名字叫BINTYPE,资源名为IDR_BINTYPE1,文件名:BINDATA.BIN
资源脚本:IDR_BINTYPE1BINTYPE "bintype.bin"(形似 IDI_ICON ICON "IconDemo.ico")
(2)获取资源句柄与加载
获取资源句柄 |
HGLOBAL hResource = LoadResource(hInstance, FindResource(hInstance,MAKEINTRESOURCE(IDR_BINTYPE1), Text(“BINTYPE”))); |
加载到内存 |
pData = LockResource(hResource); |
释放资源 |
FreeResource(hResource);//程序终止,不调用该函数,也会自动释放。 |
【POEPOEM程序】
/*------------------------------------------------------------ POEPOEM.C -- Demonstrates Custom Resource (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #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; hInst = hInstance; 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, szAppName); //图标ID为字符串“PoePoem” wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { //Win98不能使用Unicode,为了兼容Win98,改为多字节函数 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, // window class name szCaption, // window caption WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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) { HDC hdc; PAINTSTRUCT ps; RECT rect; TEXTMETRIC tm; static int iNumLines, iPosition, xScroll, cxChar, cyChar, cxClient, cyClient; static char* pText; char* pData; HRSRC hResInfo; HGLOBAL hResource; DWORD dwSize; static HWND hScroll; 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); //获取文本句柄 hResInfo = FindResource(hInst, TEXT("ANNABELLEE"), TEXT("TEXT")); hResource = LoadResource(hInst, hResInfo); //资源是只读数据 dwSize = SizeofResource(hInst, hResInfo); pText = pData = (char*)calloc(dwSize, sizeof(char)); memcpy_s(pText, dwSize, (char*)LockResource(hResource), dwSize); //内存拷贝 FreeResource(hResInfo); //读取文本行数 iNumLines = 0; while ((*pData != ‘\\‘) && (*pData != ‘\0‘)) //遇\或\0结束 { if (*pData == ‘\n‘) iNumLines++; pData = AnsiNext(pData); } *pData = ‘\0‘; //设置滚动条 SetScrollRange(hScroll, SB_CTL, 0, iNumLines, FALSE); SetScrollPos(hScroll, SB_CTL, 0, FALSE); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); MoveWindow(hScroll, cxClient - xScroll, 0, xScroll, cyClient, TRUE); SetFocus(hwnd); 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_SETFOCUS: SetFocus(hScroll); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); 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: if (pText != NULL) free(pText); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 PoePoem.rc 使用 // #define IDS_APPNAME 1 #define IDS_CAPTION 2 #define IDS_ERRMSG 3 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 106 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//Pompoem.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXT // ANNABELLEE TEXT "POEPOEM.TXT" ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. POEPOEM ICON "POEPOEM.ICO" ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN IDS_APPNAME "PopPoem" IDS_CAPTION "“Annable Lee” by Edgar Allan Poe" IDS_ERRMSG "This program requires Windows NT!" END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
//Pompoem.txt
POMPOEM.TEXT It was many and many a year ago, In a kingdom by the sea, That a maiden there lived whom you may know By the name of Annabel Lee; And this maiden she lived with no other thought Than to love and be loved by me. I was a child and she was a child In this kingdom by the sea, But we loved with a love that was more than love -- I and my Annabel Lee -- With a love that the winged seraphs of Heaven Coveted her and me. And this was the reason that, long ago, In this kingdom by the sea, A wind blew out of a cloud, chilling My beautiful Annabel Lee; So that her highborn kinsmen came And bore her away from me, To shut her up in a sepulchre In this kingdom by the sea. The angels, not half so happy in Heaven, Went envying her and me -- Yes! that was the reason (as all men know, In this kingdom by the sea) That the wind came out of the cloud by night, Chilling and killing my Annabel Lee. But our love it was stronger by far than the love Of those who were older than we -- Of many far wiser than we -- And neither the angels in Heaven above Nor the demons down under the sea Can ever dissever my soul from the soul Of the beautiful Annabel Lee: For the moon never beams, without bringing me dreams Of the beautiful Annabel Lee; And the stars never rise, but I feel the bright eyes Of the beautiful Annabel Lee: And so, all the night-tide, I lie down by the side Of my darling -- my darling -- my life and my bride, In her sepulchre there by the sea -- In her tomb by the sounding sea. [May, 1849] \