您的位置:首页 > 其它

Windows学习心得【菜单的实现】

2014-04-28 20:15 218 查看
由于翘了太多课,落下了太多课程,还有几周就要考试所以前几天就没写博客了,一直都在补习前面拉下的课程。真心觉得时间不够用啊,伤不起哦
#include <windows.h>
#include "resource.h"

#define ID_TIMER 1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//首先是一个回调函数的声明

TCHAR szAppName[] = TEXT ("MenuDemo") ;//可作为窗口名和菜单名

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 ;//窗口扩展,此处为0
wndclass.cbWndExtra    = 0 ;//窗口实例扩展,此处为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.lpszClassName = szAppName ;//窗口类名

if (!RegisterClass (&wndclass))//注册窗口,若注册失败,产生如下的信息
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}

////创建窗口,如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。
hwnd = CreateWindow (szAppName,
TEXT ("Menu Demonstration"),//窗口的名字
WS_OVERLAPPEDWINDOW,//指定创建窗口的风格
CW_USEDEFAULT, //指定窗口的初始水平位置
CW_USEDEFAULT,//指定窗口的初始垂直位置
CW_USEDEFAULT, //以设备单元指明窗口的宽度。若是CW_USEDEFAULT,则系统为窗口选择一个缺省的宽度
CW_USEDEFAULT,//以设备单元指明窗口的高度
NULL, //指向被创建窗口的父窗口或所有者窗口的句柄,此处为NULL
NULL, //菜单句柄,或依据窗口风格指明一个子窗口标识,此处为NULL
hInstance, //与窗口相关联的模块实例的句柄
NULL) ;//指向一个值的指针,该值传递给窗口WM_CREATE消息

ShowWindow (hwnd, iCmdShow) ;//显示窗口,hWnd:指窗口句柄。iCmdShow:指定窗口如何显示
UpdateWindow (hwnd) ;//更新窗口,hWnd:指窗口句柄

while (GetMessage (&msg, NULL, 0, 0))//消息循环
{
TranslateMessage (&msg) ;//该函数将虚拟键消息转换为字符消息
DispatchMessage (&msg) ;//该函数分发一个消息给窗口程序
}
return msg.wParam ;//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 ;//背景为白色的ID标识
HMENU      hMenu ;//定义一个菜单句柄

switch (message)
{
case WM_COMMAND://
hMenu = GetMenu (hwnd) ;//GetMenu函数取得分配给指定窗口的菜单的句柄
//参数的意思是本菜单所在的窗口的句柄

switch (LOWORD (wParam))
{
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
case IDM_FILE_SAVE:
case IDM_FILE_SAVE_AS:
MessageBeep (0) ;//MessageBeep函数用来播放一个波形声音
//详细参数请参考MSDN,这里就不说了,原来有一篇里面讲过的
return 0 ;

case IDM_APP_EXIT://退出程序,这是一个ID标识
SendMessage (hwnd, WM_CLOSE, 0, 0) ;
//SendMessage函数将指定的消息发送到一个或多个窗口
//第一个参数的意思是发送窗口的句柄
//第二个是消息
//第三第四个为附加消息,一般为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.

CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;
//CheckMenuItem是一个API函数,功能是复选或撤消复选指定的菜单条目
//第一个参数为含有其菜单项的标志将被提取得的菜单的句柄
//第二个参数为要修改的菜单项
//第三个参数为相当于MF_CHECKED 的反作用,取消放置于菜单项旁边的标记
iSelection = LOWORD (wParam) ;//获取当前的背景颜色信息
CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;
//MF_CHECKED功能为放置选取标记于菜单项旁边(只用于下拉式菜单、子菜单或快捷菜单)

SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)
GetStockObject
(idColor [LOWORD (wParam) - IDM_BKGND_WHITE])) ;
//SetClassLong函数功能:该函数替换额外的类存储空间中指定偏移量处的32位长整型值,或替换指定窗口所属类的WNDCLASSEX结构
//这是百度百科上的原话,我现在还是不太明白作者到底想说什么,理解不了啊
//第一个参数为窗口句柄及间接给出的窗口所属的类
//第二个参数为指定将被替换的32位值。GCL_HBRBACKGROUND:替换与类有关的背景刷子的句柄
//第三个参数为指定的替换值

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) ;
}
//SetTimer创建或设置一个定时器,如果成功返回非0,否则返回0
//EnableMenuItem意为允许、禁止或变灰指定的菜单条目
//第一个参数为菜单句柄
//第二个参数为欲允许或禁止的一个菜单条目的标识符,就代表欲改变菜单条目的命令ID
//第三个参数就是说这个菜单名字要怎么改变,详细情况请参考MSDN
return 0 ;

case IDM_TIMER_STOP:
KillTimer (hwnd, ID_TIMER) ;//移除先前用SetTimer设置的定时器
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_TIMER:
MessageBeep (0) ;//MessageBeep函数用来播放一个波形声音
return 0 ;

case WM_DESTROY:
PostQuitMessage (0) ;//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;//该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理
}
有关自定义资源的实现我觉得不是很难,主要是资源ID可能有些不够重视,加上很多菜单等要弄的ID会很多,一不小心就会和程序里面的搞乱,所以那要注意一下,下面附上图片





注意这里的ID很多同学不注意这里导致程序报错。所以要注意一下哈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: