2021-02-11SDK学习00
请注意,本文编写于 656 天前,最后修改于 204 天前,其中某些信息可能已经过时。

目录


六要素(六步骤):

  1. 设计注册窗口类
  2. 创建窗口实例
  3. 显示窗口 *
  4. 更新窗口 *
  5. 消息循环
  6. 实现窗口过程函数(窗口回调函数)

1. 设计注册窗口类

RegisterClass 用于注册一个窗口类

c
int WINAPI WinMain(
	HINSTANCE hInstance,      // handle to current instance
	HINSTANCE hPrevInstance,  // handle to previous instance
	LPSTR lpCmdLine,          // command line
	int nCmdShow              // show state
)
{
	//1.设计注册窗口类
	WNDCLASS wc;

	wc.style = CS_HREDRAW | CS_VREDRAW;				// 窗口风格
	wc.lpfnWndProc = MyWindowProc;				// 窗口过程函数(窗口回调函数)
	wc.cbClsExtra = 0;								// 在窗口类结构中额外扩展空间,不怎么用,填0即可
	wc.cbWndExtra = 0;								// 在窗口实例中额外扩展空间,不怎么用,填0即可
	wc.hInstance = hInstance;						// 应用程序实例句柄
	wc.hIcon = NULL;								// 窗口图标
	wc.hCursor = NULL;								// 窗口光标
	wc.hbrBackground = (HBRUSH)COLOR_HIGHLIGHT;		// 窗口背景
	wc.lpszMenuName = NULL;							// 窗口菜单名
	wc.lpszClassName = "MyWindowClass";				// 窗口类名


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

	return 0;
}

style

位运算在SDK中被广泛的使用

c
/*
 * Class styles    //按位存
 */
# define CS_VREDRAW          0x0001
# define CS_HREDRAW          0x0002
# define CS_DBLCLKS          0x0008
# define CS_OWNDC            0x0020
# define CS_CLASSDC          0x0040
# define CS_PARENTDC         0x0080
# define CS_NOCLOSE          0x0200
# define CS_SAVEBITS         0x0800
# define CS_BYTEALIGNCLIENT  0x1000
# define CS_BYTEALIGNWINDOW  0x2000
# define CS_GLOBALCLASS      0x4000



UINT nStyle = CS_HREDRAW | CS_VREDRAW;

if(nStyle & CS_VREDRAW)    //检测是否含有风格CS_VREDRAW
{
    //含有风格CS_VREDRAW
    MessageBox(NULL,"含有风格CS_VREDRAW","提示",MB_OK);
}

/*
# define CS_VREDRAW          0x0001     0001
# define CS_HREDRAW          0x0002     0010
nStyle 是 0011

取消CS_VREDRAW
取反 ~0001 = 1110
0011 & 1110 => 0010
*/

nStyle & = ~CS_VREDRAW;    //取消风格CS_VREDRAW

查看错误

c
	//注册窗口
	if (!RegisterClass(&wc))
	{
		DWORD dwErr = GetLastError();    //获取错误码
		//ShowErr();
		return 0;
	}

获取错误码后需要点击 工具 ==> 错误查找
错误查找
但很显然,在调试过程中这样查看错误非常麻烦的所以

监视窗口:

c
@err,hr
//如在低版本不能使用@err,也可以使用
*(unsigned int*)(tib+0x34),hr
dwErr,hr
错误码,hr

错误信息

ShowErr

FormatMessageGetLastError函数得到的错误信息(这个错误信息是数字代号)转化成字符串信息的函数。

c
void ShowErr()
{
	LPVOID lpMsgBuf;
	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		GetLastError(),
		0, // Default language
		(LPTSTR)&lpMsgBuf,
		0,
		NULL
	);
	// Process any inserts in lpMsgBuf.
	// ...
	// Display the string.
	MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
	// Free the buffer.
	LocalFree(lpMsgBuf);
}

ShowErr

2. 创建窗口实例

CreateWindow 用于创建窗口

c
//1. 设计注册窗口类
//...

//2. 创建窗口
	HWND hWnd = CreateWindow(
		"MyWindowClass",		//窗口类的类名
		"窗口标题",				//窗口的标题
		WS_OVERLAPPEDWINDOW,	//窗口风格
		400,					//X
		400,					//Y
		800,					//宽
		400,					//高
		NULL,					//没有父窗口
		NULL,					//没有菜单
		hInstance,				//实例句柄
		NULL					//窗口创建数据,CREATESTRUCT结构体
	);
	if (hWnd == NULL)
	{
		ShowErr();
		return 0;
	}

窗口风格

三种基础风格
三种风格互斥,只能选择其中一个,除了这三个风格其余风格都可以混用

  • WS_OVERLAPPED,重叠窗口,通常使用
  • WS_POPUP,弹出窗口
  • WS_CHILD,子窗口

3. 显示窗口

ShowWindow 用于显示窗口
两个参数,窗口句柄和标志

c
	{
    // 1. 设计注册窗口类...
    // 2. 创建窗口...
    // ...
    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    }

4. 更新窗口

UpdateWindow 用于更新窗口
一个参数,窗口句柄

c
    {
        // 1. 设计注册窗口类...
        // 2. 创建窗口...
        // 3. 显示窗口
        // ...
        // 4. 更新窗口
        UpdateWindow(hwnd);
        // ...
    }

5. 消息循环

MSG 结构

c
typedef struct tagMSG {
HWND hwnd;         // 窗口句柄
UINT message;      // 消息编号
WPARAM wParam;     // 参数
LPARAM lParam;     // 参数
DWORD time;        // 时间
POINT pt;          // 鼠标位置
} MSG, *PMSG;

GetMessage 从消息队列中取得消息

c
BOOL GetMessage(
    LPMSG lpMsg,        //消息
    HWND hWnd,          //窗口句柄,可以填某个窗口的句柄,或者直接填NULL获取所有窗口

    //最低值和最高值,划定一个范围,如最低值是3,最高值是B,那么GetMessage只会拿3 - B之间的消息
    //如果全部设置为0,那就是拿所有消息
    UINT wMsgFilterMin, //最低值
    UINT wMsgFilterMax  //最高值
    );

使用

c
{
    // 1. 设计注册窗口类...
    // 2. 创建窗口...
    // 3. 显示窗口...
    // 4. 更新窗口...
    // ...
    // 5. 消息循环
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg); // 翻译消息
        DispatchMessage(&msg); // 投递消息,根据窗口句柄调用对应的窗口过程函数
    }
}

6. 窗口过程函数

c
LRESULT CALLBACK MyWindowProc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{

	switch (uMsg)
	{
	case WM_CLOSE:
	{
		DestroyWindow(hwnd);	//销毁窗口
		PostQuitMessage(0);		//退出消息循环
		return 0;
	}
	default:
		break;
	}

	return DefWindowProc(hwnd,uMsg,wParam,lParam);
	//DefWindowProc函数是默认的窗口处理函数,我们可以把不关心的消息都丢给它来处理
}

鼠标输入消息

c
WM_APPCOMMAND
WM_CAPTURECHANGED
WM_LBUTTONDBLCLK
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_MBUTTONDBLCLK
WM_MBUTTONDOWN
WM_MBUTTONUP
WM_MOUSEACTIVATE
WM_MOUSEHOVER
WM_MOUSELEAVE
WM_MOUSEMOVE
WM_MOUSEWHEEL
WM_NCHITTEST
WM_NCLBUTTONDBLCLK
WM_NCLBUTTONDOWN
WM_NCLBUTTONUP
WM_NCMBUTTONDBLCLK
WM_NCMBUTTONDOWN
WM_NCMBUTTONUP
WM_NCMOUSEHOVER
WM_NCMOUSELEAVE
WM_NCMOUSEMOVE
WM_NCRBUTTONDBLCLK
WM_NCRBUTTONDOWN
WM_NCRBUTTONUP
WM_NCXBUTTONDBLCLK
WM_NCXBUTTONDOWN
WM_NCXBUTTONUP
WM_RBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_XBUTTONDBLCLK
WM_XBUTTONDOWN
WM_XBUTTONUP

使用

c
LRESULT CALLBACK MyWindowProc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	switch (uMsg)
	{
	case WM_CLOSE:
	{

		DestroyWindow(hwnd);	//销毁窗口
		PostQuitMessage(0);		//退出消息循环

		return 0;
	}
	case WM_LBUTTONDOWN:		//鼠标左键按下
	{
		WORD wX = LOWORD(lParam);
		WORD wY = HIWORD(lParam);
		char szBuf[MAXBYTE] = { 0 };
		wsprintf(szBuf,"X: %d Y: %d", wX, wY);
		MessageBox(NULL, szBuf, "提示", MB_OK);
		return 0;
	}
	default:
		break;
	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!