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.
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.