欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Windows编程基础知识点

程序员文章站 2024-03-26 12:54:41
...

什么是窗口(window)?

对于从编程的角度解析,不要简单地认为是一个程序的窗口,而是如下面定义:

think of a window as a programming construct that:

  • Occupies a certain portion of the screen.
  • May or may not be visible at a given moment.
  • Knows how to draw itself.
  • Responds to events from the user or the operating system
----MSDN

什么是句柄(handle):

是一个号码,操作系统使用这一的号码识别对象。操作系统有一个很大的表,包含了所有创建的windows的句柄,操作系统就是通过查找这一的表找到windows的。

记住句柄不是指针。


Windows入口:

每个Windows程序都有一个入口点:WinMain或者wWinMain

为什么编译器知道**wWinMain而不是main呢?因为Microsoft C runtime库(CRT)调用WinMain或者wMinMain函数,从而调用main。


什么是WindowProc :

这个是用户定义的函数,不过操作系统已经给好了接口,用户定义window的行为:外观,响应消息等等。

程序并不是直接调用这个函数的,操作系统是通过传递消息给这个函数来和我们的程序沟通的。

DispatchMessage函数使得系统**WindowProc函数,每次去掉一个消息,由这个函数处理。


window class:

每一个窗口(window)都必须和一个window class关联。window class是一个提供给操作系统内部使用的数据结构。


事件(event)

分为:

1 用户事件

2 操作系统事件

操作系统使用消息传递模式和我们的程序沟通。一个消息其实就是一个数字代码指示着某一事件。

例如,如果用户点击鼠标右键,窗口接收到一个消息代码0x0201:

#define WM_LBUTTONDOWN    0x0201

消息过程例子:

For example, suppose the user presses the left mouse button. This causes a chain of events:

  1. The operating system places a WM_LBUTTONDOWN message on the message queue.
  2. Your program calls the GetMessage function.
  3. GetMessage pulls theWM_LBUTTONDOWN message from the queue and fills in theMSG structure.
  4. Your program calls the TranslateMessage and DispatchMessage functions.
  5. Inside DispatchMessage, the operating system calls your window procedure.
  6. Your window procedure can either respond to the message or ignore it.
----MSDN

Posted Messages versus Sent Messages(发送队列消息和直接发送消息)

  • Posting a message means the message goes on the message queue, and is dispatched through the message loop (GetMessage andDispatchMessage).
  • Sending a message means the message skips the queue, and the operating system calls the window procedure directly.
----MSDN


窗口关闭:

用户关闭窗口的时候,会引发一系列消息。如果不处理的话,window就没有真正关闭。

到底有什么一系列的消息呢?听起来很可怕,呵呵。

WM_CLOSEWM_DESTROY和 WM_QUIT三个消息;

其中WM_QUIT是一个特别的消息,让GetMessage返回0,表示消息循环结束。也因为它是最后发生的消息,所以我们的消息处理程序永远也接受不到WM_QUIT这个消息,也就无法在WindProc中扑捉这个消息。

当用户关闭窗口的时候,windows自动发送WM_CLOSE和WM_DESTROY消息;但是需要我们手动调用PostQuitMessage(0),指明要发送WM_QUIT消息,才能Exit wWinMain,否则系统会停留在wWinMain中。

下面的图来自MSDN,实在把三个消息的关系画的一目了然,不忍割爱,故此贴上来了:

Windows编程基础知识点


下面是基本窗口的代码:

#include<Windows.h>

//wParam and lParam contain additional data that pertains to the message. The exact meaning depends on the message code.
/*
For example, the documentation for the WM_SIZE message states that:
wParam is a flag that indicates whether the window was minimized, maximized, or resized. 
lParam contains the new width and height of the window as 16-bit values packed into one 32- or 64-bit number. You will need to perform some bit-shifting to get these values. Fortunately, the header file WinDef.h includes helper macros that do this.
*/
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_SIZE:
		{
			int width = (unsigned long)lParam & 0xff;//LOWORD(lParam);
			int height = ((unsigned long)lParam >>16)& 0xff;//HIWORD(lParam);
		}
		return 0;
		
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);

			FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOWFRAME));

			EndPaint(hwnd, &ps);
		}
		return 0;

	case WM_CLOSE:
		PostQuitMessage(0);
		return 0;
		//MessageBox(hwnd, L"Really quit?", L"My application", MB_OKCANCEL);

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


INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
		  PSTR lpCmdLine, INT nCmdShow)
{
	const wchar_t className[] = L"Fundamental Windows Programming";

	//1. Register Class
	WNDCLASS wc = {};
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.lpszClassName = className;

	RegisterClass(&wc);

	//2. Create Window
	HWND hwnd = CreateWindowEx(
		0,
		className,
		L"Fundamental Title",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

	if (hwnd == NULL) return 0;

	//The nCmdShow parameter can be used to minimize or maximize a window.
	ShowWindow(hwnd, nCmdShow); 

	//Message Loop
	MSG msg = {};
	//This function removes the first message from the head of the queue. If the queue is empty, the function blocks until another message is queued. 
	while (GetMessage(&msg, NULL, 0, 0))
	{
		//The TranslateMessage function is related to keyboard input; it translates keystrokes (key down, key up) into characters. You don't really need to know how this function works; just remember to call it right before DispatchMessage.
		TranslateMessage(&msg);
		//The DispatchMessage function tells the operating system to call the window procedure of the window that is the target of the message. In other words, the operating system looks up the window handle in its table of windows, finds the function pointer associated with the window, and invokes the function.
		DispatchMessage(&msg);
	}

	return 0;
}