[SDK]-窗口创建

[SDK]-窗口创建


前言

各位师傅大家好,我是qmx_07,今天给大家讲解窗口创建的流程,以及console和windows的区别,下一章节会更新GDI绘制,将会持续更新

控制台编程与Windows程序在流程上的区别

  • console控制台:使用顺序的过程驱动设计方式,程序有明显的开始与结束
  • windows程序消息驱动,按照事件的发生来控制,并不清楚用户要怎样操作,比如 我点击了文件,编写,退出,各种类型的操作,我们要对这些操作进行排序和管理
  • 事件驱动程序设计是密切围绕消息的产生与处理而展开的

控制台和windows入口的区别

windows窗口的入口程序叫做 WinMain

int WINAPI WinMain(  
  HINSTANCE hInstance,  // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state
);

hinstance:表示 当前程序当前运行的实例句柄
hPrevInstance 这个一般设置为NULL,用来兼容16位程序,在win32环境下,没有作用
lpCmdLine:表示 传递给控制台的命令行参数,可以理解为类似 main()函数的[]argv
nCmdShow:表示 显示方式,最大化,最小化,隐藏

窗口的创建主要分为六步骤

设计窗口注册类

  • 设计窗口种类就是定义窗口属性的模板,这些属性包括窗口式样,鼠标形状,菜单等
  • 窗口种类也指定处理该类中所有窗口消息的窗口函数.只有先建立窗口种类,才能根据窗口种类来创建Windows应用程序的一个或多个窗口.创建窗口时,还可以指定窗口独有的附加特性
  • 窗口类具有唯一性,不能够重新注册

窗口类介绍

注册窗口类的参数:
在这里插入图片描述
代码实例:

    WNDCLASS wc = {};//创建类名为wc的窗口类
    wc.style = CS_VREDRAW | CS_HREDRAW;//这个组合,可以通过位运算增加风格或者减少风格
    wc.lpfnWndProc = WndProc;//窗口的过程函数
    wc.cbWndExtra = 0;
    wc.cbClsExtra = 0;
    wc.hInstance = hInstance;//句柄
    wc.hIcon = NULL;//图标
    wc.hCursor = NULL;//光标
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;//菜
    wc.lpszClassName = L"窗口";//窗口类名
Register和Messagebox

Messagebox:会弹出对话框窗口

int MessageBox(  HWND hWnd,			//
               LPCTSTR lpText,		//C风格字符串,以 0 结尾的字符串,文本
               LPCTSTR lpCaption,	//标题
               UINT uType); 		//方式

Register:如果注册失败,会返回0,利用Messagebox去响应失败内容
在这里插入图片描述

创建窗口

创建窗口类的参数:
在这里插入图片描述
代码实例:

  HWND hwnd = CreateWindow(
        L"窗口",//窗口类名
        L"标题",//窗口标题
        WS_OVERLAPPEDWINDOW,//重叠窗口、带标题、系统菜单
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,//x,y,宽,高
        NULL,//父窗口
        NULL,//菜单
        hInstance,//实例句柄
        NULL//消息参数
    );

注意:必选三种基础风格之一(WS_POPUP, WS_CHILD【子窗口】,WS_OVERLSPPED【重叠窗口】)必须有其中之一,并且不能互相混用,是互斥的。

显示窗口和更新窗口

API函数CreateWindow创建完窗口后,要想把它显示出现,还必须调用另一个API函数ShowWindows.

在这里插入图片描述
参数1:窗口句柄,告诉ShowWindow()显示哪一个窗口
参数2:最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),还是最大化 (SW_SHOWMAXIMIZED)。
WinMain在创建完窗口后就调用ShowWindow函数,并把iCmdShow参数传送给这个窗口

WinMain()调用完ShowWindow后,还需要调用函数UpdateWindow,最终把窗口显示了出来。调用函数UpdateWindow将产生一个WM_PAINT消息,这个消息将使窗口重画,即使窗口得到更新.且不通过消息循环。
在这里插入图片描述

## 创建消息循环 **Windows为每个正在运行的应用程序都保持一个消息队列**。当你按下鼠标或者键盘时,Windows并不是把这个输入事件直接送给应用程序,而是将输入的事件先翻译成一个消息,然后把这个消息放入到这个应用程序的消息队列中去。
BOOL GetMessage( 
  LPMSG lpMsg,         // message information
  HWND hWnd,           // handle to window
  UINT wMsgFilterMin,  // first message  UINT wMsgFilterMax   // last message);

操作系统将消息封装成MSG结构体投递到消息队列

消息循环

在这里插入图片描述
应用程序的WinMain函数通过执行一段代码从队列中来检索Windows消息。然后WinMain就把这些消息分配给相应的窗口函数以便处理它们,这段代码是一段循环代码,故称为”消息循环”。
在这里插入图片描述
拿到消息以后,在通过获取的消息对应处理调用窗口回调函数.

封装消息的结构体
typedef struct tagMSG {     // msg  
    HWND   hwnd;      //要发送的窗口句柄。如果是在一个有多个窗口的应用程序中,用这个参数就可决定让哪个窗口接收消息。
    UINT   message;	  //消息编号
    WPARAM wParam;	  //两个参数,不同的消息,一个32位的消息参数,这个值的确切意义取决于消息本身
    LPARAM lParam;	  //两个参数,不同的消息,一个32位的消息参数,这个值的确切意义取决于消息本身
    DWORD  time;	  //消息放入消息队列中的时间(消息发生时间),在这个域中写入的并不是日期,而是从Windows启动后所测量的时间值。Windows用这个域来使用消息保持正确的顺序。
    POINT  pt;		  //消息放入消息队列时的鼠标坐标.
} MSG;
建立消息循环

消息循环以GetMessage调用开始,它从消息队列中取出一个消息:

MSG msg; //定义消息名
while (GetMessage (&msg, NULL, 0, 0))
{
     TranslateMessage (&msg) ; //翻译消息
     DispatchMessage (&msg) ; //
}
return msg.wParam ;
BOOL GetMessage( 
    LPMSG lpMsg, 		//接收消息的MSG结构的地址
    HWND hWnd, 			//窗口句柄,NULL则表示要获取该应用程序创建的所有窗口的消息;
    UINT wMsgFilterMin, //指定消息范围。后面三个参数被设置为默认值
    UINT wMsgFilterMax  //指定消息范围。后面三个参数被设置为默认值
    ); 

后面三个参数被设置为默认值这就是说你打算接收发送到属于这个应用程序的任何一个窗口的所有消息。

返回值
● 在接收到除WM_QUIT之外的任何一个消息后,GetMessage()都返回TRUE。
● 如果GetMessage收到一个WM_QUIT消息,则返回FALSE
● 如收到其他消息,则返回TRUE。

窗口过程函数

LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter);

要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程,也就是调用WindowProc来处理消息
在WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了一个消息循环。

代码实例:

LRESULT CALLBACK WndProc
(
	HWND hwnd,      // handle to window
	UINT uMsg,      // message identifier
	WPARAM wParam,  // first message parameter
	LPARAM lParam   // second message parameter
)
{
	switch (uMsg)
	{
	case WM_DESTROY: //销毁窗口的消息
		PostQuitMessage(0);//退出消息循环
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

全部代码

#include <Windows.h>

void ShowError();
LRESULT CALLBACK WndProc
(
	HWND hwnd,      // handle to window
	UINT uMsg,      // message identifier
	WPARAM wParam,  // first message parameter
	LPARAM lParam   // second message parameter
)
{
	switch (uMsg)
	{
	case WM_DESTROY: //销毁窗口的消息
		PostQuitMessage(0);//退出消息循环
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(
	HINSTANCE hInstance,      // handle to current instance
	HINSTANCE hPrevInstance,  // handle to previous instance
	LPSTR lpCmdLine,          // command line
	int nCmdShow              // show state
)
{
	//设计注册窗口类函数

	WNDCLASS wc = { };
	wc.style = CS_VREDRAW | CS_HREDRAW;//默认,当尺寸修改时,通知函数
	wc.lpfnWndProc = WndProc;//窗口过程函数
	wc.cbClsExtra = 0;//默认给0
	wc.cbWndExtra = 0;//默认给0
	wc.hInstance = hInstance;//实例句柄
	wc.hIcon = NULL;//图标
	wc.hCursor = NULL;//光标
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//背景色
	wc.lpszMenuName = NULL;//菜单
	wc.lpszClassName = L"窗口";//窗口类名

	if (!RegisterClass(&wc))
	{
		MessageBox(NULL, L"注册窗口失败", L"提示", MB_OK);
	}
	/*if (!RegisterClass(&wc))
	{

		DWORD nRet = GetLastError();
		ShowError();

	}*/

	//2、创建窗口实例
	HWND hWnd = CreateWindow(L"窗口",  // 窗口类类名
		L"第一个窗口", // 窗口标题
		WS_OVERLAPPEDWINDOW,//重叠窗口、带标题、系统菜单  WS_VISIBLE显示窗口
		CW_USEDEFAULT,//默认位置
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,//父窗口
		NULL,//菜单
		hInstance,//实例句柄
		NULL //消息参数
	);
	if (hWnd == NULL)
	{
		return 0;
	}

	//显示窗口
	ShowWindow(hWnd, SW_SHOW);

	//更新窗口

	UpdateWindow(hWnd); //立即绘制

	//消息循环
	MSG msg = {};
	while (GetMessage(&msg, NULL, 0, 0))
	{
		DispatchMessage(&msg);
	}

	return 0;
}


结语

我们学习了窗口的处理流程,大家可以手敲感受一下

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您可以使用 pip 工具来安装阿里云的 IoT Python SDK,具体步骤如下: 1. 打开终端或命令行界面,输入以下命令安装 SDK: ``` pip install aliyun-python-sdk-iot ``` 2. 安装完成后,您可以在 Python 代码中导入 SDK: ```python from aliyunsdkcore.client import AcsClient from aliyunsdkiot.request.v20180120 import PubRequest ``` 3. 在代码中使用 SDK 提供的 API 进行操作。 注意,使用 SDK 前,您需要先在阿里云控制台中创建一个 IoT 实例,并获取访问密钥(AccessKey ID 和 AccessKey Secret)。在代码中,您需要使用这些信息来初始化 AcsClient 对象。 ### 回答2: aliyun-python-sdk-iot是阿里云物联网平台提供的官方Python SDK,用于开发和管理物联网设备。下面是安装aliyun-python-sdk-iot的步骤: 1. 首先,确保已经安装了Python环境。可以在命令行中输入python --version来检查是否已经安装。 2. 打开命令行窗口,输入以下命令安装aliyun-python-sdk-iot: ``` pip install aliyun-python-sdk-iot ``` 这个命令将会在Python环境中安装aliyun-python-sdk-iot。 3. 安装完成后,可以在Python代码中导入aliyun-python-sdk-iot模块,即可使用阿里云物联网平台提供的功能和接口。 ```python from aliyunsdkcore.client import AcsClient from aliyunsdkiot.request.v20180120 import PubRequest # 创建AcsClient对象 client = AcsClient('<your-access-key-id>', '<your-access-key-secret>', '<your-region-id>') # 创建PubRequest对象,并设置参数 request = PubRequest() request.set_ProductKey('<your-product-key>') request.set_MessageContent('Hello, world!') # 调用接口 response = client.do_action_with_exception(request) print(response) ``` 上述代码演示了如何使用aliyun-python-sdk-iot发送消息到物联网设备。根据自己的需求,可以参考阿里云物联网平台的文档,了解其他功能和接口的使用方法。 总之,通过以上步骤,可以成功安装并使用aliyun-python-sdk-iot进行物联网设备的开发和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值