5 votes

Changer la taille de la police de la console en Python de manière programmatique

J'ai trouvé le code ci-dessous qui est censé changer de manière programmatique la taille de la police de la console. Je suis sur Windows 10.

Cependant, peu importe les valeurs que j'ajuste, je ne semble pas avoir de contrôle sur la taille de la police, et aussi pour une raison quelconque, la console qui s'ouvre lorsque j'exécute ce script est très large.

Je n'ai aucune idée de comment fonctionne ctypes - tout ce que je veux, c'est modifier la taille de la police de la console depuis Python.

Des solutions réellement fonctionnelles?

import ctypes

LF_FACESIZE = 32
STD_OUTPUT_HANDLE = -11

class COORD(ctypes.Structure):
    _fields_ = [("X", ctypes.c_short), ("Y", ctypes.c_short)]

class CONSOLE_FONT_INFOEX(ctypes.Structure):
    _fields_ = [("cbSize", ctypes.c_ulong),
                ("nFont", ctypes.c_ulong),
                ("dwFontSize", COORD),
                ("FontFamily", ctypes.c_uint),
                ("FontWeight", ctypes.c_uint),
                ("FaceName", ctypes.c_wchar * LF_FACESIZE)]

font = CONSOLE_FONT_INFOEX()
font.cbSize = ctypes.sizeof(CONSOLE_FONT_INFOEX)
font.nFont = 12
font.dwFontSize.X = 11
font.dwFontSize.Y = 18
font.FontFamily = 54
font.FontWeight = 400
font.FaceName = "Lucida Console"

handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
ctypes.windll.kernel32.SetCurrentConsoleFontEx(
        handle, ctypes.c_long(False), ctypes.pointer(font))

print("Foo")

7voto

CristiFati Points 2058

Je veux commencer par souligner [SO]: Fonction C appelée depuis Python via ctypes renvoie une valeur incorrecte (réponse de @CristiFati) qui décrit un problème auquel la plupart des utilisateurs de CTypes sont confrontés.

La page d'accueil de CTypes (également répertoriée dans l'URL ci-dessus) : [Python.Docs]: ctypes - Une bibliothèque de fonctions étrangères pour Python

J'ai modifié votre code "un peu".

code.py:

#!/usr/bin/env python

import sys
from ctypes import POINTER, WinDLL, Structure, sizeof, byref
from ctypes.wintypes import BOOL, SHORT, WCHAR, UINT, ULONG, DWORD, HANDLE

LF_FACESIZE = 32
STD_OUTPUT_HANDLE = -11

class COORD(Structure):
    _fields_ = [
        ("X", SHORT),
        ("Y", SHORT),
    ]

class CONSOLE_FONT_INFOEX(Structure):
    _fields_ = [
        ("cbSize", ULONG),
        ("nFont", DWORD),
        ("dwFontSize", COORD),
        ("FontFamily", UINT),
        ("FontWeight", UINT),
        ("FaceName", WCHAR * LF_FACESIZE)
    ]

kernel32_dll = WinDLL("kernel32.dll")

get_last_error_func = kernel32_dll.GetLastError
get_last_error_func.argtypes = []
get_last_error_func.restype = DWORD

get_std_handle_func = kernel32_dll.GetStdHandle
get_std_handle_func.argtypes = [DWORD]
get_std_handle_func.restype = HANDLE

get_current_console_font_ex_func = kernel32_dll.GetCurrentConsoleFontEx
get_current_console_font_ex_func.argtypes = [HANDLE, BOOL, POINTER(CONSOLE_FONT_INFOEX)]
get_current_console_font_ex_func.restype = BOOL

set_current_console_font_ex_func = kernel32_dll.SetCurrentConsoleFontEx
set_current_console_font_ex_func.argtypes = [HANDLE, BOOL, POINTER(CONSOLE_FONT_INFOEX)]
set_current_console_font_ex_func.restype = BOOL

def main():
    # Get stdout handle
    stdout = get_std_handle_func(STD_OUTPUT_HANDLE)
    if not stdout:
        print("{:s} error: {:d}".format(get_std_handle_func.__name__, get_last_error_func()))
        return
    # Get current font characteristics
    font = CONSOLE_FONT_INFOEX()
    font.cbSize = sizeof(CONSOLE_FONT_INFOEX)
    res = get_current_console_font_ex_func(stdout, False, byref(font))
    if not res:
        print("{:s} error: {:d}".format(get_current_console_font_ex_func.__name__, get_last_error_func()))
        return
    # Display font information
    print("Information de la console pour {:}".format(font))
    for field_name, _ in font._fields_:
        field_data = getattr(font, field_name)
        if field_name == "dwFontSize":
            print("    {:s}: {{X: {:d}, Y: {:d}}}".format(field_name, field_data.X, field_data.Y))
        else:
            print("    {:s}: {:}".format(field_name, field_data))
    while 1:
        try:
            height = int(input("\nEntrez la hauteur de la police (invalide pour quitter) : "))
        except:
            break
        # Alter font height
        font.dwFontSize.X = 10  # Changer X n'a aucun effet (du moins sur mon ordinateur)
        font.dwFontSize.Y = height
        # Appliquer les changements
        res = set_current_console_font_ex_func(stdout, False, byref(font))
        if not res:
            print("{:s} error: {:d}".format(set_current_console_font_ex_func.__name__, get_last_error_func()))
            return
        print("OMG! La fenêtre a changé :)")
        # Get current font characteristics again and display font size
        res = get_current_console_font_ex_func(stdout, False, byref(font))
        if not res:
            print("{:s} error: {:d}".format(get_current_console_font_ex_func.__name__, get_last_error_func()))
            return
        print("\nNouvelles tailles    X: {:d}, Y: {:d}".format(font.dwFontSize.X, font.dwFontSize.Y))

if __name__ == "__main__":
    print("Python {:s} sur {:s}\n".format(sys.version, sys.platform))
    main()

Notes:

  • CTypes permet un accès de bas niveau similaire à C (seule la syntaxe est en Python)

  • Le code utilise [MS.Docs]: Fonction SetConsoleTextAttribute

  • Les constantes de ctypes.wintypes (qui réfèrent aux types standard de CTypes) sont utilisées (pour donner au code une saveur Win)

  • C'est très (presque douloureusement) long (aussi parce que j'ai ajouté une gestion d'erreurs appropriée)

  • Une alternative, comme suggéré dans l'une des réponses de [SO]: Changer la police de la console sous Windows (d'où vous avez copié le code), serait d'installer un module tiers (par exemple [GitHub]: mhammond/pywin32 - Python pour Windows (pywin32) Extensions qui est un wrapper Python sur les _WINAPI_s) qui nécessiterait moins de code à écrire car le pont entre Python et C serait déjà implémenté, et probablement la fonctionnalité ci-dessus pourrait être accomplie en seulement quelques lignes

  • Comme je l'ai commenté dans le code, définir COORD.X semble être ignoré. Mais il est automatiquement réglé lors du réglage de COORD.Y (à une valeur proche de COORD.Y // 2 - probablement pour préserver le rapport d'aspect). Sur mon ordinateur (ordinateur Win 10 pc064), la valeur par défaut est 16. Vous voudrez peut-être la réinitialiser à la fin, pour éviter de laisser la console dans un état "challengé" (apparemment, Win ajuste la taille de la fenêtre cmd, pour être (en quelque sorte) en sync avec la taille de la police) :

    Img0

0voto

Yinian Chin Points 88

Il ne s'agit pas d'un problème python pur, mais cela couvre l'API Windows.

Consultez la documentation de la structure CONSOLE_FONT_INFOEX. Il y a un membre COORD pour la largeur et la hauteur de chaque caractère.

Pour changer la taille de la police de la console, vous pouvez donner ces attributs comme valeur adéquate :

font.dwFontSize.X = 11
font.dwFontSize.Y = 18

Référence : Changer la police de la console dans Windows

0voto

DinosaurMoritz Points 55

Pour toute personne future qui souhaite utiliser la console comme méthode d'affichage d'images en noir et blanc ou simplement obtenir la taille de police la plus petite possible, voici le code de réponse modifié que j'ai utilisé. J'ai trouvé qu'une hauteur et une largeur de 2px étaient la meilleure taille la plus petite, mais soyez prudent, toutes les tailles déforment l'image, certaines plus que d'autres. En tant que police, j'utilise uniquement "rasterfont" qui est disponible. (Personnellement, j'ai eu d'énormes problèmes pour que cela fonctionne, je ne sais pas pourquoi cependant... et ce n'est PAS la même réponse que celle acceptée)

def changeFontSize(size=2): #Modifie la taille de la police à *size* pixels (en quelque sorte, mais pas vraiment. Vous devrez essayer pour voir si cela fonctionne à des fins)
    from ctypes import POINTER, WinDLL, Structure, sizeof, byref
    from ctypes.wintypes import BOOL, SHORT, WCHAR, UINT, ULONG, DWORD, HANDLE

    LF_FACESIZE = 32
    STD_OUTPUT_HANDLE = -11

    class COORD(Structure):
        _fields_ = [
            ("X", SHORT),
            ("Y", SHORT),
        ]

    class CONSOLE_FONT_INFOEX(Structure):
        _fields_ = [
            ("cbSize", ULONG),
            ("nFont", DWORD),
            ("dwFontSize", COORD),
            ("FontFamily", UINT),
            ("FontWeight", UINT),
            ("FaceName", WCHAR * LF_FACESIZE)
        ]

    kernel32_dll = WinDLL("kernel32.dll")

    get_last_error_func = kernel32_dll.GetLastError
    get_last_error_func.argtypes = []
    get_last_error_func.restype = DWORD

    get_std_handle_func = kernel32_dll.GetStdHandle
    get_std_handle_func.argtypes = [DWORD]
    get_std_handle_func.restype = HANDLE

    get_current_console_font_ex_func = kernel32_dll.GetCurrentConsoleFontEx
    get_current_console_font_ex_func.argtypes = [HANDLE, BOOL, POINTER(CONSOLE_FONT_INFOEX)]
    get_current_console_font_ex_func.restype = BOOL

    set_current_console_font_ex_func = kernel32_dll.SetCurrentConsoleFontEx
    set_current_console_font_ex_func.argtypes = [HANDLE, BOOL, POINTER(CONSOLE_FONT_INFOEX)]
    set_current_console_font_ex_func.restype = BOOL

    stdout = get_std_handle_func(STD_OUTPUT_HANDLE)
    font = CONSOLE_FONT_INFOEX()
    font.cbSize = sizeof(CONSOLE_FONT_INFOEX)

    font.dwFontSize.X = size
    font.dwFontSize.Y = size

    set_current_console_font_ex_func(stdout, False, byref(font))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X