Programmation avec la SDL/Les fenêtres

Programmation avec la SDL
Sommaire
L' affichage vidéo
L'essentiel
Approfondissement
La gestion des évènements
Annexes
Modifier ce modèle

Dans ce chapitre, nous allons apprendre à créer une fenêtre. Cette étape est fondamentale dans la conception d'un programme en mode graphique.

Création d'une fenêtre modifier

Pour créer une fenêtre, la première étape va consister en la déclaration d'un pointeur de SDL_Window. Mais ce dont nous aurons besoin le plus, ce sera de la fonction SDL_CreateWindow. Il semble que cela va devenir une habitude (une bonne) : en voici le prototype.

SDL_Window* SDL_CreateWindow(const char* title,
                              int         x,
                              int         y,
                              int         w,
                              int         h,
                              Uint32      flags);
 
Repère utilisé par la fonction SDL_CreateWindow

La fonction SDL_CreateWindow renvoie NULL en cas d'erreur.

Penchons-nous sur les arguments de cette fonction :

  • title : c'est le titre de la fenêtre.
  • x et y : ces arguments correspondent à la position de départ de la fenêtre en pixel. Mais attention, le repère est un peu spécial. Son origine se situe en haut à gauche de votre écran. Lorsque vous vous déplacez vers la droite, la valeur de x augmente et lorsque vous vous déplacez vers le bas, c'est y qui sera de plus en plus grand. Pour mieux le visualiser, le repère est tracé ci-contre sur une capture d'écran de Linux (Interface : Gnome). Pour ceux qui n'ont pas leur barre de démarrage en haut (en particulier les utilisateurs de Windows), le repère prend son origine tout en haut à gauche et non à partir de la barre de démarrage. Si vous voulez centrer la fenêtre, vous pouvez donner la valeur SDL_WINDOWPOS_CENTERED ou bien si vous n'êtes pas inspiré, SDL_WINDOWPOS_UNDEFINED conviendra.
  • w et h : respectivement la largeur (width) et la hauteur (height), en pixels tous deux.
  • flags : ici, on retrouve le même principe que pour SDL_Init. Voici la liste des flags avec leur description :
Flags de SDL_CreateWindow
Description
SDL_WINDOW_FULLSCREEN Fenêtre en plein écran (perte de qualité : c'est en fait un zoom de la fenêtre de résolution h * w que vous avez entrée).
SDL_WINDOW_FULLSCREEN_DESKTOP Fenêtre en plein écran avec la résolution du bureau.
SDL_WINDOW_SHOWN La fenêtre est visible.
SDL_WINDOW_HIDDEN La fenêtre n'est pas visible.
SDL_WINDOW_BORDERLESS Fenêtre sans bordures. Utile pour les splash screens
SDL_WINDOW_RESIZABLE Fenêtre redimensionnable.
SDL_WINDOW_MINIMIZED Fenêtre réduite.
SDL_WINDOW_MAXIMIZED Fenêtre maximisée.
SDL_WINDOW_OPENGL Pour les utilisateurs d'OpenGL, cela ne nous concerne pas.

Voici donc le code complet pour créer une fenêtre redimensionnable de résolution 600x600 dont la position sera centrée, que vous ne devez pas compiler pour le moment :

SDL_Window* fenetre;  //Déclaration de la fenêtre
fenetre = SDL_CreateWindow("Une fenetre SDL",
    SDL_WINDOWPOS_CENTERED,
    SDL_WINDOWPOS_CENTERED, 600 , 600 , SDL_WINDOW_RESIZABLE);  //Création de la fenêtre

if (fenetre == NULL)  //gestion des erreurs
{
    printf("Erreur lors de la creation d'une fenetre : %s", SDL_GetError());
    return EXIT_FAILURE;
}

Il nous manque encore quelque chose pour que le code ci-dessus soit correct : nous avons alloué de l'espace au pointeur fenetre, il va nous falloir le libérer. Pour cela, on utilise la fonction SDL_DestroyWindow que l'on va utiliser ainsi :

SDL_DestroyWindow(fenetre);

À présent, vous pouvez compiler un code combinant l'initialisation de la SDL, la création de la fenêtre et sa destruction. Mais une mauvaise surprise vous attend : la fenêtre n'apparaît pas... En fait, elle apparaît bel et bien, sauf qu'elle se referme tellement rapidement que vous n'avez pas le temps de la voir. Afin de pouvoir la contempler, nous allons donc mettre une pause dans le programme grâce à la fonction SDL_Delay :

void SDL_Delay(Uint32 ms);

Pour utiliser cette fonction, on lui passe la durée de la pause en ms (un millième de seconde). Ainsi, si l'on veut ajouter une pose de 3 secondes, le code sera le suivant :

SDL_Delay(3000);

Voici donc le code complet pour afficher une fenêtre redimensionnable de résolution 600x600 pendant 3 secondes :

#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[])
{
    SDL_Window* fenetre;  // Déclaration de la fenêtre

    if(SDL_Init(SDL_INIT_VIDEO) < 0)  // initialisation de la SDL
    {
       printf("Erreur d'initialisation de la SDL : %s", SDL_GetError());
       return EXIT_FAILURE;
    }

    fenetre = SDL_CreateWindow("Une fenetre SDL",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, 600, 600, SDL_WINDOW_RESIZABLE);  // Création de la fenêtre

    if (fenetre == NULL)  //gestion des erreurs
    {
        printf("Erreur lors de la creation d'une fenetre : %s", SDL_GetError());
        return EXIT_FAILURE;
    }

    SDL_Delay(3000);  //pause de 3 secondes

    SDL_DestroyWindow(fenetre);
    SDL_Quit();  //on quitte la SDL
    return 0;
}

Manipulation de la fenêtre modifier

Vous savez maintenant créer une fenêtre. Concrètement, vous n'avez pas besoin d'en savoir beaucoup plus. Si vous êtes un peu pressé, vous pouvez donc passer au chapitre suivant. Cependant, il existe quelques fonctions qui peuvent se montrer très utiles dans la manipulation des fenêtres. Vous trouverez ici une liste non exhaustive de ces fonctions.

Titre et icône modifier

Si vous voulez changer le titre de votre fenêtre après sa création ou bien ajouter une icône à votre fenêtre, vous êtes au bon endroit. Il est possible d'avoir besoin de changer le titre de sa fenêtre sans avoir à en créer une à nouveau, par exemple lorsque l'utilisateur vient d'enregistrer un fichier, le nom de la fenêtre comprend ensuite le nom du fichier ouvert (observez bien le nom de la fenêtre de votre logiciel de traitement de texte lorsque vous enregistrez un fichier que vous venez de créer). Voici les fonctions qui vont vous permettre d'ajouter un titre et une icône à votre fenêtre :

// le titre de la fenêtre est la chaîne de caractère passée en deuxième argument
void SDL_SetWindowTitle(SDL_Window* window, const char* title);

// ajoute une icône à la fenêtre
void SDL_SetWindowIcon(SDL_Window*  window, SDL_Surface* icon);

La fonction SDL_SetWindowIcon demande en argument une variable de type SDL_Surface*. Ne vous inquiétez pas, vous saurez utiliser ce type de variable lorsque vous aurez lu le chapitre sur les surfaces.

Si vous voulez récupérer le titre de la fenêtre, utilisez :

const char* SDL_GetWindowTitle(SDL_Window* window);

Position et taille modifier

Voici deux paramètres qui peuvent être très utiles à manipuler. Déterminer la taille et la position de la fenêtre peut être commode, par exemple, si vous souhaitez créer une interface comportant des fenêtres que l'on peut déplacer semblable à celle du Gimp (lorsqu'il n'est pas en mode fenêtre unique) pour ceux qui connaissent. En déterminant la position et la taille de ces fenêtres, vous pouvez coder une fonction pour les agencer automatiquement de manière pratique pour l'utilisateur.

N'oubliez pas toutefois que la SDL gère automatiquement le déplacement de la fenêtre et sa taille pour les fenêtres redimensionnables et que vous ne devez utiliser ces fonctions que dans les cas où la gestion automatique de la SDL ne suffit plus. Il est à noter également que le redimensionnement présenté fonctionne même avec les fenêtres créées sans le flag SDL_WINDOW_RESIZABLE. Voici donc SDL_SetWindowPosition et SDL_SetWindowSize qui vont vous permettre de changer la position et la taille de la fenêtre :

// déplace la fenêtre à la position (x;y) dans le repère présenté précédemment
void SDL_SetWindowPosition(SDL_Window* window , int x, int y);

// redimensionne la fenêtre qui sera ensuite large de w pixels et haute de h pixels
void SDL_SetWindowSize(SDL_Window* window , int w , int h);

Si vous voulez récupérer la taille ou la position d'une fenêtre, utilisez les fonctions suivantes :

// la position de la fenêtre sera placée dans les pointeurs x et y
void SDL_GetWindowPosition(SDL_Window* window, int* x, int* y);

// la taille de la fenêtre sera placée dans les pointeurs w et h
void SDL_GetWindowSize(SDL_Window* window, int* w, int* h);

Agrandir, réduire, restaurer, plein écran modifier

Normalement, vous n'avez pas à le faire manuellement : la SDL gère automatiquement les agrandissements, réductions et restaurations. Pourtant, il est possible que vous ayez à le faire. Si vous n'avez pas de but précis, n'utilisez pas ces fonctions et laissez la SDL gérer seule. Voici les trois fonctions qui permettent respectivement d'agrandir une fenêtre, la réduire et la restaurer. Elle s'utilisent de la même manière que SDL_Destroy.

void SDL_MaximizeWindow(SDL_Window* window);  // agrandissement de la fenêtre
void SDL_MinimizeWindow(SDL_Window* window);  // réduction de la fenêtre
void SDL_RestoreWindow(SDL_Window* window);  // restauration de la fenêtre

Si vous voulez programmer un jeu, vous aurez sûrement besoin de passer en mode plein écran à un moment ou à un autre. Voici la fonction activant ou désactivant le mode plein écran :

int SDL_SetWindowFullscreen(SDL_Window* window , SDL_bool fullscreen);

La fonction renvoie 0 en cas de succès et une valeur négative en cas d'erreur. Dans ce cas, vous savez gérer les erreurs...

Pour rentrer un SDL_Bool, vous pouvez :

  • utiliser SDL_TRUE (passage en mode plein écran) ou SDL_FALSE (fin du mode plein écran) pour envoyer un 0.
  • envoyer un 1 (passage en mode plein écran) ou un 0 (fin du mode plein écran) comme avec un booléen normal.

Pour passer en mode plein écran, on codera donc, en supposant qu'on a déjà déclaré la variable fenêtre et créé la fenêtre qui lui est associé :

if (SDL_SetWindowFullscreen(fenetre , SDL_TRUE) < 0)
{
        printf("Erreur lors du passage en mode plein ecran : %s", SDL_GetError());
        return EXIT_FAILURE;
}
// À partir d'ici, vous êtes en plein écran...

Luminosité modifier

La luminosité (brightness en anglais) d'une fenêtre est représentée par un nombre décimal (float) entre 0.0 et 1.0. La valeur 0.0 correspond à une fenêtre totalement noire et la valeur 1.0 est celle de la luminosité de votre écran. Vous pouvez donc ajuster la luminosité entre ces deux bornes à l'aide de cette fonction :

// définir la luminosité de l'écran
int SDL_SetWindowBrightness(SDL_Window* window, float luminosite);

Vous aurez probablement deviner que cette fonction renvoie une valeur négative en cas d'erreur et 0 si tout s'est bien passé...

Comme pour les fonctions ci-dessus, il existe également une fonction permettant de récupérer la luminosité actuelle de votre fenêtre. La voici :

// récupérer la luminosité
float SDL_GetWindowBrightness(SDL_Window* window);

Conclusion modifier

Nous arrivons à la fin du chapitre sur les fenêtres. Comme vous l'avez vu, l'utilisation des fenêtres est plutôt simple. Il est vrai que le nombre de fonction que nous avons vu ici est important mais vous vous rendrez compte qu'en pratique, on ne les utilise pas beaucoup. Il n'y a donc pas besoin de les apprendre par cœur, il suffit d'un petit rappel que vous trouverez dans ce récapitulatif des fonction vues dans ce livre.