zoukankan      html  css  js  c++  java
  • Windows应用程序基础

    关于Windows应用程序的基础,基本内容就是那几项,以前学MFC的时候看孙鑫的视频讲过一遍,学习DirectX的时候学过一遍。现在回来想做MFC的程序,发现又忘了,这种学了忘忘了学的感觉真烦恼,每次都要从头学起,每次都是新手。所以我决定一定要自己写个总结,可能还是会忘记,但是查看自己的总结感觉踏实一些。

    一. WinMain函数

    Windows程序的入口函数:

    int WINAPI WinMain(
    
        HINSTANCE hInstance, // handle to current instance
        // 应用程序实例的句柄。同一程序代码也有可能有多个实例,因为应用程序实例也是一种资源,所以需要对应用程序实例进行标识。
    
        HINSTANCE hPrevInstance, // handle to previous instance
        // 先前实例的标识,之前没有则为空。Win32下总是为空。
    
        LPSTR lpCmdLine, // command line
        //LP表示长指针,STR表示字符串,所以LPSTR表示指向字符串的指针。lpCmdLine接受命令行参数。
    
        int nCmdShow // show state
        // 显示状态,指定程序运行的时候应该如何显示
    );

    WinMain函数由操作系统调用,因此WinMain函数的参数都是由操作系统进行赋值。

    二.窗口

    窗口一般需要进行以下几个步骤:

    1.设计窗口

    2.注册窗口

    3.创建窗口

    4.显示及更新窗口

    窗口类是一个结构体

    typedef struct WNDCLASSEX
     { 
        UINT style; 
        WNDPROC lpfnWndProc; 
        int cbClsExtra; 
        int cbWndExtra; 
        HANDLE hInstance; 
        HICON hIcon; 
        HCURSOR hCursor; 
        HBRUSH hbrBackground; 
        LPCTSTR lpszMenuName; 
        LPCTSTR lpszClassName;
     } WNDCLASS;

    1.设计窗口

    设计窗口类。

    WNDCLASSEX wc;
    
    //窗口类的类型
    wc.style = CS_HREDRAW | CS_VREDRAW; //水平或垂直位置变化的时候要求窗口重画
    
    //窗口过程函数,一个指针,指向一个窗口过程,用来接收一个函数指针,用来指定窗口对应的过程函数/回调函数
    wc.lpfnWndProc = (WNDPROC) WndProc; //函数名可以代表代码的首地址
    
    //类的附加内存
    wc.cbClsExtra = 0; //通常情况下设置为0
    
    //窗口的附加内存空间
    wc.cbWndExtra = 0;
    
    wc.cbSize = sizeof(WNDCLASSEX);
    
    //应用程序实例号,来自WinMain函数参数
    wc.hInstance = hInstance;
    
    //图标句柄
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    //标准图标被加载的时候第一个参数必须为NULL
    
    //如果要自定义的图标的话
    //wc.hIcon = LoadIcon(hInstance, //(LPCTSTR)IDI_DIRECTX_ICON);
    
    //光标句柄
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    
    //画刷的句柄
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    
    //菜单的名字
    wc.lpszMenuName = 0;
    
    //窗口类的名字
    wc.lpszClassName = "Class Name";

    2.注册窗口

    窗口设计完之后,需要向操作系统进行注册,之后才可以创建基于这种窗口类型的窗口。

    //函数原型:
    //ATOM RegisterClass (CONST WNDCLASS* lpWndClass) ;
    
    //向操作系统注册窗口
    RegisterClassEx(&wc) ) //传入窗口类结构体的地址
    //函数的返回值为布尔值,注册成功则返回真

    3.创建窗口

    注册完成之后,就可以创建窗口类实例了。首先需要定义一个句柄,作为一个标识,保存下来。

    HWND CreateWindow(
    
        LPCTSTR lpszClassName,    //窗口类名
    
        LPCTSTR lpszTitle,    //窗口标题名
    
        DWORD dwStyle,    //创建窗口的样式
    
        int x,y,    //窗口左上角坐标
    
        int nWidth,nHeight,    //窗口宽度和高度
    
        HWND hwndParent,//该窗口的父窗口句柄
    
        HWENU hMenu,    //窗口主菜单句柄
    
        HINSTANCE hInstance,    //创建窗口的应用程序当前句柄
    
        LPVOID lpParam    //指向一个传递给窗口的参数值的指针
    );
    
    //创建窗口
    
    HWND hwnd = 0; //句柄,用以保存新创建的窗口的标识
    
    hwnd = CreateWindow(
        " Class Name ", //注册的类名,设计窗口的时候指定的名字
        "窗口标题", 
        WS_OVERLAPPEDWINDOW,//层叠的窗口,具有标题栏和边框
        0, 0, width, height,
        0 /*parent hwnd*/, 
        0 /* menu */, 
        hInstance, 
        0 /*extra*/); 
    
    //第一个参数是注册的类名,一定要用注册之后的窗口类名
    
    //第二个参数是窗口的名字,即窗口标题名
    
    //第三个参数是窗口的类型
    
    //之后的四个参数表示窗口的左上角水平坐标、垂直坐标、宽度、高度
    
    //之后是一个窗口的句柄HWND,父窗口句柄,没有父窗口可设置为NULL
    
    //之后是菜单句柄
    
    //之后是当前应用程序实例的句柄,WinMain形参之一
    
    //之后是一个数据指针,多文档时用,主要作为WM_CREATE消息的附加参数

    4.显示及更新窗口

    //显示窗口
    ShowWindow(hwnd, SW_SHOW);//窗口句柄及显示状态
    
    //更新窗口,刷新一次窗口,可有可无
    UpdateWindow(hwnd);

    三.消息及消息循环

    1.消息

    操作系统将每个事件(输入设备上的变化)都包装成一个称为消息的结构体MSG来传递给应用程序,然后由应用程序来决定对此事件做出何种响应,应用程序通过调用函数的形式来通知操作系统执行相应的功能。应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows操作系统提供给应用程序编程的接口(Application Programming Interface),简称Windows API。

    消息结构体:

    typedef struct tagMSG
    { 
        HWND hwnd;     //接受消息的窗口的句柄;
                //句柄是资源的标识,窗口句柄的类型是HWND
        UINT message;     //消息标识符,表示具体的消息信息;
        WPARAM wParam; //32位的附加消息参数。根据消息的不同而不同。
        LPARAM lParam;     //32位的附加消息参数,其值与消息有关;
        DWORD time;     //双16位,即32位的整数,消息放入消息队列的时间
        POINT pt;     //消息放入消息队列时鼠标的坐标
    
    } MSG, *PMSG;

    UINT是一个无符号整数,因为数值一般不好记忆,所以微软定义了一些宏来帮助记忆,宏以WM作为开头(Window Message),如WM_LBUTTONDOWN,WM_CHAR等。

    当按下键盘之后,无论按下哪个键,收到的都是WM_CHAR消息,并不知道按下的是哪个字母,可以通过wParam获取到相对应的字母的ASCII码。

    2.消息循环

    消息队列是一个先进先出的缓冲区,操作系统为每一个应用程序都会建立一个消息队列,应用程序从消息队列中取出消息,进行相应的相应。

    消息循环的常见写法如下:

    MSG msg;
    
    while(GetMessage(&msg,NULL,0,0))
    
    {
        TranslateMessage (&msg);
    
        DispatchMessage (&msg);
    }

    GetMessage从消息队列中获取消息。检索到WM_QUIT消息时返回零值。

    GetMessage(
    
        lpMSG,//指向MSGMSG结构的指针
    
        hwnd, //窗口句柄
    
        nMsgFilteMin, //用于消息过滤的最小消息号值
    
        nMsgFilterMax//用于消息过滤的最大消息号值
    
    );

    TranslateMessage转换消息。比如将键盘的WM_KEYDOWN和WM_KEYUP消息转换成WM_CHAR消息,放在消息队列当中。

    DispatchMessage将收到的消息传到窗口的回调函数(窗口过程函数)中。

    3.窗口过程函数(回调函数)

    窗口过程函数用来处理和响应消息。

    LRESULT CALLBACK WindowProc(
        HWND hwnd,
        UINT uMsg,
        WPARAM wParam,
        LPARAM lParam
    );

    函数名可以更改,但是参数的类型不能变,参数名可以随便取。

    接收一个消息,DispatchMessage调用的时候,操作系统调用这个窗口过程函数,并且将相关的参数传递给这个函数。直到窗口过程函数将控制返回给Windows操作系统,DispatchMessage才能返回。

    函数内部一般用Switch case语句判断具体是什么消息,然后采取相应的措施。

    一个回调函数的例子如下:

    //
    // WndProc
    //
    //窗口过程函数,回调函数
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     //窗口句柄、消息标识、消息的附加参数
    {
        //LRESULT是个Long型,返回的结果码
    
        switch( msg )
        {
    
            case WM_DESTROY: 
        //在消息处理程序段中一般都有对//WM_DESTROY的处理,该消息是关闭窗口时发出的
                PostQuitMessage(0);
                break;
    
            case WM_KEYDOWN:
                if( wParam == VK_ESCAPE )
                DestroyWindow(hwnd);
                break;
            default:
            //提供缺省处理,让系统对不感兴趣的消息进行一些缺省处理 
                return DefWindowProc(hwnd, msg, wParam, lParam);
    
        //按键: WM_CHAR 
        //鼠标左键: WM_LBUTTONDOWN
        //窗口重绘: WM_PAINT
        //关闭: WM_CLOSE
        //DestroyWindow函数销毁窗口,并发送以下消息
        //WM_DESTROY 然后PostQuitMessage(0) 退出程序,发送WM_QUIT消息,消息循环返回值,结束消息循环,退出WinMain函数
        }
      return 0; 
    }
  • 相关阅读:
    线性表——(2)单向链表
    线性表——(1)顺序表
    UVa 1592 数据库
    UVa 12096 集合栈计算机
    Python 协程
    Python 多线程及进程
    Python 日志(Log)
    Python 函数式编程
    Python基础
    DB2 获取前两天的数据
  • 原文地址:https://www.cnblogs.com/mengdd/p/2630863.html
Copyright © 2011-2022 走看看