windows程序设计「GRAFMENU.C」范例分析笔记

本文档展示了如何在Windows程序设计中创建带有位图菜单项的应用程序。通过`GRAFMENU.C`代码分析,讲解了如何加载位图资源、创建菜单、响应菜单事件,以及添加自定义帮助菜单项。程序使用`WinAPI`,包含窗口类注册、消息处理、系统菜单和自定义菜单的创建与管理。

/*----------------------------------------------

   GRAFMENU.C -- Demonstrates Bitmap Menu Items

                 (c) Charles Petzold, 1998

  ----------------------------------------------*/

 

#include <windows.h>

#include "resource.h"

 

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

void    AddHelpToSys     (HINSTANCE, HWND) ;

HMENU   CreateMyMenu     (HINSTANCE) ;

HBITMAP StretchBitmap    (HBITMAP) ;

HBITMAP GetBitmapFont    (int) ;

void    DeleteAllBitmaps (HWND) ;

 

TCHAR szAppName[] = TEXT ("GrafMenu") ;

 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    PSTR szCmdLine, int iCmdShow)

{

     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  = NULL ;

     wndclass.lpszClassName = szAppName ;

    

     if (!RegisterClass (&wndclass))

     {

          MessageBox (NULL, TEXT ("This program requires Windows NT!"),

                      szAppName, MB_ICONERROR) ;

          return 0 ;

     }

    

     hwnd = CreateWindow (szAppName, TEXT ("Bitmap Menu Demonstration"),

                          WS_OVERLAPPEDWINDOW,

                          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 iMsg, WPARAM wParam, LPARAM lParam)

{

     HMENU      hMenu ;

     static int iCurrentFont = IDM_FONT_COUR ;

    

     switch (iMsg)

     {

     case WM_CREATE:

                     // 在系统菜单中添加新菜单项(水平分隔符和HELP位图菜单)

          AddHelpToSys (((LPCREATESTRUCT) lParam)->hInstance, hwnd) ;

                     // 建立位图样式的程序菜单

          hMenu = CreateMyMenu (((LPCREATESTRUCT) lParam)->hInstance) ;

                     // 为程序添加自建菜单

          SetMenu (hwnd, hMenu) ;

                     // 放置选取标记于菜单项iCurrentFont旁边

          CheckMenuItem (hMenu, iCurrentFont, MF_CHECKED) ;

          return 0 ;

         

                     // 处理HELP菜单项

     case WM_SYSCOMMAND:

          switch (LOWORD (wParam))

          {

          case IDM_HELP:

               MessageBox (hwnd, TEXT ("Help not yet implemented!"),

                           szAppName, MB_OK | MB_ICONEXCLAMATION) ;

               return 0 ;

          }

          break ;

         

     case WM_COMMAND:

          switch (LOWORD (wParam))

          {

          case IDM_FILE_NEW:

          case IDM_FILE_OPEN:

          case IDM_FILE_SAVE:

          case IDM_FILE_SAVE_AS:

          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_FONT_COUR:

          case IDM_FONT_ARIAL:

          case IDM_FONT_TIMES:

               hMenu = GetMenu (hwnd) ;

               CheckMenuItem (hMenu, iCurrentFont, MF_UNCHECKED) ;

               iCurrentFont = LOWORD (wParam) ;

               CheckMenuItem (hMenu, iCurrentFont, MF_CHECKED) ;

               return 0 ;

          }

          break ;

              

     case WM_DESTROY:

          DeleteAllBitmaps (hwnd) ;

          PostQuitMessage (0) ;

          return 0 ;

     }

     return DefWindowProc (hwnd, iMsg, wParam, lParam) ;

}

 

/*----------------------------------------------------

   AddHelpToSys: 在系统菜单中添加新菜单项(水平分隔符和HELP位图菜单)

  ----------------------------------------------------*/

 

void AddHelpToSys (HINSTANCE hInstance, HWND hwnd)

{

     HBITMAP hBitmap ;

     HMENU   hMenu ;

 

          //取窗口系统菜单句柄

     hMenu = GetSystemMenu (hwnd, FALSE);

          // 载入Help位图资源进程序内存

     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapHelp"))) ;

          // 在菜单项中增加一个水平分隔符和包含位图的新菜单项,标识符为IDM_HELP

     AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;

     AppendMenu (hMenu, MF_BITMAP, IDM_HELP, (PTSTR) (LONG) hBitmap) ;

}

 

/*----------------------------------------------

   CreateMyMenu: 建立位图样式的程序菜单

  ----------------------------------------------*/

 

HMENU CreateMyMenu (HINSTANCE hInstance)

{

     HBITMAP hBitmap ;

     HMENU   hMenu, hMenuPopup ;

     int     i ;

 

          // 创建一个空项目的菜单

     hMenu = CreateMenu () ;

     // 载入MenuFile菜单资源和BitmapFile位图资源

     hMenuPopup = LoadMenu (hInstance, TEXT ("MenuFile")) ;

     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapFile"))) ;

          // 在新建立的空白菜单中添加位图和弹出式样式的菜单项

     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,

                        (PTSTR) (LONG) hBitmap) ;

    

     hMenuPopup = LoadMenu (hInstance, TEXT ("MenuEdit")) ;

     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapEdit"))) ;

     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,

                        (PTSTR) (LONG) hBitmap) ;

    

          // 再建新空白菜单项,用于设计FONT菜单

     hMenuPopup = CreateMenu () ;

    

     for (i = 0 ; i < 3 ; i++)

     {

                    // 依次创建以三种逻辑字体为内容的位图,并添加到FONT菜单中

          hBitmap = GetBitmapFont (i) ;

          AppendMenu (hMenuPopup, MF_BITMAP, IDM_FONT_COUR + i,

                                  (PTSTR) (LONG) hBitmap) ;

     }

    

          // 添加FONT菜单到程序菜单中

     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapFont"))) ;

     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,

                        (PTSTR) (LONG) hBitmap) ;

     return hMenu ;

}

 

/*----------------------------------------------------

   StretchBitmap: 依系统字体为基础,重新设计位图大小

  ----------------------------------------------------*/

 

HBITMAP StretchBitmap (HBITMAP hBitmap1)

{

     BITMAP     bm1, bm2 ;

     HBITMAP    hBitmap2 ;

     HDC        hdc, hdcMem1, hdcMem2 ;

     int        cxChar, cyChar ;

 

     // 获取系统字体字符的宽度和高度

     cxChar = LOWORD (GetDialogBaseUnits ()) ;

     cyChar = HIWORD (GetDialogBaseUnits ()) ;

    

          // 创建屏幕的设备场景,并以此再创建两个与其兼容的内存设备内容

     hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;

     hdcMem1 = CreateCompatibleDC (hdc) ;

     hdcMem2 = CreateCompatibleDC (hdc) ;

     DeleteDC (hdc) ;

 

     // 获取实参位图的结构信息

     GetObject (hBitmap1, sizeof (BITMAP), (PTSTR) &bm1) ;

 

     // 依系统字体为基础,重新设计位图大小

     bm2 = bm1 ;

     bm2.bmWidth      = (cxChar * bm2.bmWidth)  / 4 ;

     bm2.bmHeight     = (cyChar * bm2.bmHeight) / 8 ;

     bm2.bmWidthBytes = ((bm2.bmWidth + 15) / 16) * 2 ;

 

     // 创建特定结构的位图

     hBitmap2 = CreateBitmapIndirect (&bm2) ;

 

          // Select the bitmaps in the memory DCs and do a StretchBlt

    

     SelectObject (hdcMem1, hBitmap1) ;

     SelectObject (hdcMem2, hBitmap2) ;

    

          // 把实参位图拉伸显示到新建立的位图中

     StretchBlt (hdcMem2, 0, 0, bm2.bmWidth, bm2.bmHeight,

                 hdcMem1, 0, 0, bm1.bmWidth, bm1.bmHeight, SRCCOPY) ;

 

     // 清理工作,返回用于FONT菜单项的位图句柄

     DeleteDC (hdcMem1) ;

     DeleteDC (hdcMem2) ;

     DeleteObject (hBitmap1) ;

    

     return hBitmap2 ;

}

 

/*------------------------------------------------

   GetBitmapFont: 创建以三种逻辑字体之一为内容的位图

  ------------------------------------------------*/

 

HBITMAP GetBitmapFont (int i)

{

     static TCHAR  * szFaceName[3] = { TEXT ("Courier New"), TEXT ("Arial"),

                                       TEXT ("Times New Roman") } ;

     HBITMAP         hBitmap ;

     HDC             hdc, hdcMem ;

     HFONT           hFont ;

     SIZE            size ;

     TEXTMETRIC      tm ;

    

          // 创建整个屏幕的设备场景,用于快速低开销的获取相关设备信息

     hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;

          // 获取程序当前的字体信息,存放到TEXTMETRIC结构中

     GetTextMetrics (hdc, &tm) ;

    

          // 创建与视讯设备兼容的内存设备上下文环境和自建逻辑字体,

     hdcMem = CreateCompatibleDC (hdc) ;

     hFont  = CreateFont (2 * tm.tmHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

                          szFaceName[i]) ;

 

          // 将自建字体选进内存设备内容中,并保存先前的字体句柄

     hFont = (HFONT) SelectObject (hdcMem, hFont) ;

 

          // 计算选进内存设备内容中的正文字符串的高度和宽度

     GetTextExtentPoint32 (hdcMem, szFaceName[i],

                           lstrlen (szFaceName[i]), &size);

    

          // 创建以自建文字信息为大小的单色位图,并选进内存设备内容中

     hBitmap = CreateBitmap (size.cx, size.cy, 1, 1, NULL) ;

     SelectObject (hdcMem, hBitmap) ;

    

          // 将文字写在内存设备内容中

     TextOut (hdcMem, 0, 0, szFaceName[i], lstrlen (szFaceName[i])) ;

    

          // 恢复默认字体,删除自建字体、内存设备内容和设备信息场景

     DeleteObject (SelectObject (hdcMem, hFont)) ;

     DeleteDC (hdcMem) ;

     DeleteDC (hdc) ;

    

     return hBitmap ;

}

 

/*-------------------------------------------------------

   DeleteAllBitmaps: 删除建立的菜单和位图

  -------------------------------------------------------*/

 

void DeleteAllBitmaps (HWND hwnd)

{

     HMENU        hMenu ;

     int          i ;

          /* MIIM_SUBMENU 检索或设置hSubMenu成员

             MIIM_TYPE    检索或设置fTypedwTypeData成员 */

     MENUITEMINFO mii = { sizeof (MENUITEMINFO), MIIM_SUBMENU | MIIM_TYPE } ;

 

     hMenu = GetSystemMenu (hwnd, FALSE);

          // 取得与一个菜单条目有关的特定信息到MENUITEMINFO结构中

          // 第三个参数如果为TRUE说明参数二指定的是条目位置,否则为菜单ID

     GetMenuItemInfo (hMenu, IDM_HELP, FALSE, &mii) ;

          // dwTypeData低位字是索检的位图句柄,删除HELP位图对象

     DeleteObject ((HBITMAP) mii.dwTypeData) ;

 

          // 获取程序菜单句柄

     hMenu = GetMenu (hwnd) ;

 

     for (i = 0 ; i < 3 ; i++)

     {

                    // 依次索检并删除三个下拉式菜单项位图

          GetMenuItemInfo (hMenu, i, TRUE, &mii) ;

          DeleteObject ((HBITMAP) mii.dwTypeData) ;

     }

 

          // 最后一次的GetMenuItemInfo调用中,

          // 元素hSubMenu记录了FONT菜单项相关联的下拉菜单或子菜单的的句柄

     hMenu = mii.hSubMenu ;;

 

     for (i = 0 ; i < 3 ; i++)

     {

                    // 参数三为TRUE,表明了是条目位置

                    // 依次索检和删除FONT关联的三个子菜单项位图

          GetMenuItemInfo (hMenu, i, TRUE, &mii) ;

          DeleteObject ((HBITMAP) mii.dwTypeData) ;

     }

}


/*-------------------------------------------------------

   GrafMenu.rc: 资源文件

  -------------------------------------------------------*/

 

//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 _WIN32

LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

#pragma code_page(1252)

#endif //_WIN32

 

#ifdef APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

 

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h/0"

END

 

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""/r/n"

    "/0"

END

 

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "/r/n"

    "/0"

END

 

#endif    // APSTUDIO_INVOKED

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

 

MENUFILE MENU DISCARDABLE

BEGIN

    MENUITEM "&New",                        IDM_FILE_NEW

    MENUITEM "&Open...",                    IDM_FILE_OPEN

    MENUITEM "&Save",                       IDM_FILE_SAVE

    MENUITEM "Save &As...",                 IDM_FILE_SAVE_AS

END

 

MENUEDIT MENU DISCARDABLE

BEGIN

    MENUITEM "&Undo",                       IDM_EDIT_UNDO

    MENUITEM SEPARATOR

    MENUITEM "Cu&t",                        IDM_EDIT_CUT

    MENUITEM "&Copy",                       IDM_EDIT_COPY

    MENUITEM "&Paste",                      IDM_EDIT_PASTE

    MENUITEM "De&lete",                     IDM_EDIT_CLEAR

END

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Bitmap

//

 

BITMAPFONT              BITMAP  DISCARDABLE     "Fontlabl.bmp"

BITMAPHELP              BITMAP  DISCARDABLE     "Bighelp.bmp"

BITMAPEDIT              BITMAP  DISCARDABLE     "Editlabl.bmp"

BITMAPFILE              BITMAP  DISCARDABLE     "Filelabl.bmp"

#endif    // English (U.S.) resources

/////////////////////////////////////////////////////////////////////////////

 

 

 

#ifndef APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

 

 

/////////////////////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值