• Windows 程序设计(4) MFC-01前置知识


    1. Windows编程简介

    1.0 开发环境

    操作系统 Win10
    IDE: VS2017

    1.1 Windows程序简介

    Windows程序呢也主要分那么几种,例如:exe的可执行程序,dll的动态链接库程序,lib的静态库程序,sys的驱动类型程序等等。这些都可以用VC++来开发。

    Exe类的程序从操作界面的使用角度来说又分成两种:
    第一种:黑窗口的控制台下的程序,这种程序一般没有什么界面,都是使用命令行进行操作,比如:ipconfig、ping 之类的。使用系统提供的cmd控制台进行加载。入口点函数是 main。
    第二种:非控制台类型的程序,这种程序可以有界面,也可以没有界面。

    想要界面就调用创建窗口的API函数去创建个界面出来,不想要界面呢不创建就可以了。所以呢比较灵活。入口点函数是 WinMain。

    1.3 Windows编程开发相关概念

    1.3.1 Windows API

    Windows操作系统应用程序接口(Windows API),有非正式的简称法为WinAPI,是微软对于Windows操作系统中可用的核心应用程序编程接口的称法。

    它被设计为各种语言的程序调用,也是应用软件与Windows系统最直接的交互方式。

    大多数驱动程序需要对Windows系统更底层次访问接口,由所用版本的Windows的Native API来提供接口。

    Windows有一个软件开发包(SDK, software development kit)提供相应的文档和工具,以使程序员开发使用Windows API的软件和利用Windows技术。

    1.3.2 开发语言与API

    仅仅使用:C++,只能编写一些简单的控制台下的黑窗口程序。或者说只能调用C++基本语言内部的函数。但是如果你要创建一个窗口,如果你要创建一个按钮,如果你要创建一个菜单,如果你要创建一个进程,如果你要做一个带界面的任务管理器,就要调用windows系统提供给我们的API接口

    对比 iOS 使用 Objective-C作为语言,但是API是 iOS SDK

    Android使用 Java作为开发语言,但是写窗口要 Android SDK

    1.3.3 基本的Win32程序:

    Win32 Project 创建



    // WindowsSDKFirst.cpp : 定义应用程序的入口点。
    //
    
    #include "framework.h"
    #include "WindowsSDKFirst.h"
    
    #define MAX_LOADSTRING 100
    
    // 全局变量:
    HINSTANCE hInst;                                // 当前实例
    WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
    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_WINDOWSSDKFIRST, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // 执行应用程序初始化:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSSDKFIRST));
    
        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_WINDOWSSDKFIRST));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSSDKFIRST);
        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; // 将实例句柄存储在全局变量中
    
       HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
       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)
    {
        switch (message)
        {
        case WM_COMMAND:
            {
                int wmId = LOWORD(wParam);
                // 分析菜单选择:
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    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;
    }
    
    

    当前工程模版默认创建出来的这个窗口不是对话框,所以是没办法进行拖拽控件的,对于小白来说想快速的拖拽控件做出一个窗口看来是有点麻烦了。
    实际上Win32类型的工程就是调用基本的系统提供的API函数来写程序的

    1.4 解决方案:

    本身C++就是一门面相对象的,可封装的语言,所以能不能对系统提供的API函数以及复杂的开发流程进行一下封装呢,这样我们以后使用起来就能方便不少?答案是:当然可以了。所以现在市面上有很多封装好的C++库,或者说框架,比如:MFC、QT,这两个算是比较有名的,而且他们两个不仅仅是界面库,还包括很多其他的操作,比如文件管理,字符串操作,网络管理,多线程,数据库操作,注册表操作等等吧,很多方面。

    1.4.1 MFC

    MFC:微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API,并且包含一个(也是微软产品的唯一一个)应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。

    优点
    1. VC对MFC支持的也很好。
    1. 对于界面方面实现起来简单,易于上手,能快速的制作简单的UI界面**,
    1. 执行效率高,生成的EXE或者其他程序可以直接在Windows系统上执行,生成的文件体积也比较小
    缺点:
    1. 因为是对WinApi的封装,里面用到了大量的宏,所以有时候是基于面向过程的,有时候是基于面向对象的,内部也是使用基于Windows系统的消息机制,所以学起来不是那么容易,学习周期长
    1. 微软自己的东西,所以不能跨平台,在 Linux、Mac 系统上是别想用了。

    总结:所以MFC适合开发对界面美化要求不高软件

    1.4.2 QT

    Qt:是一个跨平台的C++应用程序开发框架。广泛用于开发GUI程序,这种情况下又被称为部件工具箱。也可用于开发非GUI程序,比如控制台工具和服务器。

    优点:

    Qt是一个开源的项目,可以跨平台使用,在 Linux、Mac 系统下一样可以使用。

    使用完全面向对象的封装机制,内部使用信号与槽机制,易于上手。

    开发文档丰富,支持VS插件的形式进行开发。

    可以制作漂亮精美的软件UI界面。省时省力。

    缺点:

    Qt有点过度封装,而且体积也稍大,执行效率没有MFC高,程序分发打包的时候需要将Qt的核心DLL一起随程序打包,不然程序跑步起来。当然也可以用静态库的方式编译,默认只生成一个Exe文件,但这样的话程序的体积会变的很大,不管怎么说Qt生成的文件在分发携带方面的方便性上赶不上Windows的原生程序或者MFC的程序

    总结:所以Qt适合开发对界面美化要求较高的软件。

    MFC 和 QT 就好比 手动档车与自动档车一样,前者开发软件太累,但可控性更加高些。

    建议:界面UI方面使用MFC来开发,除界面外的其他逻辑部分我们全用 原生CPP + SDK API 的方式来做。

    1.5 相关控件

    Button 按钮控件
    CheckBox 复选框控件
    Edit 编辑框控件
    ComboBox 下拉控件
    ListBox 列表控件
    GroupBox 分组控件
    Radio Button 单选框控件
    Static Text 静态文本框控件
    Picture Control 图像控件
    Slider Control 滑块控件
    Spin Control 数值调节钮控件
    Progress Control 进度条控件
    List Control 高级列表控件
    Tree Control 树形控件
    Tab Control 标签控件

    2. MFC对话框工程的建立与使用

    2.1、工程中的类:

    主线程类:CMFCTest
    对话框类:CMFCTestDlg

    2.2、对话框类的初始化函数

    BOOL CXXXDlg::OnInitDialog() 可以把一些对话框的初始化代码放在这个函数中,但要记得,一定要放在 CDialog::OnInitDialog(); 的下面!

    2.3、对话框模版资源

    默认情况下:IDD_XXX_DIALOG 为主对话框资源,我们可以自定义的往界面上拖拽各种控件。

    2.4、都是窗口

    Windows系统中的各个大家能看到的小界面都可以看做是窗口,一个对话框是个窗口,对话框上面的按钮控件也同样可以看做个一个小窗口,针对于窗口的任何操作都适用于对话框,也适用于按钮、编辑框、下拉选择框 等等各个控件。因为他们都是窗口。所有的窗口都有个标识窗口的变量类型,叫做窗口句柄:HWND,实际上他就是个指针。不同的窗口这个值都是不一样的。以后会经常用到HWND这个类型。

  • 相关阅读:
    Angular4学习笔记(六)- Input和Output
    Angular4学习笔记(五)- 数据绑定、响应式编程和管道
    Angular4学习笔记(四)- 依赖注入
    Angular4学习笔记(三)- 路由
    Angular4学习笔记(二)-在WebStorm中启动项目
    Angular4学习笔记(一)-环境搭建
    HTML5移动Web开发(六)——定义一个内容策略
    HTML5移动Web开发(五)——移动设计之CSS媒介查询
    HTML5移动Web开发(四)——移动设计
    HTML5移动Web开发(三)——在移动网站中使用HTML5
  • 原文地址:https://www.cnblogs.com/chance0x1/p/13110228.html
Copyright © 2020-2023  润新知