Loupe simple (win32)

Soyez le premier à donner votre avis sur cette source.

Vue 7 617 fois - Téléchargée 844 fois

Description

Suite à une question du forum j'ai fait cette petite loupe qui affiche la zone sous la souris avec un facteur 2. Un timer raffraichit la loupe toutes les 50ms.

Source / Exemple :


//***************************************************************************************
// Loupe.cpp :
//
//***************************************************************************************

#include <windows.h>

//=======================================================================================
// Variables globales.
//=======================================================================================
HINSTANCE	g_hAppInstance	= NULL;	// instance de l'application
HWND		g_hWndMainFrame	= NULL;	// fenêtre principale de l'application

//=======================================================================================
// Fonctions du module.
//=======================================================================================
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

//***************************************************************************************
// WinMain :
//***************************************************************************************
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
				   int nCmdShow)
{
	// initialisation de l'application
	if(!InitInstance(hInstance, nCmdShow))
		return 0;

	// boucle de messages
	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

//***************************************************************************************
// InitInstance :
//***************************************************************************************
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	// sauvegarde instance de l'application
	g_hAppInstance = hInstance;
	char szWndClass[] = "LoupeWnd";
	char szWndTitle[] = "Loupe";

	// initialisation classe de fenêtre
	WNDCLASS wc;
	ZeroMemory(&wc, sizeof(WNDCLASS));
	wc.hInstance		= g_hAppInstance;
	wc.lpfnWndProc		= WndProc;
	wc.lpszClassName	= szWndClass;
	wc.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.style			= CS_HREDRAW|CS_VREDRAW;
	if(!RegisterClass(&wc))
		return FALSE;

	// création de la fenêtre principale
	g_hWndMainFrame = CreateWindowEx(WS_EX_TOPMOST, szWndClass, szWndTitle,
			WS_OVERLAPPED|WS_CAPTION|WS_THICKFRAME|WS_SYSMENU|WS_MINIMIZEBOX,
			0, 0, 200, 200, NULL, NULL, g_hAppInstance, NULL);
	if(g_hWndMainFrame == NULL)
		return FALSE;

	// affichage et mise à jour
	ShowWindow(g_hWndMainFrame, nCmdShow);
	UpdateWindow(g_hWndMainFrame);
	return TRUE;
}

//***************************************************************************************
// WndProc :
//***************************************************************************************
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// en fonction du message
	switch(uMsg)
	{
	case WM_CREATE :
		{
			// création timer
			SetTimer(hWnd, 0x100, 50, NULL);
			return 0;
		}
	case WM_DESTROY :
		{
			// suppression du timer, fin de l'application
			KillTimer(hWnd, 0x100);
			PostQuitMessage(0);
			return 0;
		}
	case WM_TIMER :
		{
			// mise à jour de la fenêtre
			InvalidateRect(hWnd, NULL, FALSE);
			UpdateWindow(hWnd);
			return 0;
		}
	case WM_PAINT :
		{
			// début du dessin
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hWnd, &ps);

			// taille zone cliente
			RECT rcClient;
			GetClientRect(hWnd, &rcClient);
			SIZE sizeDst;
			sizeDst.cx = rcClient.right-rcClient.left;
			sizeDst.cy = rcClient.bottom-rcClient.top;

			// création DC et bitmap en mémoire
			HDC hMemDC = CreateCompatibleDC(hdc);
			HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, sizeDst.cx, sizeDst.cy);
			HBITMAP hOldMemBmp = (HBITMAP) SelectObject(hMemDC, hMemBmp);

			// effacement du fond en blanc
			HBRUSH hBrush = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));
			FillRect(hMemDC, &rcClient, hBrush);
			DeleteObject(hBrush);

			// position de la souris et de la fenêtre
			POINT ptMouse;
			GetCursorPos(&ptMouse);
			RECT rcWnd;
			GetWindowRect(hWnd, &rcWnd);

			// faire un zoom de la zone sous la souris
			if(!PtInRect(&rcWnd, ptMouse))
			{
				// zone source
				SIZE sizeSrc;
				sizeSrc.cx = sizeDst.cx/2;
				sizeSrc.cy = sizeDst.cy/2;
				RECT rcSrc;
				rcSrc.left		= ptMouse.x-sizeSrc.cx/2;
				rcSrc.top		= ptMouse.y-sizeSrc.cy/2;
				rcSrc.right		= rcSrc.left+sizeSrc.cx;
				rcSrc.bottom	= rcSrc.top+sizeSrc.cy;

				// récupération DC de l'écran et recopie
				HDC hScreenDC = GetDC(NULL);
				StretchBlt(hMemDC, 0, 0, sizeDst.cx, sizeDst.cy, hScreenDC,
						rcSrc.left, rcSrc.top, sizeSrc.cx, sizeSrc.cy, SRCCOPY);
				ReleaseDC(NULL, hScreenDC);
			}
			
			// recopie du DC en mémoire, libération des ressources
			BitBlt(hdc, 0, 0, sizeDst.cx, sizeDst.cy, hMemDC, 0, 0, SRCCOPY);
			SelectObject(hMemDC, hOldMemBmp);
			DeleteObject(hMemBmp);
			DeleteDC(hMemDC);

			// fin du dessin
			EndPaint(hWnd, &ps);
			return 0;
		}
	}

	// traitement par défaut
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

julien_boss
Messages postés
165
Date d'inscription
samedi 4 juin 2005
Statut
Membre
Dernière intervention
24 octobre 2007

Euh enfaite je ne comprends pas :
si on souhaite restaurer le bitmap "par défaut", pourquoi ne pas le restaurer dans le DC "par défaut" ; pourquoi ca : SelectObject(hMemDC, hOldMemBmp); et non SelectObject(hdc, hOldMemBmp);
?
julien_boss
Messages postés
165
Date d'inscription
samedi 4 juin 2005
Statut
Membre
Dernière intervention
24 octobre 2007

Ah ok je ne savais pas que (HBITMAP) SelectObject(hMemDC, hMemBmp); retournait le bitamp "par défaut". Je comprends mieux merci. Je vais donc réintégrer ces lignes à ma source pour être tout à fait propre ^^
Ombitious_Developper
Messages postés
2333
Date d'inscription
samedi 28 février 2004
Statut
Membre
Dernière intervention
26 juillet 2013
34
Salut:

C'est la philosophie de Windows, c'est tout.
Ombitious_Developper
Messages postés
2333
Date d'inscription
samedi 28 février 2004
Statut
Membre
Dernière intervention
26 juillet 2013
34
Salut:

Dans la programmation Windows, tu ne peux pas afficher une image directement sur une fenêtre, tu dois passer par une image qui se trouve en mémoire. Les deux premières lignes font ça:

Création d'un contexte d'affichage en mémoire compatible avec celui de la fenêtre.
Création d'une image compatible avec le contexte d'affichage de la fenêtre.

Dans la toisième ligne tu séléctionne ce bitmap dans le hMemDC et ça retourne le bitmap par défaut que tu enregistre dans une variable pour le restaurer après avoir finir le dessin, sinon tu auras une fuite de mémoire [memory leak].

Le 4eme ligne contient la fameuse fonction BitBlt (notament la plus heureuse) qui effectue des transferts de bloques de bits de la mémoire vers la fenêtre pour dessiner l'image en question.
SRCCOPY veut dire transfert sans modification.

La dernière ligne est déja expliquée elle fait retourner le HBITMAP par défaut du hMemDC.

J'espère que ça t'aides au moins.

Bye.
julien_boss
Messages postés
165
Date d'inscription
samedi 4 juin 2005
Statut
Membre
Dernière intervention
24 octobre 2007

Bonjour,

je peux savoir à quoi servent ces lignes, stp :

// création DC et bitmap en mémoire
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, sizeDst.cx, sizeDst.cy);
HBITMAP hOldMemBmp = (HBITMAP) SelectObject(hMemDC, hMemBmp); //Celle ci

// recopie du DC en mémoire, libération des ressources
BitBlt(hdc, 0, 0, sizeDst.cx, sizeDst.cy, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOldMemBmp); // Et celle ci

Merci ;)

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.