/*----------------------------------------------
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 检索或设置fType和dwTypeData成员 */
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
本文档展示了如何在Windows程序设计中创建带有位图菜单项的应用程序。通过`GRAFMENU.C`代码分析,讲解了如何加载位图资源、创建菜单、响应菜单事件,以及添加自定义帮助菜单项。程序使用`WinAPI`,包含窗口类注册、消息处理、系统菜单和自定义菜单的创建与管理。
4876

被折叠的 条评论
为什么被折叠?



