none
Padding en WinForm RRS feed

  • Question

  • Bonjour tout le monde,

    Je cherche à créer une marge intérieure, notamment à droite, dans un TextBox sous WinForm.

    La documentation dit que c'est possible :

    https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.textboxbase.padding?view=netframework-4.8#System_Windows_Forms_TextBoxBase_Padding

    Or, quand j'essaie, je n'y ai accès qu'en lecture, du coup je me demande pourquoi on précise {get; set;}

    Padding : Impossible de modifier la valeur de retour de 'Control.Padding' car il ne s'agit pas d'une variable

    En fait en creusant un peu je peux changer le padding pour les quatre bords à la fois :

    textBox1.Padding = new Padding(10);

    Je me demande d'ailleurs si c'est la bonne syntaxe, car même en mettant 1000 je ne vois pas le résultat à l'œil nu. Ah non j'y suis : j'ai mis ça dans le constructeur du formulaire, ça doit être ça l'erreur.

    Ah non j'ai lu trop vite. La page que j'ai mentionnée commence  par "This property is not relevant for this control".

    Donc on ne se fait pas jeter à l'exécution, mais ça ne modifie rien.

    Est-ce que la réponse, c'est juste "Peut pô !" ?


    • Modifié Gloops samedi 16 novembre 2019 13:12
    samedi 16 novembre 2019 12:30

Réponses

  • On peut utiliser EM_SETRECT (doit être Multiline comme indiqué)

    Par ex, une marge de 20 à droite :

    RECT rc = new RECT(0, 0, textBox1.ClientSize.Width - 20, textBox1.ClientSize.Height);
    SendMessage(textBox1.Handle, EM_SETRECT, 0, ref rc);

    Declarations :

    private const int EM_SETRECT = 0xB3;
    
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
        public RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }
    }
    
    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, ref RECT rect);

    • Marqué comme réponse Gloops samedi 16 novembre 2019 18:37
    samedi 16 novembre 2019 15:18

Toutes les réponses

  • On peut utiliser EM_SETRECT (doit être Multiline comme indiqué)

    Par ex, une marge de 20 à droite :

    RECT rc = new RECT(0, 0, textBox1.ClientSize.Width - 20, textBox1.ClientSize.Height);
    SendMessage(textBox1.Handle, EM_SETRECT, 0, ref rc);

    Declarations :

    private const int EM_SETRECT = 0xB3;
    
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
        public RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }
    }
    
    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, ref RECT rect);

    • Marqué comme réponse Gloops samedi 16 novembre 2019 18:37
    samedi 16 novembre 2019 15:18
  • OK, merci.

    On dirait que je dois réviser un petit coup InteropServices (plus avec mes souvenirs qu'avec ce qu'il reste de doc, d'ailleurs), car le Form_Load a beau être déclaré et associé à la bonne propriété, je charge le formulaire sans voir le point d'arrêt au début.

    Du coup tout ce que j'ai réussi à faire, c'est rendre tous les contrôles invisibles.

    ***

    En remettant les choses un peu dans l'ordre ils reviennent.

    En tête du module Form1.cs :

    using System.Runtime.InteropServices;

    Dans la classe Form1, au-dessus du constructeur :

    		private const int EM_SETRECT = 0xB3;
    
    		[StructLayout(LayoutKind.Sequential)]
    		public struct RECT
    		{
    			public int Left;
    			public int Top;
    			public int Right;
    			public int Bottom;
    			public RECT(int left, int top, int right, int bottom)
    			{
    				Left = left;
    				Top = top;
    				Right = right;
    				Bottom = bottom;
    			}
    		}
    
    		[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    		private static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, ref RECT rect);

    Et en double-cliquant sur le formulaire je fais apparaître Form1_Load, et je mets dedans :

    		private void Form1_Load(object sender, EventArgs e)
    		{
    			RECT rc = new RECT(0, 0, textBox1.ClientSize.Width - 20, textBox1.ClientSize.Height);
    
    			SendMessage(textBox1.Handle,			EM_SETRECT, 0, ref rc);
    		}

    C'est moins le bazar que tout-à-l'heure, les contrôles sont revenus à l'affichage, si je mets un point d'arrêt dans le Form1_Load j'y passe, mais je ne vois pas de changement du côté du Padding ...

    Me serais-je trompé quelque part ?

    Je me rappelle qu'il est plus orthodoxe d'écrire un autre module pour y mettre l'appel à l'API, si je me rappelle bien ça devrait quand même fonctionner ?

    ***

    Ah j'y suis. J'ai tellement mis le bazar en collant du code à l'aveuglette, qu'il a été plus simple de commencer un nouveau projet, et là j'ai oublié que le contrôle devait être MultiLine pour que ça marche.

    Une fois que c'est fait, en effet il y a une marge à droite.

    À noter qu'il peut être utile d'initialiser la propriété MaxLength, si on n'affiche qu'une ligne, et que le contrôle doit être multiligne pour implémenter le Padding. Sinon, si on introduit trop de chiffres, ils vont s'afficher sur plusieurs lignes, et comme on n'en affiche qu'une, il y a de quoi dérouter l'utilisateur.

    La mise en œuvre a été laborieuse, mais le conseil était le bon, merci.



    • Modifié Gloops samedi 16 novembre 2019 18:48
    samedi 16 novembre 2019 16:30