第十章 菜单和其他资源

来源:互联网 发布:理性知乎 编辑:程序博客网 时间:2024/06/01 14:01

checked  选中  drop-down menu 下拉菜单  popup menu 弹出菜单  submenu 子菜单

enabled 启用 disabled 禁用 grayed 变灰 active 活动  inactive 非活动

 

程序图标:(不必过多的介绍了,使用最简洁的一个)

一、注意添加头文件 #include "resource.h"

wndclass.hIcon         = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON));

二、不需要添加头文件 #include "resource.h" ,直接使用字符

wndclass.hIcon         = LoadIcon(hInstance,"IDI_ICON");

获取图标句柄:

hIcon =  LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON));

 可以调用DrawIcon(hdc, x, y, hIcon); 在客户区显示图标,并在水平和垂直方向重复排列。(其中X ,Y 是图标显示位置的左上角坐标)

MAKEINTRESOURCE 宏(这个名称表示 “make an integer into a resource string”)是这样用数字来产生指针的:

#define MAKEINTRESOURCE(i) (LPSTR)((DWORD)((WORD)(i)))

图标演示实例如下:

/*----------------------------------------------------icodemo.c -- icodemo(c) bm, 2014  ----------------------------------------------------*/#include <windows.h>#include <stdio.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 ("icocode") ;     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 (NULL, IDC_ARROW);     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);     wndclass.lpszMenuName  = NULL;     wndclass.lpszClassName = szAppName ;       RegisterClass (&wndclass);          hwnd = CreateWindow (szAppName, TEXT ("Icodemo"),                          WS_OVERLAPPEDWINDOW,                          1000, 30,                          250, 600,                          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  RECT  rect;static int cxIcon, cyIcon;static HICON hIcon;TCHAR    szBuffer[100];HDC      hdc ;PAINTSTRUCT ps ;HINSTANCE hInstance;     switch (message)     {     case WM_CREATE:  GetClientRect(hwnd,&rect);  hInstance = ((LPCREATESTRUCT)lParam) ->hInstance; //用于获取实例  hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON)); //获得图标句柄  cxIcon = GetSystemMetrics(SM_CXICON);  cyIcon = GetSystemMetrics(SM_CYICON);          return 0 ; case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;  sprintf(szBuffer,TEXT("ico x: %d  ico y: %d"), cxIcon, cyIcon);  SetTextColor(hdc,RGB(0,0,255));  TextOut(hdc,0,0,szBuffer,lstrlen(szBuffer));  DrawIcon(hdc, 0, 20,hIcon); //显示图标 位置在(0,20)      EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

运行结果:

这里倾向于另一种写法,给图标使用文本名字,这样可以用程序名字表示。



代码:

/*----------------------------------------------------icodemo.c -- icodemo(c) bm, 2014  ----------------------------------------------------*/#include <windows.h>#include <stdio.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("icocode") ; // 这里表示类名 和 图标的文本名     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,szAppName);//  使用程序名szAppName      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);     wndclass.lpszMenuName  = NULL;     wndclass.lpszClassName = szAppName ;       RegisterClass (&wndclass);          hwnd = CreateWindow (szAppName, TEXT ("Icodemo"),                          WS_OVERLAPPEDWINDOW,                          1000, 30,                          250, 600,                          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){PAINTSTRUCT ps ;static  RECT  rect;TCHAR    szBuffer[100] ;TCHAR cxIcon, cyIcon;HDC      hdc ;     switch (message)     {     case WM_CREATE:  GetClientRect(hwnd,&rect);          return 0 ; case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;  cxIcon = GetSystemMetrics(SM_CXICON);  cyIcon = GetSystemMetrics(SM_CYICON);  sprintf(szBuffer,TEXT("ico x: %d  ico y: %d"), cxIcon, cyIcon);  SetTextColor(hdc,RGB(0,0,255));  TextOut(hdc,0,0,szBuffer,lstrlen(szBuffer));      EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

鼠标自定义:(和图标一样)

代码:

/*----------------------------------------------------cursordemo.c -- cursordemo(c) bm, 2014  ----------------------------------------------------*/#include <windows.h>#include <stdio.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 ("cursorcode") ;     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 (hInstance,MAKEINTRESOURCE(IDC_CUR));     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);     wndclass.lpszMenuName  = NULL;     wndclass.lpszClassName = szAppName ;       RegisterClass (&wndclass);          hwnd = CreateWindow (szAppName, TEXT ("Cursordemo"),                          WS_OVERLAPPEDWINDOW,                          1000, 30,                          250, 600,                          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){PAINTSTRUCT ps ;static  RECT  rect;static TCHAR    szBuffer[100];HDC      hdc ;     switch (message)     {     case WM_CREATE:  GetClientRect(hwnd,&rect);          return 0 ; case WM_MOUSEMOVE: sprintf(szBuffer,TEXT("pos x:%d  pos y:%d"), LOWORD(lParam), HIWORD(lParam));         InvalidateRect(hwnd,&rect,TRUE); return 0; case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;   SetTextColor(hdc,RGB(0,0,255));  TextOut(hdc,0,0,szBuffer,lstrlen(szBuffer));      EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

运行结果:看不见鼠标忘了

 字符串资源 和 自定义资源 (2014年4月1日更新)

使用字符串表可以翻译成另外一种语言,这个方法比乱改你的源程序要安全得多。但是字符串表会使代码看起来更加晦涩和复杂,而不是清晰明了。

创建字符串表,应从Insert菜单中选择Resource,然后选择String Table 。字符串将会被显示在屏幕右侧的列表里。

对每个字符串,都需要指定标识符和字符串本身。

字符串表:

在资源脚本(.RC)里,字符串显示为类似于下面的多行语句:

STRINGTABLE DISCARDABLE BEGIN    IDS_FILENOTFOUND        "File %s not found."    IDS_FILETOOBIG          "File %s too large to edit."    IDS_FILEEREADONLY       "File %s is read-only."    IDS_OK                  "确定"//只需要修改 这里就可以翻译成另一种语言END

也可以手工创建字符串表,在资源脚本(.RC)中编写上面的语句,

然后在Resource.H 头文件中包含 这些字符串的标识符。

// Used by icon.rc//#define IDS_FILENOTFOUND                1#define IDS_FILETOOBIG                  2#define IDS_FILEEREADONLY               3#define IDS_OK                          4

程序实例:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){HINSTANCEhInstance;TCHAR  szOk[20];switch(message){case WM_CREATE:hInstance = ((LPCREATESTRUCT)lParam)->hInstance;LoadString(hInstance, IDS_OK, szOk, 20); //复制字符串资源到程序数据区的缓存中CreateWindow(TEXT("Button"), szOk,WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,20, 20, 100, 30, hwnd, (HMENU)1, hInstance, NULL);//这里创建了一个 按钮return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);}

运行:


程序中调用了:

LoadString(hInstance, id, szBuffer, iMaxLength);

id 参数代表资源脚本中每个字符串前面的ID号, szBuffer是一个指向接受字符串的字符数组的指针

iMaxLength是szBuffer可以接收的最大字符数。此函数返回字符串中字符的数目。

菜单:

一、资源脚本(.RC)

///////////////////////////////////////////////////////////////////////////////// Menu  注意 红色的部分,使用数字标识表式//IDM_MENU MENU DISCARDABLE   BEGIN    POPUP "文件(&F)"    BEGIN        MENUITEM "打开(&F)",                    IDM_MENU_OPEN        MENUITEM "保存",                        IDM_MENU_BAOCUN        MENUITEM SEPARATOR        MENUITEM "退出",                        IDM_MENU_CANCEL    END    POPUP "关于(&A)"    BEGIN        MENUITEM "作者",                        IDM_MENU_ABOUT_EDIT    ENDEND

第一种方法创建菜单:(这里先使用数字形式)

在窗口类创建时,即

wc.lpszMenuName  = MAKEINTRESOURCE(IDM_MENU);

第二种方法是在窗口创建的时候,会覆盖窗口类中指定的任何菜单

hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDM_MENU));  // 加载菜单.首先定义一个菜单句柄,HMENU  hMenu ,hwnd = CreateWindow(szClassName,  TEXT("Menu Demo"),  WS_OVERLAPPEDWINDOW,  CW_USEDEFAULT,  CW_USEDEFAULT,  CW_USEDEFAULT,  CW_USEDEFAULT,  NULL,  hMenu,  hInstance,NULL);

第三种方法,在窗口创建之后再指派一个菜单,这样可以动态地改变窗口的菜单

hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDM_MENU)); hwnd = CreateWindow(szClassName,      TEXT("Menu Demo"),      WS_OVERLAPPEDWINDOW,      CW_USEDEFAULT,      CW_USEDEFAULT,      CW_USEDEFAULT,      CW_USEDEFAULT,      NULL,NULL,     // hMenu,      hInstance,NULL); SetMenu(hwnd, hMenu);  //动态的改变窗口菜单  ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd);

下面是使用字符表示

///////////////////////////////////////////////////////////////////////////////// Menu   资源脚本(.RC) 注意红色的部分不同//MYMENU MENU DISCARDABLE BEGIN    POPUP "文件(&F)"    BEGIN        MENUITEM "打开(&F)",                    IDM_MENU_OPEN        MENUITEM "保存",                        IDM_MENU_BAOCUN        MENUITEM SEPARATOR        MENUITEM "退出",                        IDM_MENU_CANCEL    END    POPUP "关于(&A)"    BEGIN        MENUITEM "作者",                        IDM_MENU_ABOUT_EDIT    ENDEND

字符表示形式 只需要把  MAKEINTRESOURCE( IDM_MENU )修改为 TEXT( "MYMENU " );

第一种方法,其它方法相同

wc.lpszMenuName  = TEXT("MYMENU");

菜单消息

其中最重要的消息是程序会向窗口过程发送WM_COMMAND 消息

实例程序

#include <windows.h>#include "resource.h"LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance,       HINSTANCE hPrevInstance,       LPSTR szCmdLine,       int nCmdShow){ static TCHAR szClassName[] = TEXT("ClassName"); WNDCLASS wc; HWND hwnd; MSG msg; HMENU hMenu; wc.style =  CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc  = WndProc; wc.cbClsExtra  = 0; wc.cbWndExtra  = 0; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.hIcon   = LoadIcon(hInstance, TEXT("icondemo"));//LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); //LoadIcon(NULL, IDI_APPLICATION); wc.hCursor   = LoadCursor(hInstance, TEXT("cursor"));//LoadCursor (NULL,IDC_ARROW); wc.hInstance  = hInstance; wc.lpszMenuName  = NULL;//MAKEINTRESOURCE(IDM_MENU);//或者写成数字形式,TEXT("MYMENU");   wc.lpszClassName = szClassName; RegisterClass(&wc); hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDM_MENU)); hwnd = CreateWindow(szClassName,      TEXT("Menu Demo"),      WS_OVERLAPPEDWINDOW,      CW_USEDEFAULT,      CW_USEDEFAULT,      CW_USEDEFAULT,      CW_USEDEFAULT,      NULL,NULL,      hInstance,NULL); SetMenu(hwnd, hMenu);  ShowWindow(hwnd, nCmdShow); 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){ switch(message) { case WM_COMMAND:  switch(LOWORD(wParam))  {  case IDM_MENU_ABOUT_EDIT:   // 关于->作者 产生的消息   MessageBox(hwnd, TEXT("作者:XXX \n日期:2014-04-01"),TEXT("测试"), MB_OK);   break;  case IDM_MENU_CANCEL: //退出消息      PostQuitMessage(0);     break;  }  return 0; case WM_DESTROY:  PostQuitMessage(0);  return 0; } return DefWindowProc(hwnd, message, wParam, lParam);}

运行:

0 0