首页 > 系统相关 >D3D所用Windows应用程序流程

D3D所用Windows应用程序流程

时间:2022-09-27 23:35:51浏览次数:57  
标签:窗口 Windows 句柄 应用程序 int 程序流程 msg D3D 消息

概述

  • 本篇说讲的是window窗口程序——由主窗口、菜单、工具栏、滚动条、按钮等控件组成,而D3D游戏编程并不需要过于复杂的GUI(graphics user interface),仅仅需要一个主窗口用以渲染

基础

  • windows中,多个应用程序可以并发运行,因此硬件资源都在多应用程序的共享范围。然而为了防止一些无组织的访问或修改资源,windows应用程序无法直接访问硬件资源

  • windows应用程序依靠事件(如按键、点击鼠标等)不断运行,当事件发生后,操作系统向发生事件的应用程序发送相应消息,消息便进入此应用程序的消息队列,而应用程序会于消息循环中不断检测队列中的消息,接受到消息时则将消息分派到相应窗口的窗口过程函数,而窗口过程函数则写有处理特定消息的代码

    • 不一定非要给每个窗口都写一个独立的窗口过程。每个窗口都有与之相关联的窗口过程函数,但窗口间可以共享相同的窗口过程函数
    • 目标窗口不处理的消息转发至Win32API提供的默认窗口过程DefWindowProc
  • windows程序中含有各种各样的资源(如窗口、光标),系统创建这些资源时会为它们分配内存并返回标识这些资源的标识号,而标识号则为句柄

  • 编码约定:Windows API由函数或COM接口组成,很少由c++类提供

    • 整数类型:

      数据类型 大小 有无符号
      BYTE 8bit
      DWORD 32bit
      INT32 32bit
      INT64 64bit
      LONG 32bit
      LONGLONG 64bit
      UINT32 32bit
      UINT64 64bit
      ULONG 32bit
      ULONGLONG 64bit
      WORD 16bit
    • BOOL:为int类型别名,不可与bool互换

      #define FALSE    0 
      #define TRUE     1
      
    • 指针类型:16 位Windows有 2 种类型的指针,P 表示“指针”,LP 表示“长指针”。 长指针 (也称为 远指针 ,) 用于处理当前段之外的内存范围。 保留 LP 前缀,以便更轻松地将 16 位代码移植到 32 位Windows。 今天没有区别,这些指针类型都是等效的。 如果必须使用一个指针类型,请使用 P

      • 精度类型:以下数据类型始终是指针的大小,即 32 位应用程序中宽 32 位,64 位应用程序宽 64 位。 大小在编译时确定。 当 32 位应用程序在 64 位Windows上运行时,这些数据类型仍宽 4 字节。 (64 位应用程序无法在 32 位Windows上运行,因此不会发生反向情况。)
        • DWORD_PTR
        • INT_PTR
        • LONG_PTR
        • ULONG_PTR
        • UINT_PTR
  • Unicode:支持所有字符集和语言,windows使用UTF-16编码表示Unicode字符,其中每个字符编码为一个或两个16位值。UTF-16字符为宽字符

    • c++以wchar_t宽字符表示Unicode,且无论64位或32位windows操作系统,wchar_t都为16位
    • 使用宽字符时,必须为字符串字面值冠以前缀L。因为这样会将其当作宽字符串处理
    • 处理宽字符时需使用相应版本的字符串函数
      • 获取宽字符串长度:wcslen()
      • 复制宽字符串:wcscpy()
      • 比较两个宽字符串:wcscmp()
    • 宽字符串类std::wstring
    Typedef 定义
    CHAR char
    PSTR or LPSTR char*
    PCSTR or LPCSTR const char*
    PWSTR or LPWSTR wchar_t*
    PCWSTR or LPCWSTR const wchar_t*
    • ANSI 版本效率较低,因为操作系统必须在运行时将 ANSI 字符串转换为 Unicode

windows应用程序

  • 流程:

    • 注册、创建窗口结构体
    • 初始化程序主窗口并展示更新
    • 开始消息循环,窗口过程对消息进行处理
  • //头文件
    //含有编写Windows应用程序所需的所有Win32 API结构体、数据类型、函数声明
    #include<windows.h>
    
    //指定所创建主窗口的句柄
    //不少API需要指定特定窗口句柄进行处理
    HWND g_hMainWnd = 0;
    
    //创建并初始化Winodws应用程序主窗口。初始化成功返回true,失败false
    bool initMainWindow(HINSTANCE instanceHandle, int show);
    
    //消息循环
    int run()
        
    //主窗口的窗口过程
    LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
    //应用程序入口点,相当于main()
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
    {
        //用hInstance、nShowCmd作为参数调用initMainWindow
        if(!initMainWindow(hInstance, nShowCmd))
        {
            return 0;
        }
        
        //初始化完后,即可开始消息循环
        return run();
    }
    
    
    bool initMainWindow(HINSTANCE instanceHandle, int show)
    {
        //填写WNDCLASS结构体
        WNDCLASS wc;
        
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = instanceHandle;
        wc.hIcon = LoadIcon(0, IDI_APPLICATION);
        wc.hCursor = LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName = 0;
        wc.lpszClassName = L"BasicWndClass";
        
        //注册WNDCLASS实例
        if(!RegisterClass(&wc))
        {
            MessageBox(0, L"RegisterClass FAILED", 0, 0);
            return false;
        }
        
        //CreateWindow函数返回创建的窗口的句柄(HWND),若创建失败返回0
        g_hMainWnd = CreateWindow(
        	L"BasicWndClass",	//采用的前面注册的WNDCLASS
            L"Win32Basic",		//窗口标题
            WS_OVERLAPPEDWINDOW,	//窗口的样式标志
            CW_USEDEFAULT,		//x坐标
            CW_USEDEFAULT,		//y坐标
            CW_USEDEFAULT,		//窗口宽度
            CW_USEDEFAULT,		//窗口高度
            0,		//父窗口
            0,		//菜单句柄
            instanceHandle,		//应用程序实例句柄
            0		//其他参数
        );
        
        if(g_hMainWnd == 0)
        {
            MessageBox(0, L"CreateWindow FALIED", 0, 0);
            return false;
        }
        
        //展示窗口并更新
        ShowWindow(g_hMainWnd, show);	//show为显示模式
        Update(g_hMainWnd);
        
        return true;
    }
    
    int run()
    {
        MSG msg = {0};
        
        while(msg.message != WM_QUIT)
        {
            if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {
                //动画或游戏逻辑
            }
        }
        
        return (int)msg.wParam;
    }
    
    LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_LBUTTONDOWN:	//按下鼠标左键
                MessageBox(0, L"Hello, World", L"Hello", MB_OK);
                return 0;
            case WM_KEYDOWN:		//非键盘键被按下
                if(wParam == VK_ESCAPE)
                {
                    DestoryWindow(g_hMainWnd);
            	   return 0;
                }
            case WM_DESTORY:		//窗口被销毁
                PostQuitMessage(0);
                return 0;
        }
        
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
  • WinMain函数:

    • HINSTANCE hInstance:当前应用程序实例句柄
    • HINSTANCE hPrevInstance:在 16 位Windows中使用,但现在始终为零
    • PWSTR pCmdLine:运行此程序所用的命令行参数字符串
    • int nCmdShow:标志。指定应用程序如何显示
    //函数调用约定
    #define WINAPI _stdcall
    
  • WNDCLASS结构体

    typedef struct _WNDCLASS {
      UINT      style;		//窗口类样式。CS_HREDRAW | CS_VREDRAW表示宽或高改变时重绘窗口
      WNDPROC   lpfnWndProc;	//指向与此WNDCLASS实例相关联的窗口过程函数的指针
      int       cbClsExtra;		//要按照窗口类结构分配的额外字节数。 系统将字节初始化为零
      int       cbWndExtra;		//在窗口实例之后分配的额外字节数。 系统将字节初始化为零
      HINSTANCE hInstance;		//当前应用程序实例的句柄
      HICON     hIcon;		    //类图标的句柄。 图标资源的句柄。 如果为 NULL,则系统提供默认图标
      HCURSOR   hCursor;		//类游标的句柄。 游标资源的句柄。 如果为 NULL,则每当鼠标移动到应用程序的窗口中时,应用程序都必须显式设置光标形状
      HBRUSH    hbrBackground;	//类背景画笔的句柄,指定窗口工作区的背景颜色
      LPCSTR    lpszMenuName;	//窗口菜单
      LPCSTR    lpszClassName;	//所创窗口类结构体的名字
    } WNDCLASS;
    
  • 创建并显示窗口

    HWND CreateWindow(
      [in, optional] LPCTSTR  lpClassName,		//前面已注册的WNDCLASS
      [in, optional] LPCTSTR lpWindowName,		//窗口名称
      [in] DWORD           dwStyle,		//窗口样式
      [in] int           x,		//x坐标
      [in] int           y,		
      [in] int           nWidth,	//宽度
      [in] int           nHeight,	//高度
      [in, optional] HWND hWndParent,	//父窗口句柄
      [in, optional] HMENU hMenu,		//菜单句柄
      [in, optional] HANDLE hInstance,		//相关的应用程序句柄
      [in, optional] LPVOID lpParam		//指向用户定义数据
    );
    
  • 消息循环

    • 首先为Windows消息的MSG类型创建msg实例

      typedef struct tagMSG {
        HWND   hwnd;		//接受消息的窗口过程所属的窗口句柄
        UINT   message;	//识别消息的预定义常量值(如WM_QUIT)
        WPARAM wParam;	//通常用来存储小段信息,如标志
        LPARAM lParam;	//通常用于存储消息所需的对象
        DWORD  time;		//消息被发出时间
        POINT  pt;		//消息发出时,鼠标指针坐标
      } MSG, *PMSG, *NPMSG, *LPMSG;
      
    • PeekMessage

      BOOL PeekMessage(
        [out]          LPMSG lpMsg,	//指向收到的MSG消息
        [in, optional] HWND  hWnd,	//要检索消息的窗口的句柄
        [in]           UINT  wMsgFilterMin,	//要检索的消息范围内的第一条消息的值
        [in]           UINT  wMsgFilterMax,	//要检查的消息范围内最后一条消息的值
        [in]           UINT  wRemoveMsg		//指定如何处理消息
      );
      
      • TranslateMessage():键盘按键的转换
      • DispatchMessage():将消息分派给相应的窗口过程
  • 窗口过程

    • LRESULT Wndproc(
        HWND hWnd,	//接收此消息的窗口的句柄
        UINT msg,		//标识特定消息的预定值
        WPARAM wParam,	
        LPARAM lParam
      );
      
  • 消息框函数

    int MessageBox(
      [in, optional] HWND    hWnd,		//消息框所属窗口的句柄
      [in, optional] LPCTSTR lpText,	//消息框显示的文本
      [in, optional] LPCTSTR lpCaption,		//消息框的标题文本
      [in]           UINT    uType		//消息框样式
    );
    

标签:窗口,Windows,句柄,应用程序,int,程序流程,msg,D3D,消息
From: https://www.cnblogs.com/chenglixue/p/16736414.html

相关文章

  • VS2010创建windows服务其实很简单 ProjectInstaller.cs Timer
    VS2010创建windows服务其实很简单ProjectInstaller.cs【IT168技术】很多人会对使用VisualStudio有不少的烦恼,下面我们来看一下作者是如何创建windows服务的,看后你......
  • 第02章 Windows11的基本使用
    第02章Windows11的基本使用第01阶段Java语言核心技术1.Windows11的介绍Windows11是由微软公司(Microsoft)开发的操作系统,应用于计算机和平板电脑等设备。也是全世界......
  • 1. Windows机器安装配置freeSSHd服务
    1.      Windows机器安装配置freeSSHd服务第一步,官网下载http://www.freesshd.com/?ctt=download,选择freeSSHd.exe。 第二步,选择以管理员身份运行,使用administr......
  • [备忘]端口占用的解决方法(Windows,CentOS,Redhat)
    Windows查看被占用端口对应的PID(比如8080)netstat-aon|findstr8080查看是哪个进程占用的,然后决定要不要释放tasklist|findstr8080释放端口taskkill-pid......
  • windows下mysql的数据主主同步
    mysql主主备份:保证各服务器上的数据库中的数据一致,因此需要开启数据库同步机制。由于是一整套系统,并且系统内含数据库。由于任何一台服务器都有可能被选中,因此要让所有的......
  • Linux、Windows下Redis的安装即Redis的基本使用详解
    前言什么是RedisRedis是一个基于内存的key-value结构数据库。Redis是互联网技术领域使用最为广泛的存储中间件,它是「RemoteDictionaryService」的首字母缩写,也就......
  • 「国产系统」Tubian 0.3,兼容Windows和Android的GNU/Linux系统!
    Tubian是我的自用系统整理而成的Linux发行版,基于Debian,对Windows和Android应用提供了较为完善的兼容。可以直装QQTIM微信MSOFFICE等大量Windows应用,并且几乎实现对Android......
  • 【Azure 应用服务】App Service频繁出现 Microsoft.WindowsAzure.Diagnostics.Diagnos
    问题描述在使用AppService的过程中,发现应用频繁出现503错误,通过Kudu站点获取到Logfiles。在Eventlog.xml文件中,发现大量的Microsoft.WindowsAzure.Diagnostics.Diag......
  • windows安装ngxin
    1.去nginx官网下载http://nginx.org/en/download.html下载后解压到本地2.安装部署1、下载完成后,解压缩,运行cmd,使用命令进行操作,不要直接双击nginx.exe,一定要在dos窗......
  • Java 狂神 Day01 Windows快捷键
    Windows快捷键ctrl+E:打开我的电脑ctrl+shift+esc:打开任务管理器alt+F4:关闭窗口alt+tab:切换窗口shift+del:永久删除win+D:返回桌面 ......