Windows编程基础,菜单

菜单

使用VS2017(Visual studio 2017)进行程序的编译。
要使主窗口有自定义的菜单,应将wcex.lpszMenuName这个注册窗口类的默认值修改,改为null,这样就不会显示VS默认的菜单了。
下面的代码我直接调用MAKEINTRESOURCE()函数(这是一个进行资源名转换的宏,将数字类型ID转换为字符类型,这里我们注意到在wcex.lpszMenuName的类型是LPCTSTR,所以我们使用该函数进行类型转换,类似C语言的强制类型转换)并将参数设为自定义菜单的ID。
而如何在VS中构建自定义菜单我会在下文进行操作的说明。

    wcex.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU1);

在VS中,点击**“视图”,在菜单项目中点击“其他窗口”,再点击“资源视图”,我们便获得了定义项目的资源视图
exp:
在这里插入图片描述
可以看到.rc下的各个部分,Menu就是我们要用到的,点开Menu,可以看到程序自带的Menu的ID,之后如何自定义菜单,右键Menu,在弹出菜单栏中点击
添加资源即可。
可以根据菜单的属性(点击要编辑的地方便会出现属性,属性栏位于屏幕右下角,可以直接修改内容)进行相应的修改和自定义,左边边栏的工具箱是非常实用的,包括文本框等(一股VB的既视感)。
使用新插入对菜单的项目进行增添,注意,每次增添新项目
系统会自动生成相应的IDM**(可在resource.h中查看),便于之后你在WM_COMMAND中进行菜单项目的不同case的代码编写。

模态对话框和非模态对话框

模态对话框:
当程序显示一个模态对话框时,使用者不能再对话方块与同一个程序中的另一个视窗之间进行切换,必须主动结束该对话框(通过按下OK或者Cancel键来完成)。但是在显示对话框时,使用者可以从目前的程序切换到另一个程序。然后,有些称为【系统模态】的对话框甚至不允许像这样的,进行程序间的切换。
Windows程式即使不需要接收使用者的输入,也通常具有功能表上的【About】选项启动的对话框,该对话框用来显示程式的名字、图示、版权旗标和标记为【OK】的按键。
什么是功能表?可参考《Windows程序设计》第十章:功能表和其他资源。
启动对话框:
在WndProc中处理WM_CREATE讯息,取得程式的执行实体代号并将它放在静态变数中:

	hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
检查WM_COMMAND讯息,确保wParam的低位元字等于所要执行的IDM。当它获得这样一个讯息时,程式呼叫DialogBox:
DialogBox(hInstance,TEXT("AboutBox"),hwnd,AboutDlgProc);

这里贴一个该函数的详细信息:

DialogBox(hInstance, lpTemplate, hWndParent, lpDialogFunc);

该函数需要执行实体代号(在处理 WM_CREATE 时储存的)、对话方块名称(在资源描述档中定义的)、对话方块的父视窗(也是程式的主视窗)和对话 方块程序的位址。如果您使用一个数字而不是对话方块模板名称,那么可以用 MAKEINTRESOURCE 巨集将它转换为一个字串(上文有特别提到)。
如同添加自定义菜单,可以使用VS进行快速的自定义对话框。

非模态对话框:
允许使用者在对话框和其他程式之间进行切换,也可以在对话框和建立对话框的视窗之间进行切换。模态对话框通过DialogBox建立,只有在清除对话框后,函数才会传回值。在对话框程序内使用EndDialog呼叫来中止对话框,DialogBox传回的是该呼叫的第二个参数的值。

EndDialog(
    _In_ HWND hDlg,
    _In_ INT_PTR nResult);

非模态对话框是使用CreateDialog来建立的。该函数树勇的参数与DialogBox相同:

 CreateDialog(hInstance, lpTemplate, hWndParent, lpDialogFunc);

区别:
CreateDialog立即传回对话框的视窗代号,并通常将这个视窗代号存放在全局变量中。
而销毁非模态对话框则用

EndPaint(  _In_ HWND hWnd,   _In_ CONST PAINTSTRUCT *lpPaint);

将参数设置为你创建的非模态对话框的句柄即可。

附上一个简单的程序作业,帮助理解菜单和对话框的使用。
要求:
重新定义菜单名为File(F),包含show、hire、exit三个菜单子项目。点击show触发对话框,显示特定语句(无其他按钮,单单只有文本),点击hire销毁show所触发的对话框(暗示在对话框弹出时还能对父窗口进行操作,涉及到模态对话框和非模态对话框的辨别),点击exit关闭整个窗口。

样例代码:

//WindowsProject11.cpp: 定义应用程序的入口点。
//

#include "stdafx.h"
#include "WindowsProject11.h"

#define MAX_LOADSTRING 100

// 全局变量: 
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING] = TEXT("Dialog Demo");                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名

// 此代码模块中包含的函数的前向声明: 
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此放置代码。

    // 初始化全局字符串
    //LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT11, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化: 
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT11));

    MSG msg;

    // 主消息循环: 
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT11));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU1);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中
  // HMENU hMenu = CreateMenu();//菜单句柄,句柄就是一个数,标识一个资源
   //HMENU hPopMenu = CreatePopupMenu();//创建一个弹出菜单
  // AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hPopMenu, _T("操作"));
   //AppendMenu(hPopMenu, MF_STRING, ID_MOVE, _T("移动"));

   HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
	  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	static HWND hdialog = NULL;

    switch (message)
    {


    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
			int wmEvent = HIWORD(wParam);//代表高位事件

            // 分析菜单选择: 
            switch (wmId)
            {

			case ID_FILE_SHOW:
				hdialog = CreateDialog(hInst, MAKEINTRESOURCE(IDD_WINDOWSPROJECT11_DIALOG), hWnd, About);
				ShowWindow(hdialog, SW_SHOW);
				break;
			case ID_FILE_HIRE:
				//CreateDialog(hInst, MAKEINTRESOURCE(IDD_WINDOWSPROJECT11_DIALOG), hWnd, About);

				DestroyWindow(hdialog);
				break;
            case ID_FILE_EXIT32774:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {

            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值