Ecran de veille(un vrai) matrix

Description

Je sais encore du Matrix, mais je voulais faire un écran de veille et je savais pas quoi mettre dedans.

Les caractères affichés sont Unicode (police Arial Unicode MS). D'après des commentaires sur d'autres sources, j'ai mis les caractères Katakana et Hiragana.

A compiler et linker avec scrnsave.lib. Renomer le .exe en .scr

Source / Exemple :


//***************************************************************************************
// Matrix.cpp : Ecran de veille style Matrix avec des caractères aléatoires qui 
//				descendent en colonnes.
//				Les caractère utilisés sont UNICODE pour afficher les caractères Katakana
//				et Hiragana. La police utilisée est "Arial Unicode MS".
//***************************************************************************************

#include <windows.h>
#include <windowsx.h>
#include <scrnsave.h>

#include <tchar.h>

//=======================================================================================
// Définition de constantes.
//=======================================================================================
#define ID_TIMER		0x100	// Id du timer
#define TIMEOUT			50		// cadence du timer
#define COLUMN_LENGTH	15		// hauteur des colonnes

// nombre d'éléments dans un tableau
#define _countof(array) (sizeof(array) / sizeof(array[0]))

//=======================================================================================
// Variables du module.
//=======================================================================================
static HWND			m_hWndScreenSaver;	// fenêtre de l'écran de veille
static HFONT		m_hFont;			// police de caractères utiliées
static HFONT		m_hOldFont;			// ancienne police de caractères du contexte
static TEXTMETRIC	m_TextMetric;		// métriques de la police

static RECT			m_rcClient;			// zone où dessiner
static SIZE			m_Size;				// taille de la zone

static HDC			m_hMemDC;			// contexte d'affichage en memoire
static HBITMAP		m_hMemBmp;			// bitmap associé
static HBITMAP		m_hOldBmp;			// ancien bitmap du contexte.

static int			m_NbColumns;		// nombre de colonnes affichables
static int			m_NbLines;			// nombre de lignes affichables
static wchar_t**	m_ColumnsData;		// tableau des caractères
static int*			m_ColumnsPos;		// position des colonnes
static int*			m_ColumnsSpeed;		// vitesse de descente des colonnes

//=======================================================================================
// Déclaration des fonctions du module.
//=======================================================================================
static wchar_t	RandomChar	();
static int		RandomPos	();
static int		RandomSpeed	();

static LRESULT MsgCreate		(HWND, WPARAM, LPARAM);
static LRESULT MsgDestroy		(WPARAM, LPARAM);
static LRESULT MsgEraseBkgnd	(WPARAM, LPARAM);
static LRESULT MsgTimer			(WPARAM, LPARAM);

//***************************************************************************************
// RandomChar : renvoie un caractère aléatoire. Les caractères se situent dans 2 zones :
//				- Hiragana : 0x3041 - 0x309E.
//				- Katakana : 0x30A1 - 0x30FE.
// retour : le caractère.
//***************************************************************************************
wchar_t RandomChar()
{
	// on détermine la zone et le caractère aléatoirement
	if(rand() % 2 == 0)
		return (rand() % (0x309E - 0x3041 + 1)) + 0x3041;
	else
		return (rand() % (0x30FE - 0x30A1 + 1)) + 0x30A1;
}

//***************************************************************************************
// RandomPos : renvoie une position aléatoire pour les colonnes.
// retour : la position.
//***************************************************************************************
int RandomPos()
{
	return -(rand() % (2 * m_NbLines)) - COLUMN_LENGTH;
}

//***************************************************************************************
// RandomSpeed : renvoie une vitesse de descente aléatoire pour les colonnes.
// retour : la vitesse (1 ou 2).
//***************************************************************************************
int RandomSpeed()
{
	return (rand() % 2 + 1);
}

//***************************************************************************************
// RegisterDialogClasses : fonction appelée par l'écran de veille pour enregistrer les
//						   classes de fenêtre privées.
// entrée : hInst : instance de l'application.
// retour : vrai.
//***************************************************************************************
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
	return TRUE;
}

//***************************************************************************************
// ScreenSaverProc : procédure de traitement des messages de l'écran de veille. Les 
//					 messages non traités sont passés à DefScreenSaverProc et pas
//					 DefWindowProc.
// entrée : hWnd	: fenêtre de l'écran de veille.
//			message	: message à traiter.
//			wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : dépend du message à traiter.
//***************************************************************************************
LONG WINAPI ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	// en fonction du message
	switch(message)
	{
	case WM_CREATE		: return MsgCreate		(hWnd, wParam, lParam);
	case WM_DESTROY		: return MsgDestroy		(wParam, lParam);
	case WM_ERASEBKGND	: return MsgEraseBkgnd	(wParam, lParam);
	case WM_TIMER		: return MsgTimer		(wParam, lParam);
	default : return DefScreenSaverProc(hWnd, message, wParam, lParam);
	}
}

//***************************************************************************************
// MsgCreate : traitement du message WM_CREATE. Création de la fenêtre de l'écran de
//			   veille. Création et initialisation des différentes variables.
// entrée : hWnd	: fenêtre de l'écran de veille.
//			wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : 0.
//***************************************************************************************
LRESULT MsgCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	// sauvegarde fenêtre de l'écran de veille
	m_hWndScreenSaver = hWnd;

	// création police de caractères (police UNICODE)
	m_hFont = CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
							DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
							DEFAULT_QUALITY, DEFAULT_PITCH, _T("Arial Unicode MS"));

	// taille de la zone où dessiner
	GetClientRect(hWnd, &m_rcClient);
	m_Size.cx = m_rcClient.right - m_rcClient.left;
	m_Size.cy = m_rcClient.bottom - m_rcClient.top;

	// récupération contexte où dessiner et création d'un contexte en mémoire ainsi
	// qu'un bitmap associé, relâchement du DC de la fenêtre
	HDC hdc		= GetDC(hWnd);
	m_hMemDC	= CreateCompatibleDC(hdc);
	m_hMemBmp	= CreateCompatibleBitmap(hdc, m_Size.cx, m_Size.cy);
	m_hOldBmp	= SelectBitmap(m_hMemDC, m_hMemBmp);
	ReleaseDC(hWnd, hdc);

	// affectation des couleurs de texte
	SetTextColor(m_hMemDC, RGB(0x00, 0xFF, 0x00));	// vert
	SetBkColor(m_hMemDC, RGB(0x00, 0x00, 0x00));	// noir
	SetBkMode(m_hMemDC, TRANSPARENT);

	// sélection police de caractères et récupération  de ses métriques
	m_hOldFont = SelectFont(m_hMemDC, m_hFont);
	GetTextMetrics(m_hMemDC, &m_TextMetric);
	
	// nombre de lignes et colonnes affichables
	m_NbColumns	= m_Size.cx / m_TextMetric.tmAveCharWidth;
	m_NbLines	= m_Size.cy / m_TextMetric.tmHeight;

	// création tableaux de données, init aléatoire
	m_ColumnsData = new wchar_t*[m_NbColumns];
	for(int i = 0; i < m_NbColumns; i++)
	{
		m_ColumnsData[i] = new wchar_t[COLUMN_LENGTH];
		for(int j = 0; j < COLUMN_LENGTH; j++)
			m_ColumnsData[i][j] = RandomChar();
	}

	// positions
	m_ColumnsPos = new int[m_NbColumns];
	for(i = 0; i < m_NbColumns; i++)
		m_ColumnsPos[i] = RandomPos();
	
	// vitesses
	m_ColumnsSpeed = new int[m_NbColumns];
	for(i = 0; i < m_NbColumns; i++)
		m_ColumnsSpeed[i] = RandomSpeed();

	// init générateur aléatoire, création timer
	srand(GetTickCount() ^ GetCurrentProcessId());
	SetTimer(hWnd, ID_TIMER, TIMEOUT, NULL);
	return 0;
}

//***************************************************************************************
// MsgDestroy : traitement du message WM_DESTROY. Destruction de la fenêtre de l'écran de
//			   veille. Libération des ressources et de la mémoire.
// entrée : wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : 0.
//***************************************************************************************
LRESULT MsgDestroy(WPARAM wParam, LPARAM lParam)
{
	// sélection ancienne police de caractères et destruction de celle créée
	SelectFont(m_hMemDC, m_hOldFont);
	DeleteFont(m_hFont);

	// destruction contexte d'affichage en mémoire et bitmap associé
	SelectBitmap(m_hMemDC, m_hOldBmp);
	DeleteBitmap(m_hMemBmp);
	DeleteDC(m_hMemDC);

	// destruction timer
	KillTimer(m_hWndScreenSaver, ID_TIMER);
	
	// destruction tableaux de données
	for(int i = 0; i < m_NbColumns; i++)
		delete[] m_ColumnsData[i];
	delete[] m_ColumnsData;
	delete[] m_ColumnsPos;
	delete[] m_ColumnsSpeed;

	// retour
	return 0;
}

//***************************************************************************************
// MsgEraseBkgnd : traitement du message WM_ERASEBKGND. Effacement du fond de la fenêtre
//				   de l'écran de veille.
// entrée : wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : 0.
//***************************************************************************************
LRESULT MsgEraseBkgnd(WPARAM wParam, LPARAM lParam)
{
	// effacement du fond en noir
	HDC hdc = GetDC(m_hWndScreenSaver);
	FillRect(hdc, &m_rcClient, GetStockBrush(BLACK_BRUSH));
	ReleaseDC(m_hWndScreenSaver, hdc);
	return 0;
}

//***************************************************************************************
// MsgTimer : traitement du message WM_TIMER. Met à jour régulièrement l'affichage de
//			  l'écran de veille.
// entrée : wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : 0.
//***************************************************************************************
LRESULT MsgTimer(WPARAM, LPARAM)
{
	//-----------------------------------------------------------------------------------	
	// décalage du tableau des données
	for(int i = 0; i < m_NbColumns; i++)
	{
		// décalage vers le bas
		m_ColumnsPos[i] += m_ColumnsSpeed[i];

		// modification des données
		for(int j = 0; j < COLUMN_LENGTH; j++)
			m_ColumnsData[i][j] = RandomChar();

		// si colonne n'est plus visible, on la réinitialise
		if(m_ColumnsPos[i] >= m_NbLines)
		{
			m_ColumnsPos[i] = RandomPos();
			m_ColumnsSpeed[i] = RandomSpeed();
		}
	}

	// effacement du fond
	FillRect(m_hMemDC, &m_rcClient, GetStockBrush(BLACK_BRUSH)); 

	//-----------------------------------------------------------------------------------	
	// dessin des données
	for(i = 0; i < m_NbColumns; i++)
	{
		for(int j = 0; j < COLUMN_LENGTH; j++)
		{
			// si le caractère n'est pas visible
			if(m_ColumnsPos[i] + j < 0 || m_ColumnsPos[i] + j >= m_NbLines)
				continue;

			// couleur du caractère
			if(rand() % 2 == 0)
				SetTextColor(m_hMemDC, RGB(0x00, 0xFF, 0x00));
			else
				SetTextColor(m_hMemDC, RGB(0x00, 0x7F, 0x00));

			// coordonnées du caractère, dessin du caracère UNICODE avec TextOutW
			int x = i * m_TextMetric.tmAveCharWidth;
			int y = (m_ColumnsPos[i] + j) * m_TextMetric.tmHeight;
			TextOutW(m_hMemDC, x, y, &m_ColumnsData[i][j], 1);
		}
	}

	//-----------------------------------------------------------------------------------	
	// recopie à l'écran
	HDC hdc = GetDC(m_hWndScreenSaver);
	BitBlt(hdc, 0, 0, m_Size.cx, m_Size.cy, m_hMemDC, 0, 0, SRCCOPY);
	ReleaseDC(m_hWndScreenSaver, m_hMemDC);

	// retour
	return 0;
}

//***************************************************************************************
// ScreenSaverConfigureDialog : procédure de traitement des messages de la boîte de 
//								dialogue de configuration de l'écran de veille.
// entrée : hDlg	: boîte de dialogue.
//			message	: message à traiter.
//			wParam	: premier paramètre du message.
//			lParam	: second paramètre du message.
// retour : vrai si le message a été traité, faux sinon.
//***************************************************************************************
BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam)
{
	// pas de boîte de dialogue de configuration
	return FALSE;
}

Conclusion :


Dans le zip, en plus de cet écran de veille, un autre utilisant DirectX.

Codes Sources

A voir également

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.