salut,
je suis entraine d'apprendre comment faire un economiseur d'ecran sous windows XP avec langage c.
qlqun peut me montrer la skeleton d'un tel programme avec des petites commentaires sur chaque methode,
salut,
je suis entraine d'apprendre comment faire un economiseur d'ecran sous windows XP avec langage c.
qlqun peut me montrer la skeleton d'un tel programme avec des petites commentaires sur chaque methode,
merci, mais moi je veux le faire sans utiliser la librairie screen saver juste par un code en c cas cette librairie demande de creer des autres fichier que la classe en c,
merci de nouveau
bonjour,
j ai un collegue qui s'amuse a en faire en "Glut", c'est ptet sortir le marteau piqueur pour accrocher un tableau mais ca l'occupe vachement et le resultat est tres beau, qu'est ce qu'on s'amuse au boulot![]()
Bonjour,
qlqn peut me montrer un code example pour un economiseur simple qui n'utilise pas la librairie screensaver, j'ai essaye tte la semaine mais j'arrive pas a faire qlq chose![]()
Bah, quand on programme en C, on a besoin d'un fichier source (contenant le code du programme), de fichiers d'en-tête (qui contiennent la déclaration des fonctions qu'on va utiliser), de fichiers précompilés (.lib) contenant le code des fonctions qu'on va utiliser, du son à jouer, des images à afficher, etc. bref, que des fichiers. Ca n'a rien à voir avec scrnsave.lib donc si c'est la raison pour laquelle tu fuis cette bibliothèque, tu fuis plutôt le C. J'ai fait un petit screen saver (avec scrnsave.lib) histoire de te montrer que ça n'a rien de compliqué (en tout as, par rapport aux écrans de veille DX, ...).
Cet écran de veille dessine à chaque seconde, et de manière aléatoire, un petit rectangle blanc. Voici le code :
Tu dois : te lier avec scrnsave.lib (peut-être aussi avec comctl32.lib selon la version de ton compilateur), compiler sans UNICODE et exporter les fonctions ScreenSaverProc et ScreenSaverConfigureDialog à l'aide d'un fichier .def (tiens, un autre fichier). Si tu ne sais pas ce que c'est qu'un def file, tu dois étudier en profondeur les techniques de génération de DLLs. Ici t'as juste besoin d'un tout petit fichier def pour pouvoir exporter ces fonctions, je t'en fourni un exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 #include <windows.h> #include <scrnsave.h> #include <stdlib.h> #include <time.h> static int runif(int a, int b); static void rand_rect(RECT * p1, const RECT * p2); LONG WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hDC; static RECT screen; static UINT_PTR Timer; RECT r; switch(message) { case WM_CREATE: hDC = GetDC(hwnd); screen.right = GetSystemMetrics(SM_CXSCREEN); screen.bottom = GetSystemMetrics(SM_CYSCREEN); srand((unsigned)time(NULL)); Timer = SetTimer(hwnd, 1, 1000, NULL); /* Timer activé toutes les 1000 ms (1 s) */ break; case WM_TIMER: FillRect(hDC, &screen, GetStockObject(BLACK_BRUSH)); /* Efface l'écran */ rand_rect(&r, &screen); /* Calcule un rectangle aléatoire qui peut rentrer dans screen */ FillRect(hDC, &r, GetStockObject(WHITE_BRUSH)); /* Dessine le rectangle */ break; case WM_DESTROY: KillTimer(hwnd, Timer); ReleaseDC(hwnd, hDC); break; default: return (LONG)DefScreenSaverProc(hwnd, message, wParam, lParam); } return 0; } BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { /* Ne nous intéresse pas pour le moment */ return TRUE; } BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { /* Ne nous intéresse pas pour le moment */ return TRUE; } int runif(int a, int b) /* Retourne un nombre aléatoire (loi uniforme) compris entre a et b */ { return (int)(a + (((double)(b - a))/RAND_MAX) * rand() + 0.5); } void rand_rect(RECT * p1, const RECT * p2) { p1->left = runif(0, p2->right - 200); p1->top = runif(0, p2->bottom - 200); p1->right = p1->left + runif(100, 200); p1->bottom = p1->top+ runif(100, 200); }
Et voilà, tu n'as plus qu'à compiler ton projet, renommer l'exe en .scr (sauf si t'as déjà reglé cela dans les options du projet ...), et le tester. Si t'es satisfait, tu le copies enfin dans le répertoire system32 pour qu'il soit reconnu par Windows. Et si en plus tu connais un peu d'OpenGL, tu peux remplacer les rectangles par des cubes, avec des couleurs, du brouillard, des lumières, etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 EXPORTS ScreenSaverProc ScreenSaverConfigureDialog
En espérant t'avoir aidé.
salut Melem,
J'ai essayer ton code, il marchemerci.
J'ai essayer d'integrer OpenGl a l'écran de veille.
Je te passe pas les diverses fonctions OpenGl, elles sont disponibles là mais hélàs je n'obtiens qu'un ecran noir, normalement, j'ai pour l'instant programmer que le repère trigonomique...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 LONG WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: hDC = GetDC(hwnd); SetupPixelFormat(hDC); RC = wglCreateContext(hDC); wglMakeCurrent(hDC, RC); // screen.right = // screen.bottom = ; srand((unsigned)time(NULL)); // InitGL(); // Reshape(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); Timer = SetTimer(hwnd, 1, 1000, NULL); /* Timer activé toutes les 1000 ms (1 s) */ break; case WM_TIMER: // FillRect(hDC, &screen, GetStockObject(BLACK_BRUSH)); /* Efface l'écran */ // rand_rect(&r, &screen); /* Calcule un rectangle aléatoire qui peut rentrer dans screen */ // FillRect(hDC, &r, GetStockObject(WHITE_BRUSH)); /* Dessine le rectangle */ Draw(); break; case WM_DESTROY: KillTimer(hwnd, Timer); ReleaseDC(hwnd, hDC); break; default: return (LONG)DefScreenSaverProc(hwnd, message, wParam, lParam); } return 0; } BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { /* Ne nous intéresse pas pour le moment */ return TRUE; } BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { /* Ne nous intéresse pas pour le moment */ return TRUE; }
Si tu veux une fonction en particulier....
Merci de ton aide.
Flo
Tu n'as pas correctement initialisé ta vue. En outre même si ça n'a rien à voir, il faut libérer le RC dans WM_DESTROY. Voici le même écran de veille en OpenGL, avec une vue 2D (projection parallèle). Mais avant cela, quelques points à connaître :
- J'ai remplacé rand_rect par gl_rand_rect car le système de coordonnées utilisé en OpenGL (repère direct) est différent de celui utilisé par défaut sous Windows (MM_TEXT).
- runif a été modifié de façon à traiter convenablement les nombres négatifs.
- J'ai utilisé la fonction SetupPixelFormat du lien que tu m'as donné mais j'ai supprimé le double buffering (complètement inutile pour une animation de 1 image/seconde), ce qui explique le glFlush à la fin des dessins. Sinon ben t'as qu'à remplacer glFlush par SwapBuffers(hDC).
Et voilà. Tu peux maintenant tranquillement faire des écrans de veille 3D.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 #include <windows.h> #include <scrnsave.h> #include <gl/gl.h> #include <stdlib.h> #include <time.h> typedef struct { int x1, y1, x2, y2; } GLRECT; #define XMIN -10 #define XMAX 10 #define YMIN -10 #define YMAX 10 #define RECT_MIN 2 #define RECT_MAX 4 static int runif(int a, int b); static void gl_rand_rect(GLRECT * p); void SetupPixelFormat(HDC hDC); LONG WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hDC; static HGLRC hRC; static UINT_PTR Timer; GLRECT r; switch(message) { case WM_CREATE: /* Initialiser OpenGL */ hDC = GetDC(hwnd); SetupPixelFormat(hDC); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); glClearColor(0, 0, 0, 0); /* Initialiser l'animation */ srand((unsigned)time(NULL)); Timer = SetTimer(hwnd, 1, 1000, NULL); break; case WM_SIZE: glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(XMIN, XMAX, YMIN, YMAX, -1, 1); break; case WM_TIMER: gl_rand_rect(&r); glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_QUADS); glVertex2i(r.x1, r.y1); glVertex2i(r.x2, r.y1); glVertex2i(r.x2, r.y2); glVertex2i(r.x1, r.y2); glEnd(); glFlush(); break; case WM_DESTROY: KillTimer(hwnd, Timer); wglDeleteContext(hRC); ReleaseDC(hwnd, hDC); break; default: return (LONG)DefScreenSaverProc(hwnd, message, wParam, lParam); } return 0; } BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { return TRUE; } BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; } int runif(int a, int b) { double x = a + (((double)(b - a))/RAND_MAX) * rand(); return (int)(x >= 0 ? x + 0.5 : x - 0.5); } void gl_rand_rect(GLRECT * p) { p->x1 = runif(XMIN, XMAX - RECT_MAX); p->y1 = runif(YMIN + RECT_MAX, YMAX); p->x2 = p->x1 + runif(RECT_MIN, RECT_MAX); p->y2 = p->y1 - runif(RECT_MIN, RECT_MAX); }
j'ai essayer ton code, ca marche pas mieux :s
pour info :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 void SetupPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), //taille du descripteur de format 1, //version PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, //Propriété PFD_TYPE_RGBA, //Mode de couleurs 16, //Bits de couleur 0, 0, 0, 0, 0, 0, //Paramètres des couleurs 0,0, //Paramètres alpha 0,0, 0, 0, 0, //Paramètres du buffer d'accumulation 32, //Bits de profondeur 0, //Bits du buffer stencil 0, //Nombre de buffers auxiliaires 0, //ignoré (obsolète) 0, //réservé/code> 0, //ignoré (obsolète) 0, //Couleur de transparence 0 //Ignoré (obsolète) }; int pixelFormat; pixelFormat = ChoosePixelFormat(hDC, &pfd); if (!pixelFormat) { MessageBox ( WindowFromDC(hDC), "Mode graphique non supporté", "Problème", MB_ICONERROR | MB_OK ); exit(1); /*Vérifie si un PixelFormat du type demandé existe*/ } if (!SetPixelFormat(hDC, pixelFormat, &pfd)) { MessageBox ( WindowFromDC(hDC), "Mode graphique non supporté", "Problème", MB_ICONERROR | MB_OK ); exit(1); /*Applique le PixelFormat. Arrête si erreur*/ } }
AH, mais je t'avais dit de ne pas utiliser le double buffering (PFD_DOUBLEBUFFER).
Si tu mets PFD_DOUBLEBUFFER, alors tu dois remplacer glFlush() (dans WM_TIMER) par SwapBuffers(hDC);
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void SetupPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pfd; int pixelFormat; ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 32; pixelFormat = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, pixelFormat, &pfd); }
encore merci.
Juste un problème, quand j'essaye d'utiliser glulookat(...) ca n'arrive pas à afficher les symboles....
Merci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 LONG WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: /* Initialiser OpenGL */ hDC = GetDC(hwnd); SetupPixelFormat(hDC); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); glClearColor(0, 0, 0, 0); /* Initialiser l'animation */ srand((unsigned)time(NULL)); Timer = SetTimer(hwnd, 1, 1000, NULL); break; case WM_SIZE: glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluLookAt(3,2,3,0,0,0,0,1,0); // glOrtho(XMIN, XMAX, YMIN, YMAX*10, -1, 1); break; case WM_TIMER: glLoadIdentity(); g = runif(0, 10); gl_rand_rect(&r); glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINES); glVertex2i(r.x1, r.y1);glVertex2i(r.x2, r.y1); // la meme figure que toi sauf que c'est un rectangle vide glVertex2i(r.x2, r.y1);glVertex2i(r.x2, r.y2); glVertex2i(r.x2, r.y2);glVertex2i(r.x1, r.y2); glVertex2i(r.x1, r.y2);glVertex2i(r.x1, r.y1); glEnd(); glFlush(); break; case WM_DESTROY: KillTimer(hwnd, Timer); wglDeleteContext(hRC); ReleaseDC(hwnd, hDC); break; default: return (LONG)DefScreenSaverProc(hwnd, message, wParam, lParam); } return 0; }
Tu n'as même pas défini de type de projection. gluLookAt ne fait que placer la caméra, mais ça ne sert à rien tant que tu n'as pas défini une projection (parallèle ? en perspective ?).
Pour ta prochaine question, s'il y en a, je t'invite à ouvrir une nouvelle discussion car là tu commences à squatter un peu celle-ci. En outre, il y a un forum spécial pour OpenGL (2D, 3D et Jeux). Ici c'est C. Merci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 case WM_SIZE: width = LOWORD(lParam); height = HIWORD(lParam); /* On utilise toute la fenêtre */ glViewport(0, 0, width, height); /* On veut une projection en perspective, donc : */ /* glOrtho (projection parallèle) --> glFrustum (ou gluPerspective) */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, ((double)width) / ((double)height), 1, 100); /* Maintenant on place la cam (on change de point de vue) */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt( 0, 10, 20, /* Eye */ 0, 10, 0, /* Center */ 0, 1, 0 /* Up */ ); break;.
Ben tout d'abord tu crées un projet d'application Windows (Windows Application, pas Windows Console Application), ensuite dans les options de ton projet (Project > Settings), tu vas dans les options du Linkeur et tu ajoutes scrnsave.lib. Après tu peux passer à l'attaque (scrnsave.h est un fichier à inclure dans le code source (#include <scrnsave.h>), pas à "importer"). Un tutoriel sur la compilation séparée ne te fera pas non plus de mal, si t'as le temps de lire ...
j'ai suivi les instructions au dessus mais il me donne ces erreurs :
1>scrnsave.lib(scrnsave.obj) : error LNK2019: unresolved external symbol _ScreenSaverProc@16 referenced in function _RealScreenSaverProc@16
1>scrnsave.lib(scrnsave.obj) : error LNK2019: unresolved external symbol __imp__InitCommonControlsEx@4 referenced in function _WinMainN@16
1>C:\Users\MMH\Documents\Visual Studio 2008\Projects\Quaxio\Debug\Quaxio.exe : fatal error LNK1120: 2 unresolved externals
La fonction _ScreenSaverProc@16 ne peut pas être trouvée alors qu'elle est utilisée par la fonction _RealScreenSaverProc@16 du module scrnsave.obj qui se trouve dans le fichier scrnsave.lib. Cela signifie que tu n'as pas exporté (rendu publique) la fonction ScreenSaverProc, avec le def file comme je te l'ai indiqué.Envoyé par laziolb
La fonction __imp__InitCommonControlsEx@4 ne peut pas être trouvée alors qu'elle est utilisée par la fonction _WinMainN@16 du module scrnsave.obj qui se trouve dans le fichier scrnsave.lib. Cela signifie que tu as également besoin de te lier avec comctl32.lib (qui contient __imp__InitCommonControlsEx@4).Envoyé par laziolb
Quaxio.exe n'a pas pu être créé car il y a deux fonctions introuvables.Envoyé par laziolb
Conclusion :
C'est ça ...Envoyé par laziolb
![]()
voila comme tu m'a dis mais toujours la meme probleme,
si qlqu'un aura le temps voici mon projet.c en attache,
vraiement je ne sais pas quoi faire.
Partager