windows程序设计——功能表及其他资源

来源:互联网 发布:卷积运算公式矩阵 编辑:程序博客网 时间:2024/05/21 17:21

打开workspace的ResourceView可以看到系统的常用资源:图示、游标、字串、自订资源、功能表、键盘加速键、对话方块、点阵图。windows提供了一种直观的方式使得我们在开发过程中可以在资源编辑器中以所见既所得的方式来编辑这些资源,在生成可执行文件的时候资源编译器编译这些资源编译为二进制内容,并在程序连接的时候作为程序的一部分连接到可执行文件中。

但资源被添加到工程中时,系统会为资源分配ID,并被保存resource.h中,调用Load函数载入资源,并使用:

//{{NO_DEPENDENCIES}}// Microsoft Developer Studio generated include file.// Used by 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        103#define _APS_NEXT_COMMAND_VALUE         40001#define _APS_NEXT_CONTROL_VALUE         1000#define _APS_NEXT_SYMED_VALUE           101#endif#endif
rc文件的结构,标识资源类型文件名和resources的对应关系:

//Microsoft Developer Studio generated resource script.//#include "resource.h"#define APSTUDIO_READONLY_SYMBOLS///////////////////////////////////////////////////////////////////////////////// Generated from the TEXTINCLUDE 2 resource.//#include "afxres.h"/////////////////////////////////////////////////////////////////////////////#undef APSTUDIO_READONLY_SYMBOLS/////////////////////////////////////////////////////////////////////////////// English (U.S.) resources#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)#ifdef _WIN32LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US#pragma code_page(1252)#endif //_WIN32#ifdef APSTUDIO_INVOKED///////////////////////////////////////////////////////////////////////////////// TEXTINCLUDE//1 TEXTINCLUDE DISCARDABLE BEGIN    "resource.h\0"END2 TEXTINCLUDE DISCARDABLE BEGIN    "#include ""afxres.h""\r\n"    "\0"END3 TEXTINCLUDE DISCARDABLE BEGIN    "\r\n"    "\0"END#endif    // APSTUDIO_INVOKED///////////////////////////////////////////////////////////////////////////////// TEXT//ANNABELLEE              TEXT    DISCARDABLE     "poepoem.txt"///////////////////////////////////////////////////////////////////////////////// Icon//// Icon with lowest ID value placed first to ensure application icon// remains consistent on all systems.POEPOEM                 ICON    DISCARDABLE     "poepoem.ico"///////////////////////////////////////////////////////////////////////////////// String Table//STRINGTABLE DISCARDABLE BEGIN    IDS_APPNAME             "PoePoem"    IDS_CAPTION             """Annabel Lee"" by Edgar Allan Poe"    IDS_ERRMSG              "This program requires Windows NT!"END#endif    // English (U.S.) resources/////////////////////////////////////////////////////////////////////////////#ifndef APSTUDIO_INVOKED///////////////////////////////////////////////////////////////////////////////// Generated from the TEXTINCLUDE 3 resource.///////////////////////////////////////////////////////////////////////////////#endif    // not APSTUDIO_INVOKED
使用资源:

/*-------------------------------------------   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 ;     //载入字符串资源,带hInstance是程序资源,不带的是系统资源 当使用ID时使用MAKEINTRESOURCE获得字符串     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) ; //载入图标资源     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; //载入系统预定义的光标资源     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;     wndclass.lpszMenuName  = NULL ;     wndclass.lpszClassName = szAppName ;          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 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) ;          //通过FindResource找到资源的ID后再调用LoadResource得到指向内存的代号          hResource = LoadResource (hInst,                       FindResource (hInst, TEXT ("AnnabelLee"),                                           TEXT ("TEXT"))) ;          //再一次调用才会把LockResource载入到内存中          pText = (char *) LockResource (hResource) ;          iNumLines = 0 ;                    while (*pText != '\\' && *pText != '\0')          {               if (*pText == '\n')                    iNumLines ++ ;               pText = AnsiNext (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 (wParam)          {          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_THUMBPOSITION :               iPosition = LOWORD (lParam) ;               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 ;          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) ;}
菜单与其他的资源一样载入使用但更为复杂和常用而且常常与加速键联合使用:
/*-----------------------------------------   MENUDEMO.C -- Menu Demonstration                 (c) Charles Petzold, 1998  -----------------------------------------*/#include <windows.h>#include "resource.h"//定义系统附加菜单的ID#define IDM_SYS_ABOUT   1#define IDM_SYS_HELP    2#define IDM_SYS_REMOVE  3#define ID_TIMER 1//回调函数LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//程序名和程序句柄TCHAR szAppName[] = TEXT ("MenuDemo") ;HINSTANCE hInst ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     HACCEL   hAccel ; //加速键句柄     HMENU    hMenu ;  //菜单句柄(创建的系统菜单)     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 (NULL, IDI_APPLICATION) ;     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;     wndclass.lpszMenuName  = szAppName ;  //第一种指定菜单方式,直接在WNDCLASS中指定     wndclass.lpszClassName = szAppName ;          if (!RegisterClass (&wndclass))     {          MessageBox (NULL, TEXT ("This program requires Windows NT!"),                      szAppName, MB_ICONERROR) ;          return 0 ;     }     //保存程序句柄(后期的资源load需要用到)     hInst = hInstance ;     //创建窗口(这里也可以指定窗口菜单,第七个参数)     hwnd = CreateWindow (szAppName, TEXT ("Menu Demonstration"),                          WS_OVERLAPPEDWINDOW,                          CW_USEDEFAULT, CW_USEDEFAULT,                          CW_USEDEFAULT, CW_USEDEFAULT,                          NULL, NULL, hInstance, NULL) ; //得到系统菜单,第二个参数为true时恢复默认菜单     hMenu = GetSystemMenu (hwnd, FALSE) ;     //为菜单增加子菜单项目(分割符和三个item,并指定ID)     AppendMenu (hMenu, MF_SEPARATOR, 0,           NULL) ;     AppendMenu (hMenu, MF_STRING, IDM_SYS_ABOUT,  TEXT ("About...")) ;     AppendMenu (hMenu, MF_STRING, IDM_SYS_HELP,   TEXT ("Help...")) ;     AppendMenu (hMenu, MF_STRING, IDM_SYS_REMOVE, TEXT ("Remove Additions")) ;     ShowWindow (hwnd, iCmdShow) ;     UpdateWindow (hwnd) ;     //载入根据名称加速表 hAccel = LoadAccelerators (hInstance, TEXT("HELP_ONLY")) ;          while (GetMessage (&msg, NULL, 0, 0))     {          //将加速键转化为command和ID          if (!TranslateAccelerator (hwnd, hAccel, &msg))          {               TranslateMessage (&msg) ;               DispatchMessage (&msg) ;          }     }     return msg.wParam ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static int idColor [5] = { WHITE_BRUSH,  LTGRAY_BRUSH, GRAY_BRUSH,                                DKGRAY_BRUSH, BLACK_BRUSH } ;     static int iSelection = IDM_BKGND_WHITE ;     HMENU      hMenu ; POINT      point ;     static HMENU hMenu_pop ;     switch (message)     {     case WM_CREATE: //创建窗口的时候载入弹出菜单          hMenu_pop = LoadMenu (hInst, TEXT ("PopMenu")) ;          //并取出菜单资源定义的第一个子项目,作为窗口上的弹出菜单          hMenu_pop = GetSubMenu (hMenu_pop, 0) ;          return 0 ;     case WM_RBUTTONUP: //单击右键时弹出菜单(计算点击的位置并显示菜单)          point.x = LOWORD (lParam) ;          point.y = HIWORD (lParam) ;          ClientToScreen (hwnd, &point) ;                    TrackPopupMenu (hMenu_pop, TPM_RIGHTBUTTON, point.x, point.y,                           0, hwnd, NULL) ;          return 0 ;     case WM_COMMAND: //处理菜单被单击的消息          hMenu = GetMenu (hwnd) ;                    switch (LOWORD (wParam)) //处理菜单ID的消息          {          case IDM_FILE_NEW:          case IDM_FILE_OPEN:          case IDM_FILE_SAVE:          case IDM_FILE_SAVE_AS:               MessageBeep (0) ;               return 0 ;                         case IDM_APP_EXIT:               SendMessage (hwnd, WM_CLOSE, 0, 0) ;               return 0 ;                         case IDM_EDIT_UNDO:          case IDM_EDIT_CUT:          case IDM_EDIT_COPY:          case IDM_EDIT_PASTE:          case IDM_EDIT_CLEAR:               MessageBeep (0) ;               return 0 ;                         case IDM_BKGND_WHITE:         // Note: Logic below          case IDM_BKGND_LTGRAY:        //   assumes that IDM_WHITE          case IDM_BKGND_GRAY:          //   through IDM_BLACK are          case IDM_BKGND_DKGRAY:        //   consecutive numbers in          case IDM_BKGND_BLACK:         //   the order shown here.               //设置主菜单中的checke信息               CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;               iSelection = LOWORD (wParam) ;               CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;               //设置窗口背景画刷               SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)                     GetStockObject                              (idColor [LOWORD (wParam) - IDM_BKGND_WHITE])) ;               //刷新               InvalidateRect (hwnd, NULL, TRUE) ;               return 0 ;                         case IDM_TIMER_START: //启用定时器,设置相关菜单项可用或不可用               if (SetTimer (hwnd, ID_TIMER, 1000, NULL))               {                    EnableMenuItem (hMenu, IDM_TIMER_START, MF_GRAYED) ;                    EnableMenuItem (hMenu, IDM_TIMER_STOP,  MF_ENABLED) ;               }               return 0 ;                         case IDM_TIMER_STOP: //停止定时器,设置相关菜单项可用或不可用               KillTimer (hwnd, ID_TIMER) ;               EnableMenuItem (hMenu, IDM_TIMER_START, MF_ENABLED) ;               EnableMenuItem (hMenu, IDM_TIMER_STOP,  MF_GRAYED) ;               return 0 ;                         case IDM_APP_HELP: //帮助信息,弹出消息框               MessageBox (hwnd, TEXT ("Help not yet implemented!"),                           szAppName, MB_ICONEXCLAMATION | MB_OK) ;               return 0 ;                         case IDM_APP_ABOUT: //关于信息,弹出消息框               MessageBox (hwnd, TEXT ("Menu Demonstration Program\n")                                 TEXT ("(c) Charles Petzold, 1998"),                           szAppName, MB_ICONINFORMATION | MB_OK) ;               return 0 ;          }          break ;     case WM_SYSCOMMAND: //系统菜单,转发消息,或者恢复默认系统菜单          switch (LOWORD (wParam))          {          case IDM_SYS_ABOUT:               SendMessage (hwnd, WM_COMMAND, IDM_APP_ABOUT, 0);               return 0 ;                         case IDM_SYS_HELP:               SendMessage (hwnd, WM_COMMAND, IDM_APP_HELP, 0);               return 0 ;                         case IDM_SYS_REMOVE:               GetSystemMenu (hwnd, TRUE) ;               return 0 ;          }          break ;               case WM_TIMER:          MessageBeep (0) ;          return 0 ;                    case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

处理以上代码中所使用的常用接口外还有如下接口(同时有不通过资源创建菜单的方法):

//创建菜单hMenu = CreateMenu () ;AppendMenu 在功能表尾部添加一个新的功能表项目DeleteMenu 删除功能表中一个现有的功能表项并清除该项目InsertMenu 在功能表中插入一个新项目ModifyMenu 修改一个现有的功能表项目RemoveMenu 从功能表中移走某一项目//销毁菜单DestroyMenu (hMenu) ;//获取菜单项个数iCount = GetMenuItemCount (hMenu) ;//获取某个菜单index上的IDid = GetMenuItemID (hMenuPopup, iPosition) ;//获取菜单状态iFlags = GetMenuState (hMenu, id, iFlag) ;//获取菜单的文字信息iCharCount = GetMenuString (hMenu, id, pString, iMaxCount, iFlag) ;