`
java-mans
  • 浏览: 11430800 次
文章分类
社区版块
存档分类
最新评论

windows程序设计(17):使用菜单

 
阅读更多

菜单应该算是比较简单的资源了,因为菜单的设计跟VB很像,图形界面的,你只要写菜单按钮的响应程序就行了。每个菜单都有自己的ID。菜单的消息是通过WM_COMMAND传给系统的,通过消息的wParam的低字节,就能获得ID号。需要注意的是,你最好把ID设成宏一样,见到名字就能看懂意思,不要用原配的那种数字。菜单的属性框中,还能选择菜单是否被选中,能否使用,是否变灰等等。

下来看看程序:

/*-----------------------------------------
   MENUDEMO.C -- Menu Demonstration
			  (c) Charles Petzold, 1998
  -----------------------------------------*/

#include <windows.h>
#include "resource.h"

#define ID_TIMER 1
#define MAX_COLOR 5

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 ;
	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.lpszClassName = szAppName ;
	
	if (!RegisterClass (&wndclass))
	{
		MessageBox (NULL, TEXT ("This program requires Windows NT!"),
				  szAppName, MB_ICONERROR) ;
		return 0 ;
	}
	
	hwnd = CreateWindow (szAppName, TEXT ("Menu Demonstration"),
					 WS_OVERLAPPEDWINDOW,
					 CW_USEDEFAULT, CW_USEDEFAULT,
					 CW_USEDEFAULT, CW_USEDEFAULT,
					 NULL, 
					 //装载菜单
					 LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU2)),
					 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)
{

	HMENU	 hMenu ;
	HDC		 hdc;
	//定义一个数组,里面存储着背景菜单中的不同颜色消息
	static TCHAR idColor [MAX_COLOR] = { IDM_BKGND_WHITE,  IDM_BKGND_LTGRAY, IDM_BKGND_GRAY,
                                IDM_BKGND_DKGRAY, IDM_BKGND_BLACK } ;
    switch (message)
    {
	//菜单消息
    case WM_COMMAND:

		hMenu = GetMenu (hwnd) ;
		hdc = GetDC(hwnd);  
		//
		switch (LOWORD (wParam))
		{
			//暂时没有其他操作,只发出蜂鸣
			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_CUT:
			case IDM_EDIT_COPY:
			case IDM_EDIT_PASTE:
			case IDM_EDIT_CLEAR:
				MessageBeep (0) ;
			return 0 ;
			
			//白色
			case IDM_BKGND_WHITE:			
				
				
				for(int i = 0;i < MAX_COLOR ; i++)
				{
					if(idColor[i] == IDM_BKGND_WHITE)
						CheckMenuItem (hMenu, idColor[i], MF_CHECKED) ;
					//
					else
					{
						CheckMenuItem (hMenu, idColor[i], MF_UNCHECKED) ;
					}
				}

				//改变wndclacc类里面的背景
				SetClassLong (hwnd, GCL_HBRBACKGROUND, 
					(LONG) GetStockObject (WHITE_BRUSH)) ;
				//刷新
				InvalidateRect (hwnd, NULL, TRUE) ;
				
				return 0;

			//浅灰
			case IDM_BKGND_LTGRAY:
				
				for(int i = 0;i < MAX_COLOR ; i++)
				{
					if(idColor[i] == IDM_BKGND_LTGRAY)
						CheckMenuItem (hMenu, idColor[i], MF_CHECKED) ;
					else
					{
						CheckMenuItem (hMenu, idColor[i], MF_UNCHECKED) ;
					}
				}

 
				SetClassLong (hwnd, GCL_HBRBACKGROUND, 
					(LONG) GetStockObject (LTGRAY_BRUSH)) ;
				InvalidateRect (hwnd, NULL, TRUE) ;
				return 0;

			//灰色
			case IDM_BKGND_GRAY:
				for(int i = 0;i < MAX_COLOR ; i++)
				{
					if(idColor[i] == IDM_BKGND_GRAY)
						CheckMenuItem (hMenu, idColor[i], MF_CHECKED) ;
					else
					{
						CheckMenuItem (hMenu, idColor[i], MF_UNCHECKED) ;
					}
				}				


				SetClassLong (hwnd, GCL_HBRBACKGROUND, 
					(LONG) GetStockObject (GRAY_BRUSH)) ;
				InvalidateRect (hwnd, NULL, TRUE) ;
				return 0;

			//深灰
			case IDM_BKGND_DKGRAY:
				for(int i = 0;i < MAX_COLOR ; i++)
				{
					if(idColor[i] == IDM_BKGND_DKGRAY)
						CheckMenuItem (hMenu, idColor[i], MF_CHECKED) ;
					else
					{
						CheckMenuItem (hMenu, idColor[i], MF_UNCHECKED) ;
					}
				}				


				SetClassLong (hwnd, GCL_HBRBACKGROUND, 
					(LONG) GetStockObject (DKGRAY_BRUSH)) ;
				InvalidateRect (hwnd, NULL, TRUE) ;
				return 0;


			case IDM_BKGND_BLACK:
				for(int i = 0;i < MAX_COLOR ; i++)
				{
					if(idColor[i] == IDM_BKGND_BLACK)
						CheckMenuItem (hMenu, idColor[i], MF_CHECKED) ;
					else
					{
						CheckMenuItem (hMenu, idColor[i], MF_UNCHECKED) ;
					}
				}					


				SetClassLong (hwnd, GCL_HBRBACKGROUND, 
					(LONG) GetStockObject (BLACK_BRUSH)) ;
				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 ("自己百度"),
					  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 ;
				ReleaseDC(hwnd,hdc);
		}
		break ;
		
	case WM_TIMER:
		MessageBeep (0) ;
		return 0 ;
			
	case WM_DESTROY:
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;
}


在创建窗口时,就要加载菜单。程序中前两个菜单里的内容都没啥作用。只有文件->退出导致一个关闭窗口的消息WM_CLOSE。这个消息会导致WM_DESTROY。

有用的就是改变背景以及计时器,以及帮助。改变背景时,源程序玩了一个很投机取巧的花样,大家可以看Charles Petzold那本书,我在这里使用·了一个更为常见的作法,就是在每个消息下,写他自己的相应。但是,为了保证背景菜单里的内容始终保持单选效果,需要在每个消息下,把背景菜单中的别的选项置为没有选中,而把自己设为选中。而改变背景,也不像我一开始想象的使用画图的方法,而是直接改变wndclass中的背景,然后将客户区设为无效,重新刷新一遍。

计时器的内容比较简单,就是开始时发送计时器消息,结束时发送删除计时器的消息。唯一要注意的是,开始计时以后,计时器的开始就被设为灰色的了,不能再使用了,直到结束为止。同理也这样设计了计时器的结束。

分享到:
评论

相关推荐

    Windows程序设计基础课件:第4讲菜单、工具栏、状态栏.pdf

    Windows程序设计基础课件:第4讲菜单、工具栏、状态栏.pdf

    Windows程序设计第十章

    Windows程序设计第十章 Windows程序设计第十章

    Q760642.zip windows程序设计 编写Windows窗口应用程序实现对话框与菜单的应用

    Q760642.zip windows程序设计 编写Windows窗口应用程序实现对话框与菜单的应用 https://ask.csdn.net/questions/760642 编写Windows窗口应用程序实现对话框与菜单的应用 1)编程实现如下应用程序,含有菜单,单击...

    Windows 程序设计(第5版)(上、下册)--详细书签版

    他在《Microsoft Systems Joumal》1986年 12月号上发表了第一篇关于 Windows程序设计的杂志论文。从 1986年到 1995年,他为《PC Magazine》撰写“Environments”专栏,给读者介绍了Windows和OS/2程序设计的许多方面...

    MFC Windows程序设计(第2版修订版)--源代码

     像我的许多同行一样,我学习Windows编程是从读Petzold的书《Windows程序设计》——一本所有Windows程序员都使用的Windows编程圣经——开始的。在刚刚成为一名MFC程序员时,那天我冲进书店,想买一本能够与...

    windows 程序设计

    为说明Windows程序设计的多种技术,本书提供了许多范例程序。这些程序使用C语言撰写并原原本本的使用Windows API来开发程序。我将这种方法称作「古典」Windows程序设计。这是我们在1985年为Windows 1.0写程序的方法...

    windows 程序设计 chm版

    windows 程序设计,很值得阅读 基础篇 1. 开始 2.Unicode简介 3. 窗口和消息 4. 输出文字 5. 图形基础 6. 键盘 7. 鼠标 8. 定时器 9. 子窗口控件 10. 菜单及其它资源 11. 对话框 12. 剪贴...

    windows 程序设计中文版

    10.2.5 菜单和消息 10.2.6 范例程序 10.2.7 菜单设计中的规范 10.2.8 定义菜单的繁琐方式 10.2.9 浮动弹出菜单 10.2.1 0使用系统菜单 10.2.1 1改变菜单 10.2.1 2其他菜单命令 10.2.1 3菜单的另类用法 10.3 键盘加速...

    MFC Windows 程序设计之文档菜单的使用

    MFC Windows 程序设计之文档菜单的使用,适合初学MFC的小伙伴学习研究,博客中有对应的讲解和演示,避免走弯路,费时费力。也真心希望能够帮助正在苦学MFC Windows 程序设计的小伙伴们,你们的成长是我最大的幸福

    Windows程序设计笔记

    6、掌握菜单的使用(菜单消息处理) 7、掌握文件存储(设计存储结构、文件的保存与打开) 8、掌握对话框的使用和参数传递 9、掌握全局变量、外部静态变量、局部静态变量、自动变量的作用范围、生命周期 10、掌握函数...

    《Windows程序设计》中文chm版

    …………………… WINDOWS程序设计选项 …………………… 编写第一个WINDOWS程序 2.Unicode简介 …………………… 字符集简史 …………………… 宽字符和C …………………… 宽字符和WINDOWS 3. 窗口和消息...

    windows程序设计第五版 chm 版本

    《Windows程序设计(第5版 珍藏版)》是一本经典的Windows编程圣经,曾经伴随着近50万Windows程序员步入编程殿堂,成长为IT时代的技术精英。 作为Windows开发人员的必备参考,涵盖基础知识和中高级主题,全面地介绍了...

Global site tag (gtag.js) - Google Analytics