Calendrier incrusté sur le bureau [win32]

Soyez le premier à donner votre avis sur cette source.

Vue 8 718 fois - Téléchargée 795 fois

Description

Cette source permet d'avoir un calendrier mensuel directement affiché sur le bureau.

Cette source permet notament de voir la techinque du double-buffering.

Pour ceux qui ne savent pas ce que c'est : rapide aperçu...
En gros si on dessine au fur et à mesure un dessin à l'écran à chaque fois qu'on recommence ça ferait apparaitre un clignotement. Pour éviter cela, on dessine dans un buffer (sorte d'écran virtuel) et quand le dessin est terminé on bascule le buffer à l'écran. Du coup on ne voit plus les étapes intermédiaires.

PS : pour configurer le calendrier (couelurs, positions, ...) c'est au tout début du code

Source / Exemple :


//////////////////////////////////////////////////////////////
// Include
//////////////////////////////////////////////////////////////

#include <windows.h>
#include <stdio.h>

//////////////////////////////////////////////////////////////
// Paramètres du calendrier
//////////////////////////////////////////////////////////////

#define POSITION_X	700
#define POSITION_Y	5

#define ESPACEMENT_HORIZONTAL	30
#define ESPACEMENT_VERTICAL		20

#define FORECOLOR	RGB(0,0,0)
#define BACKCOLOR	RGB(255,255,255)
#define JOURCOLOR	RGB(255,32,32)

#define REFRESH_RATE	1000

//////////////////////////////////////////////////////////////
// Variables globales
//////////////////////////////////////////////////////////////

HWND hDesk;
RECT fullRect;

short nJours[6][7];
SYSTEMTIME st;

char* cJours[7];

//////////////////////////////////////////////////////////////
// Fonctions
//////////////////////////////////////////////////////////////

/**

  • Récupère le HWND du bureau
  • /
HWND FindDesktopWindow() { HWND hWnd = FindWindow("Progman", "Program Manager"); if(GetParent(hWnd) == NULL) { HWND hWndEnfant = GetWindow(hWnd, GW_CHILD); char szBuf[32]; while(hWndEnfant != NULL) { GetClassName(hWndEnfant, szBuf, sizeof(szBuf)); if(lstrcmp(szBuf, "SHELLDLL_DefView") == 0) break; hWndEnfant = GetWindow(hWndEnfant, GW_HWNDNEXT); } if(hWndEnfant != NULL) { hWndEnfant = GetWindow(hWndEnfant, GW_CHILD); while(hWndEnfant != NULL) { GetClassName(hWndEnfant, szBuf, sizeof(szBuf)); if(lstrcmp(szBuf, "SysListView32") == 0) break; hWndEnfant = GetWindow(hWndEnfant, GW_HWNDNEXT); } if(hWndEnfant != NULL) return hWndEnfant; } } return GetDesktopWindow(); } /**
  • Dessine le calendrier sans ombre
*
  • hDC : DC où le calendrier est dessiné
  • bFore : TRUE si c'est le calendrier d'avant-plan qui doit être dessiné FALSE sinon (ombre)
  • /
void DessineCalendrierAux(HDC hDC, BOOL bFore) { int i, j; char nDecalage; RECT rect; // Si c'est le dessin du texte d'avant plan il n'y a aps de décalage, sinon il y a un décalage de 1 pixel nDecalage = bFore ? 0 : 1; SetTextColor(hDC, bFore ? FORECOLOR : BACKCOLOR); SetBkMode(hDC, TRANSPARENT); for (j=0; j<7; j++) { // jours de la semaine rect.left = nDecalage + j *ESPACEMENT_HORIZONTAL; rect.right = nDecalage + (j+1)*ESPACEMENT_HORIZONTAL; rect.top = nDecalage; rect.bottom = nDecalage + ESPACEMENT_VERTICAL; DrawText(hDC, cJours[j], 1, &rect, DT_CENTER); for (i=0; i<6; i++) { // numéro des jours du mois char numero[2] = ""; if (nJours[i][j]>0) { sprintf(numero, "%d", nJours[i][j]); rect.top = nDecalage + (i+1)*ESPACEMENT_VERTICAL; rect.bottom = nDecalage + (i+2)*ESPACEMENT_VERTICAL; if (nJours[i][j]==st.wDay && nDecalage == 0) Arc( hDC, rect.left, rect.top-1, rect.right, rect.bottom-1, 0, 0, 0, 0); DrawText(hDC, numero, strlen(numero), &rect, DT_CENTER); } } } } /**
  • Dessine le calendrier ombré (utilisation du double buffering
  • /
void DessineCalendrier(HDC hDeskDC) { HDC hDC; DWORD dwWidth, dwHeight, dwNumColors, dwBPP; void *pBits; HBITMAP hbmp; BITMAPINFO bmpinfo; HPEN hPen; // Dimensions du buffer dwWidth = fullRect.right - fullRect.left; dwHeight = fullRect.bottom - fullRect.top; dwBPP = GetDeviceCaps(hDeskDC, BITSPIXEL); if(dwBPP <= 8) dwNumColors = 256; else dwNumColors = 0; // Initialisation du buffer bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpinfo.bmiHeader.biWidth = dwWidth; bmpinfo.bmiHeader.biHeight = dwHeight; bmpinfo.bmiHeader.biPlanes = 1; bmpinfo.bmiHeader.biBitCount = (WORD) dwBPP; bmpinfo.bmiHeader.biCompression = BI_RGB; bmpinfo.bmiHeader.biSizeImage = 0; bmpinfo.bmiHeader.biXPelsPerMeter = 0; bmpinfo.bmiHeader.biYPelsPerMeter = 0; bmpinfo.bmiHeader.biClrUsed = dwNumColors; bmpinfo.bmiHeader.biClrImportant = dwNumColors; hbmp = CreateDIBSection(hDeskDC, &bmpinfo, DIB_PAL_COLORS, &pBits, NULL, 0); // Création du buffer et copie de la zone de l'écran concernée hDC = CreateCompatibleDC(hDeskDC); SelectObject(hDC, hbmp); BitBlt(hDC, 0, 0, dwWidth, dwHeight, hDeskDC, fullRect.left, fullRect.top, SRCCOPY); // Couleur pour l'ellipse hPen = CreatePen(PS_SOLID, 1, JOURCOLOR); SelectObject(hDC, hPen); // Dessine la partie en arriere plan (l'ombre) DessineCalendrierAux(hDC, FALSE); // Dessine la partie en avant-plan DessineCalendrierAux(hDC, TRUE); // Copie du buffer sur le bureau BitBlt(hDeskDC, POSITION_X, POSITION_Y, dwWidth, dwHeight, hDC, 0, 0, SRCCOPY); DeleteObject(hbmp); DeleteObject(hPen); DeleteDC(hDC); } /**
  • Initialisation de valeurs necessaires au graphisme
  • /
void InitCalendrierGraphique() { // Rect du calendrier fullRect.left = POSITION_X; fullRect.top = POSITION_Y; fullRect.right = POSITION_X + 7*ESPACEMENT_HORIZONTAL; fullRect.bottom = POSITION_Y + 7*ESPACEMENT_VERTICAL; } /**
  • Initialise le tableau du calendrier
  • /
void RemplitCalendrier() { short nPremierJour; short nJoursParMois[13]; short nombreJours; short nCase, day; char i,j; // Récupère la date du jour GetLocalTime(&st); // Le premier jour du mois est-il un lundi, mardi ,... ? nPremierJour = (st.wDayOfWeek - st.wDay + 1 + 5*7) % 7; if (nPremierJour==0) nPremierJour=7; // Nombre de jours par mois nJoursParMois[0] = 0; nJoursParMois[1] = 31; nJoursParMois[2] = 28; nJoursParMois[3] = 31; nJoursParMois[4] = 30; nJoursParMois[5] = 31; nJoursParMois[6] = 30; nJoursParMois[7] = 31; nJoursParMois[8] = 31; nJoursParMois[9] = 30; nJoursParMois[10] = 31; nJoursParMois[11] = 30; nJoursParMois[12] = 31; // Année bissextile (facile entre 1980 et 2099) if (st.wMonth%4==0) nJoursParMois[2]++; // Nombre de jours pour le mois en cours nombreJours = nJoursParMois[st.wMonth]; // On remplit le calendrier for (i = 0; i<6; i++) for (j = 0; j<7; j++) { nCase = 7*i + j; day = nCase - nPremierJour + 2; nJours[i][j] = day>0 && day<=nombreJours ? day :0; } // Lettres qui représentent les jours de la semaine cJours[0] = "L"; cJours[1] = "M"; cJours[2] = "M"; cJours[3] = "J"; cJours[4] = "V"; cJours[5] = "S"; cJours[6] = "D"; } /**
  • Fonction appelée périodiquement pour relancer le dessin du calendrier
  • /
void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT uTimerId, DWORD dwTime) { HDC hDC; SYSTEMTIME st_recent; // Si la date a changé, mettre à jour le calendrier GetLocalTime(&st_recent); if (st_recent.wDay != st.wDay || st_recent.wMonth != st.wMonth || st_recent.wYear != st.wYear) { InvalidateRect(NULL, NULL, TRUE); RemplitCalendrier(); } // Dessine le calendrier if(hDC = GetDC(hDesk)) { DessineCalendrier(hDC); ReleaseDC(hDesk, hDC); } } /**
  • Point d'entrée
  • /
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int iCmdShow) { MSG msg; DWORD dwPid; hDesk = FindDesktopWindow(); InitCalendrierGraphique(); RemplitCalendrier(); dwPid = GetWindowThreadProcessId(hDesk, NULL); if(!AttachThreadInput(dwPid, GetCurrentThreadId(), TRUE)) return 0; SetTimer(NULL, 0, REFRESH_RATE, TimerProc); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } AttachThreadInput(dwPid, GetCurrentThreadId(), FALSE); KillTimer(NULL, 0); return msg.wParam; }

Conclusion :


Je me suis inspiré de 2 autres sources :
- celle de Brunews sur la sauvegarde des HDC dans des fichiers BMP :
http://www.cppfrance.com/code.aspx?ID=11128
-et celle de magma : "ANIMEZ VOTRE BUREAU"
http://www.cppfrance.com/code.aspx?ID=16843

Merci à eux

MISE A JOUR : 22/11/2003
Si la date change pendant le fonctionnement du calendrier, il se met à jour

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_dominion
Messages postés
230
Date d'inscription
mardi 21 janvier 2003
Statut
Membre
Dernière intervention
15 mai 2008

ymca : ok merci
garslouche : en fait je cherche à créer une fonction capable de savoir si la fenêtre active c'est le bureau... Le but est d'afficher une sorte de post it si c'est le cas. Par exemple si je clique sur l'icone bureau mon soft doit le détecter et afficher le postit.
ymca2003
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
GetDesktopWindow renvoi le handle de la fenêtre globale du bureau mais cette fenêtre contient d'autres fenêtres comme une ListView pour la zone de travail avec les icones et c'est cette ListView qui faut récupérer.
garslouche
Messages postés
584
Date d'inscription
mardi 26 novembre 2002
Statut
Membre
Dernière intervention
29 mai 2015

1. Je ne sais pas pourquoi mais GetDesktopWindow ne fonctionne pas. Comme c'est marqué je me suis largement inspiré de la source
http://www.cppfrance.com/code.aspx?ID=16843

2. Je ne comprends ce que tu veux dire par "si on est sur le bureau"
cs_dominion
Messages postés
230
Date d'inscription
mardi 21 janvier 2003
Statut
Membre
Dernière intervention
15 mai 2008

2 choses :
1. Pourquoi GetDesktopWindow(); ne suffit pas pour trouver le handle du bureau ?
2. Ton prog c'est un dessin c'est ça ? Je cherche un moyen de détecter si on est sur le bureau pour afficher des windows... Si quelqu'un sait m'aider...

Merci.
J6B
Messages postés
11
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
4 septembre 2006

ta fonction FindDesktopWindow() est très simplifiable avec des FindWindowEx pour trouver les fenêtre filles plus facilement.


HWND FindDesktopWindow(){

HWND hWnd=FindWindow("Progman","Program Manager");
if(!GetParent(hWnd)){

if(HWND hWndEnfant=FindWindowEx(hWnd,NULL,"SHELLDLL_DefView",NULL)){

if(hWndEnfant=FindWindowEx(hWndEnfant,NULL,"SysListView32",NULL)) return hWndEnfant;
};
};
return GetDesktopWindow();
};

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.