持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
目的
为什么在写神经网络前我们要创建一个窗口,答案是用 c++ 写神经网络神经网络的可视化实现
创建一个 Windows 桌面应用程序
创建主程序
创建一个 Main.cpp 文件
引入头文件
#include <Windows.h>
首先我们把入口函数保存过来,入口函数和之前 c++ 语言和 c 语言入口函数有所不同,这里并不是 main 函数,而是 mWinMain 注意在 c++ 中是区分大小写的,这就是入口文件,主函数需要只用这个名称,保证应用程序可以将你应用正确调用
#include <Windows.h>
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
return 1;
}
- HINSTANCE 类型
- LPWSTR 类型
我们创建文件在IDE 默认生成文件看多大量没有见过数据类型,其实这些大家不用担心这些都是一些基本类型别名,使用
typedef对一些基本类型定义别名, 例如typedef int INT,这样做好处是使用 deftype 起别名可以用于简化类型,赋予类型的可解释性,这些还都是表面,便于以后系统即使更改某一个类型不会导致你 code 出现 bug
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,//当前,每一个进程代表一个实例
_In_opt_ HINSTANCE hPrevInstance,//前一个应用程序实例句柄
_In_ wchar_t* lpCmdLine,//命令行参数,默认时候没有传入命令行参数
_In_ int nCmdShow)
{
MessageBox(NULL,L"hello world win32",L"anet ",MB_OK);
return 0;
}
这里创建了 MessageBox 用于,一个系统提供的弹框窗口,不需要注册,因为系统将 MessageBox 注册好了,其他这样窗口类还有 BUTTON 和 EDIT
- NULL 是父窗口句柄
typedef HINSTANCE HMODULE
接下来要做的事
- 注册窗口类
- 创建窗口
- 显示窗口
- 更新窗口
- 消息循环
注册窗口
什么是窗口类
- 窗口类包含了窗口的各种参数信息的数据结构
- 每个窗口都具有窗口类,窗口类可以看做创建窗口的模板
- 每个窗口类都具有一个名字,在创建和使用窗口类前必须将其注册到系统
窗口类的分类
- 系统窗口类
- 应用程序全局窗口类(所有模块化可视)
- 应用程序局部窗口类(
定义窗口类的过程就是窗口注册过程
定义窗口结构体
typedef struct
{
HWND windowHandle; // 窗口句柄
BOOL Running;//状态
} typeWindow;
定义创建窗口的方法
long typeWindowCreate(typeWindow* parent, HINSTANCE hInstance, WNDPROC windowProc);
long typeWindowCreate(typeWindow* parent, HINSTANCE hInstance, WNDPROC windowProc)
{
// EX 表示扩展的意思
WNDCLASSEXW wcex;
if (parent == 0)
return 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;//窗口特征,并不是窗口外观特征,水平重画和垂直重绘制
wcex.lpfnWndProc = windowProc;//设置用哪个 WindowProc 来处处理消息
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;//当前应用实例句柄
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;//菜单 ID
wcex.lpszClassName = windowClass;//向系统注册的类名
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
//注册
if (!RegisterClassExW(&wcex))
{
return 0;
}
HWND hwnd = CreateWindowW(
windowClass,//类名称,和刚刚注册一致
windowTitle,//标题名称
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //窗口外观样式
CW_USEDEFAULT,//窗口相对于父级的 x 坐标
CW_USEDEFAULT,//窗口相对于父级的 y 坐标
CW_USEDEFAULT,//窗口宽度
CW_USEDEFAULT, //窗口高度
NULL, //父窗口
NULL, //菜单
hInstance, //应用程序实例
NULL);//附加数据
if (!hwnd)
{
return 0;
}
parent->windowHandle = hwnd;
parent->Running = 1;
return 1;
}
long typeWindowGetEvent(typeWindow* parent)
{
//消息内容
MSG msg;
if (parent == 0)
return 0;
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return parent->Running;
}
销毁窗口
long typeWindowDestroy(typeWindow* parent)
{
if (parent == 0)
return 0;
DestroyWindow(parent->windowHandle);
parent->windowHandle = 0;
parent->Running = 0;
return 1;
}
完整代码
#ifndef TYPEWINDOW_H
#define TYPEWINDOW_H
#include <windows.h>
// 定义一个数据结构
typedef struct
{
HWND windowHandle; // 窗口句柄
BOOL Running;//状态
} typeWindow;
// 创建窗口
long typeWindowCreate(typeWindow* parent, HINSTANCE hInstance, WNDPROC windowProc);
//从消息队列获取消息
long typeWindowGetEvent(typeWindow* parent);
long typeWindowPeekEvent(typeWindow* parent);
//销毁窗口
long typeWindowDestroy(typeWindow* parent);
//
const WCHAR windowClass[] = L"windowClass";
const WCHAR windowTitle[] = L"windowTitle";
// 创建和显示主程序窗口
long typeWindowCreate(typeWindow* parent, HINSTANCE hInstance, WNDPROC windowProc)
{
// EX 表示扩展的意思
WNDCLASSEXW wcex;
if (parent == 0)
return 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;//窗口特征,并不是窗口外观特征,水平重画和垂直重绘制
wcex.lpfnWndProc = windowProc;//设置用哪个 WindowProc 来处处理消息
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;//当前应用实例句柄
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;//菜单 ID
wcex.lpszClassName = windowClass;//向系统注册的类名
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
//注册
if (!RegisterClassExW(&wcex))
{
return 0;
}
HWND hwnd = CreateWindowW(
windowClass,//类名称,和刚刚注册一致
windowTitle,//标题名称
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //窗口外观样式
CW_USEDEFAULT,//窗口相对于父级的 x 坐标
CW_USEDEFAULT,//窗口相对于父级的 y 坐标
CW_USEDEFAULT,//窗口宽度
CW_USEDEFAULT, //窗口高度
NULL, //父窗口
NULL, //菜单
hInstance, //应用程序实例
NULL);//附加数据
if (!hwnd)
{
return 0;
}
parent->windowHandle = hwnd;
parent->Running = 1;
return 1;
}
/**
消息循环 消息队列
*/
long typeWindowGetEvent(typeWindow* parent)
{
MSG msg;
if (parent == 0)
return 0;
//获取消息,直到条件不成立,循环跳出
if (GetMessage(&msg, NULL, 0, 0))
{
//用于将转换按键信息
TranslateMessage(&msg);
//将消息分发给 WindowProc 来处理
DispatchMessage(&msg);
}
return parent->Running;
}
long typeWindowPeekEvent(typeWindow* parent)
{
MSG msg;
if (parent == 0)
return 0;
if (PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return parent->Running;
}
long typeWindowDestroy(typeWindow* parent)
{
if (parent == 0)
return 0;
DestroyWindow(parent->windowHandle);
parent->windowHandle = 0;
parent->Running = 0;
return 1;
}
#endif // !TYPEWINDOW_H
主函数实现部分
LRESULT CALLBACK windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// 声明窗口
typeWindow window;
typeBitmap bitmap;
// 应用程序运行入口函数
// APIENTRY 是 _stdcall , 函数调用的协议,_stdcall 调用约定用于 Win32 API 函数,
// wWinMain 是由系统调用的
int APIENTRY wWinMain(
_In_ HINSTANCE hInstance, // 应用程序实列的句柄
_In_opt_ HINSTANCE hPrevInstance,//前一个实例
_In_ LPWSTR lpCmdLine,//命令行参数 LP 表示指针
_In_ int nCmdShow) //主窗口显示方式
{
//创建窗口
typeWindowCreate(&window, hInstance, windowProc);
//创建 bitmap
typeBitmapCreate(&bitmap, 100, 100);
while (typeWindowGetEvent(&window)) {
//
}
//退出销毁 bitmap
typeBitmapDestroy(&bitmap);
//返回值 0 表示应用程序正常退出
return 1;
}
// wParam 和 lParam 通常消息出参数,其中
LRESULT CALLBACK windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// 绘制 bitmap
case WM_PAINT:
{
// PAINSTRUCT 结构体包括用于在客户端绘制的信息
PAINTSTRUCT ps;
//
HDC hdc = BeginPaint(hWnd, &ps);
typeBitmapShow(&bitmap, &window, 10, 10);
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
typeWindowDestroy(&window);
return 0;
}
// 不做任何处理,又把控制权交给操作系统默认处理
return DefWindowProc(hWnd, message, wParam, lParam);
}