Win32窗口创建

Win32窗口创建

一、前言

Win32窗口程序基础教程,前期项目设置:

右键打开项目属性:

image-20211003120811205

按图配置:

image-20211003120845033

image-20211003120933746

这里Debug和Release模式要分开设置;

image-20211003121015404

image-20211003121034016

因为我的项目不需要太高的精度;

image-20211003121105663

image-20211003121136069

image-20211003121247536

二、WinMain

WinMain是windows的关键字,类似控制台程序的mian函数,都窗口程序的入口;

HINSTANCE hInstance			//应用程序当前实例的句柄
HINSTANCE hPrevInstance			//应用程序的先前实例的句柄,总是null
LPSTR	  lpCmdLine			//参数,只能是string
int		  nCmdShow		//窗口样式

创建窗口关键api(这里使用Ex版本):

WNDCLASSEX wc;				//windows类,包含所有窗口的信息

RegisterClassEx(&w);			//注册窗口
    
HWND hWnd = CreateWindowExA(		//创建窗口
  DWORD     dwExStyle,			//窗口样式 0
  LPCSTR    lpClassName,		//窗口类名
  LPCSTR    lpWindowName,		//窗口名称title
  DWORD     dwStyle,			//窗口样式
  int       X,				//在屏幕坐标
  int       Y,
  int       nWidth,			//窗口宽高
  int       nHeight,
  HWND      hWndParent,			//父窗口句柄	nullptr
  HMENU     hMenu,			//子窗口标识符,唯一	nullptr
  HINSTANCE hInstance,			//WinMain的参数 hInstance
  LPVOID    lpParam			//(重要)指向要通过WM_CREATE消息的lParam参数指向的CREATESTRUCT结								   
                                        //构(lpCreateParams成员)传递给窗口的值的指针;不需要可为nullptr
);
    
ShowWindow(
 HWND hWnd,				//窗口句柄
 int  nCmdShow				//显示方式 SW_SHOW
);
GetMessage(
  LPMSG lpMsg,				//OUT 接受参数的指针 MSG msg 指针&msg
  HWND  hWnd,				//窗口句柄
  UINT  wMsgFilterMin,			//过滤消息
  UINT  wMsgFilterMax
);

TranslateMessage(			//将虚拟键消息转换为字符消息,下次GetMessage可读取
const MSG *lpMsg			//MSG msg 指针&msg
);				

DispatchMessage(			//向窗口过程发送消息
const MSG *lpMsg
);

WinMain的完整代码:

int __stdcall WinMain(
	HINSTANCE hInstance, 
	HINSTANCE hPrevInstance, 
	LPSTR	  lpCmdLine,		//只接受string
	int		  nCmdShow)			
{
        //创建窗口结构体
	const auto pClassName = "littlePerilla";
	WNDCLASSEX wc = { 0 };
	wc.cbSize = sizeof(wc);
	wc.style = CS_OWNDC;
	wc.lpfnWndProc = WindowProc;	//重要,函数指针,下面的WindowProc函数
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = nullptr;
	wc.hCursor = nullptr;
	wc.hbrBackground = nullptr;
	wc.lpszMenuName = nullptr;
	wc.lpszClassName = pClassName;
	wc.hIconSm = nullptr;

	//注册窗口
        RegisterClassEx(&wc);

        //创建窗口
        HWND hWnd = CreateWindowExA(
		0, pClassName,
		"Happy National Day",
		WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
		200, 200, 800, 600,
		nullptr, nullptr, hInstance, nullptr
	);

	//显示窗口
	ShowWindow(hWnd, SW_SHOW);
    
	MSG msg;
	BOOL gResult;
        //获取消息
	while ((gResult = GetMessage(&msg, nullptr, 0, 0)) > 0)
	{
          //翻译按键字符串
	  TranslateMessage(&msg);
	  //传递消息
          DispatchMessage(&msg);
	}

	if (gResult == -1)
		return -1;

	return msg.wParam;	
}

三、Windows消息机制

WindowProc之前,先了解Windows的消息机制;

  1. 系统中发生了某个事件。

  2. Windows把这个事件翻译为消息,然后把它放到消息队列中。

  3. 应用程序从消息队列中接收到这个消息,把它存放在Msg记录中。

  4. 应用程序把消息传递给一个适当的窗口的窗口过程。

  5. 窗口过程响应这个消息并进行处理。

image-20211003141729354

四、WindowProc

只是个函数名,不固定,可以更改,只要赋值给窗口结构体的lpfnWndProc即可;

msg: 代表系统消息事件的种类,多达上千种?

每种不同的msg,对应的wParam和lParam参数的作用不一样,可查看MSDN了解具体作用;

在WndProc中拦截不同的消息做相应的处理;

LRESULT __stdcall WindowProc(
	HWND hWnd,		//产生消息的窗口
	UINT msg,		//消息类型
	WPARAM wParam,	        //消息附加参数 1
	LPARAM lParam)	        //消息附加参数 2
{
	switch (uMsg)
	{
	case WM_CLOSE:				                                //关闭消息
		PostQuitMessage(69);
		break;
	case WM_KEYDOWN:							//键盘按下
		if (wParam == 'F')
		{
			SetWindowText(hWnd, "RESPECT");
		}
		break; 
	case WM_KEYUP:								//键盘抬起
		if (wParam == 'F')
		{
			SetWindowText(hWnd, "FUCKYOU");
		}
		break;
	case WM_CHAR:								//获取输入
		{
			static std::string title;
			title.push_back((char)wParam);
			SetWindowText(hWnd, title.c_str());
		}
		break;
	case WM_LBUTTONDOWN:						        //鼠标左键按下
		{
			POINTS pt = MAKEPOINTS(lParam);
			std::ostringstream oss;
			oss << "(" << pt.x << "," << pt.y << ")";
			SetWindowText(hWnd, oss.str().c_str());
		}
		break;
	case WM_DESTROY:							//销毁程序
		PostQuitMessage(96);
		break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
posted @ 2021-10-03 14:24  小紫苏  阅读(311)  评论(0编辑  收藏  举报