Maison  >  Article  >  Opération et maintenance  >  Bases du SDK Win32 (12) Traitement du message WM_PAINT (Figure)

Bases du SDK Win32 (12) Traitement du message WM_PAINT (Figure)

黄舟
黄舟original
2017-06-06 10:11:467777parcourir

1. Introduction

Dans un ordinateur, presque tout ce qui est affiché à l'écran est dessiné, y compris les fenêtres, les boîtes de dialogue, les images et tout le texte, et le message WM_PAINT est Message déclenché. par le système lors du dessin de ces objets . Presque toutes les opérations que nous effectuons sur l'ordinateur déclencheront ce message, et c'est également l'un des messages les plus importants de Windows. Cet article se concentre sur l’expérimentation de ce message pour une étude approfondie.

2. Bases de WM_PAINT

2.1 Définition des macros

#define WM_PAINT                        
0x000F

2.2 Paramètres de transport

Nous savons cela lors de l'utilisation de send Lorsque message/postmessage envoie un message, il porte souvent deux paramètres, WPARAM et LPARAM, et lors de l'utilisation de GetMessage ou PeekMessage pour recevoir un message, il recevra également ces deux paramètres. Certains de ces messages contiendront des informations nécessaires dans des paramètres, tels que la position de la souris, la longueur et la largeur de la fenêtre, etc. Ces deux paramètres de WM_PAINT sont vides et ne portent aucun message.

2.3 Synchronisation du déclenchement

Afin d'obtenir la synchronisation du déclenchement de ce message, nous créons d'abord un projet de fenêtre Win32 comme objet de test. La fonction de traitement de fenêtre est définie comme suit :

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
{  
	switch (uMsg)  
	{  
	case WM_DESTROY:  
		PostQuitMessage(0);//可以使GetMessage返回0  
		break;
	case  WM_PAINT:
		{
			WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL);
		}
		break;
	default:  
		break;  
	}  
	return DefWindowProc(hWnd, uMsg, wParam, lParam);  
}

Dans notre instruction de traitement WM_PAINT, une chaîne de "WM_PAINTn" est écrite sur la sortie standard de la console pour vérifier que le message WM_PAINT a été déclenché. Vérifions respectivement le timing de déclenchement de WM_PAINT :

1 Lorsque le programme démarre, il se déclenche lorsque la fenêtre est dessinée.

Lorsque nous démarrons le programme, parce que nous devons dessiner la fenêtre, le message WM_PAINT sera déclenché et la chaîne ci-dessus sera imprimée :


2. Lorsque la fenêtre est redimensionnée avec la souris, elle se déclenchera en continu :

Puisque la fenêtre doit être redessinée en continu lors du redimensionnement de la fenêtre, qu'est-ce que c'est ? affiché à ce moment est un déclenchement continu. de la minimisation

L'image ci-dessous provient du processus de réduction à la restauration de la fenêtre deux fois. Vous pouvez voir que deux autres chaînes sont imprimées

.

4. Le message WM_PAINT sera déclenché lors de la maximisation

Lorsque l'image est agrandie et restaurée, le message WM_PAINT sera déclenché respectivement, comme indiqué dans la figure ci-dessous :

5. Lorsque vous faites glisser la fenêtre hors de l'écran, le message WM_PAINT ne sera pas déclenché, mais lorsqu'il sera ramené à l'écran, le message WM_PAINT sera affiché. Le message continuera à être déclenché


La capture d'écran ci-dessous montre que lorsque la fenêtre est ramenée à l'écran, la fenêtre est constamment redessinée, déclenchant le message WM_PAINT.

6. Utilisez la fonction Inval

idate

Rect pour déclencher le message WM_PAINT

Fonction prototype d'InvalidateRect Comme suit, chaque appel déclenchera un message WM_PAINT :

hWnd : Le handle du formulaire où la zone client où le doit être mis à jour. S'il est NULL, le système redessinera toutes les fenêtres avant le retour de la fonction, puis enverra WM_ERASEBKGND et WM_PAINT à la fonction de traitement de la procédure de fenêtre.

lpRect : La représentation rectangulaire de la zone invalide. C'est un

pointeur de structure

qui stocke la taille du rectangle. Si NULL, toute la zone client de la fenêtre sera ajoutée à la zone de mise à jour.
BOOL InvalidateRect(
HWND hWnd, // handle of window with changed update region
CONST RECT *lpRect, // address of rectangle coordinates
BOOL bErase // erase-background flag
);
bErase : indique s'il faut redessiner le rectangle invalide une fois qu'il est marqué comme valide. Utilisez un pinceau prédéfini lors du redessin. Un redessinage est requis lorsque TRUE est spécifié.

Valeur de retour : Si la fonction réussit, elle renvoie une valeur non nulle, sinon elle renvoie une valeur nulle.
Afin de vérifier le fonctionnement de la fonction InvalidateRect, nous devons ajouter un traitement du message WM_LBUTTONDOWN dans la fonction de traitement de fenêtre, et appeler InvalidateRect à chaque fois que l'on clique sur le bouton gauche de la souris :

//窗口处理函数  
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
{  
	switch (uMsg)  
	{  
	case WM_DESTROY:  
		PostQuitMessage(0);//可以使GetMessage返回0  
		break;
	case  WM_PAINT:
		{
			WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL);
		}
	case WM_LBUTTONDOWN:
		{
			InvalidateRect(hWnd,NULL,true);
		}
		break;
	default:  
		break;  
	}  
	return DefWindowProc(hWnd, uMsg, wParam, lParam);  
}

        下图为执行结果,点击了3次鼠标左键,触发了3次WM_PAINT消息。

总结:

        触发WM_PAINT消息的本质是改变窗口对应的显存的大小就触发一次,我们进行的每一次窗口最大化、最小化并恢复都是因为改变了窗口的显存而触发了该消息。在我们向屏幕外面拖动窗口时,这点比较特殊,窗口的显存是在一点点被擦除的,此时不会触发WM_PAINT,但是拉回窗口后,显存需要将擦除的部分重新绘制,这就又会触发一次该消息。而InvalidateRect函数,就是通过强制的清除并重绘显存来实现触发WM_PAINT消息。

三、WM_PAINT消息的处理

        我们尝试处理WM_PAINT消息,并在窗口上绘制一个矩形,绘图步骤如下:

1、开始绘图处理

HDC BeginPaint(
        HWND hwnd,//绘图窗口
        LPPAINTSTRUCT  lpPaint
	);

        我们利用BeginPaint获取绘图设备的句柄---一个HDC对象,然后在改绘图设备上进行绘制。

2、利用HDC对象进行绘图

3、结束绘图处理

Bool EndPoint(
        HWND hWnd,
        CONST PAINTSTRUCT *lpPaint
);

        绘制过程参考下面的代码:

//窗口处理函数  
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
{  
	
	switch (uMsg)  
	{  
	case WM_DESTROY:  
		PostQuitMessage(0);//可以使GetMessage返回0  
		break;
	case  WM_PAINT:
		{
			PAINTSTRUCT pt;
			HDC hdc;
			hdc=BeginPaint(hWnd,&pt);
			Rectangle(hdc,0,0,100,100);
			EndPaint(hWnd,&pt);
		}
	case WM_LBUTTONDOWN:
		{
			//InvalidateRect(hWnd,NULL,true);
		}
		break;
	default:  
		break;  
	}  
	return DefWindowProc(hWnd, uMsg, wParam, lParam);  
}

        执行结果如下,我们成功绘制了一个矩形:


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn