IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

Comment activer la propriété KeyPreview d'un TForm dont je n'ai que le handle ?


Sujet :

Composants VCL Delphi

  1. #1
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 433
    Billets dans le blog
    1
    Par défaut Comment activer la propriété KeyPreview d'un TForm dont je n'ai que le handle ?
    Bonjour,

    Je suis sous W11 avec Delphi 6 Personal Edition.

    J'ai créé un contrôle dérive de TScrollBox dans lequel j'ai placé un TImage. Le tout est créé dynamiquement, par programme.
    Ca marche très bien.

    Mais maintenant, je veux récupérer les touches directionnelles (avec/sans SHIFT) frappées sur ce TImage (qui remplit tout l'espace de la ScrollBox.
    Je récupère le clic sans problème, mais j'ai compris qu'il n'y a pas de OnKeyDown event pour un TImage car ce dernier ne descend pas de TWinControl.

    Alors, j'ai essayé d'intercepter OnKeyDown sur la ScrollBox. Rien n'est intercepté pour les touches du clavier, seul le clic gauche déclenche cet évènement.

    Alors, j'ai vu qu'il y a une propriété KeyPreview pour la Form qui contient ma ScrollBox.
    Or, pour accéder la Form, je ne connais que son handle, je n'ai pas accès à l'objet proprement-dit.

    Question: comment activer KeyPreview sur une TForm par son handle ?

    Question subsidiaire:
    serait-ce possible d'intercepter un message Windows indiquant la frappe d'une des touches directionnelles, éventuellement avec les attributs TShiftState ?

    L'ensemble du code (création et gestion de la TScrollBox et du TImage) est placé dans une DLL, ainsi que devra l'être le code d'interception des touches.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 292
    Par défaut
    La TForm Parent est affectée via un SetParent de l'API Windows, est-ce vraiment une TForm ou un Handle venant d'un EXE Delphi dans ta DLL Delphi qui expose quelques foncions pour gérer le ScrollBox ?
    Si c'est un EXE développé dans un autre langage, c'est n'est pas une TForm.

    Si le TImage remplit tout l'espace de la ScrollBox, il n'y a donc pas de barre de scrolling ?
    Pourquoi ne pas utiliser un TPanel sans bordure comme container parent du TImage ?


    Enfin si tu es l'auteur de la TForm, tu peux fournir une fonction de CallBack pour que la TForm notifie depuis son OnKeyDown + KeyPreview la DLL
    Si tu n'es pas l'auteur de la TForm appelante, voir les possibilités pour que tu puisse depuis la DLL faire un contournement de la WndProc voir carrément un Hook



    A quoi c'est l'image, est-ce un fond du scrollBox, dans ce cas, tu peux modifier le WM_PAINT pour dessiner ton propre fond, voir TSLTBackgroundWindowHook
    Aide via F1 - Utilisez l'I.A. - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité ! Sachez-le : l'IA remplace la très grande majorité des développeurs, pas seulement les ignares ...

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 433
    Billets dans le blog
    1
    Par défaut
    La DLL qui gère tout cela, est appelée par un programme en Panoramic et qui, lui, est réalisé en Delphi. Pas la version 6 PE, mais Delphi tout de même. Et si j'utilise le API retournant le ClassName pour le handle, c'est bien 'TForm' qui apparaît.

    La ScrollBox peut avoir n'importe quelle taille, mais le TImage placée à l'intérieur est bien plus grand. positionné en (0,0) de la ScrollBox, il remplit tout l'espace d'affichage visible, mais évidemment les ascenseurs sont là pour déplacer la fenêtre de vision sur le TImage. De plus, j'ai fait de sorte qu'on puisse "tirer" l'image avec la souris, comme alternative à l'utilisation des ScrollBars.
    J'aimerais savoit s'il y a une API permettant de gérer cette propriété de TForm, ou un code message pour SendMessage, pour positionner la propriété KeyPreview de la form. Je n'ai pas réussi à trouver ça...

  4. #4
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 433
    Billets dans le blog
    1
    Par défaut
    Je viens de découvrir ceci:
    https://www.thoughtco.com/intercepti...-input-1058465

    Apparemment, c'est précisément mon cas: intercepter des frappes au clavier pour un TImage. Je vais explorer cela...

  5. #5
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 433
    Billets dans le blog
    1
    Par défaut
    YES !

    CA marche. Je peux intercepter les touches directionnelles et les traiter selon le sens que je veux leur donner, sans déranger le reste du fonctionnement.

    Dans KeyboardHookProc, je renvoie 1 si j'ai traité une touche, ou 0 sinon.

    Mon problème est résolu.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 292
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    un programme en Panoramic et qui, lui, est réalisé en Delphi. Pas la version 6 PE, mais Delphi tout de même. Et si j'utilise le API retournant le ClassName pour le handle, c'est bien 'TForm' qui apparaît.
    Cela revient au fait que tu n'es pas l'auteur du programme et sans parler que la TForm n'est pas la même, déjà entre une DLL et un EXE dans le même Delphi, sans BPL, les adresses des classes ne sont pas compatible, entre deux version de Delphi c'est même dans certains écarts de version totalement différents.
    Donc tu as tranché et choisi la méthode appropriée que j'avais évoqué :

    Citation Envoyé par ShaiLeTroll Voir le message
    Si tu n'es pas l'auteur de la TForm appelante, voir les possibilités pour que tu puisse depuis la DLL faire un contournement de la WndProc voir carrément un Hook
    Je n'ai pas du en mettre un en place depuis 20 ans, le premier c'était en 2002, pour récupérer les saisies d'un lecteur de code barre sans être tributaire du focus dans le TEdit (le programme étant lancé dans un coin, personne pour le surveiller et voir le que TEdit passait en rouge )

    Par contre, l'exemple que tu as fourni, cela montre le Hook sans DLL, comme tu es déjà dans une DLL ça doit le faire, mais en prod, je l'ai toujours fait avec une DLL jamais depuis directement l'exe.
    Aide via F1 - Utilisez l'I.A. - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité ! Sachez-le : l'IA remplace la très grande majorité des développeurs, pas seulement les ignares ...

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Invité de passage
    Homme Profil pro
    autre
    Inscrit en
    Septembre 2026
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Septembre 2026
    Messages : 2
    Par défaut
    Mais maintenant, je veux récupérer les touches directionnelles (avec/sans SHIFT) frappées sur ce TImage (qui remplit tout l'espace de la ScrollBox.
    Je récupère le clic sans problème, mais j'ai compris qu'il n'y a pas de OnKeyDown event pour un TImage car ce dernier ne descend pas de TWinControl.
    C'est tout a fait faisable avec un TScrollBox sans hook.
    Dans l'evenement Onclick de l image ajoute
    ScrollBox1.SetFocus;

    et après la création du ScrollBox affecte l'evenment OnKeyDown ou KeyPress:
    déclaration pour accéder au OnKeyPress encore protégé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    type Acc = class(TWincontrol);
     ... 
     Acc(Scrollbox1).OnKeyDown := BoxKeyDown;
    concernant les touches directionnelles je pense que tu as déjà posé une question similaire regarde dans tes anciennes discutions

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 292
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Alors, j'ai essayé d'intercepter OnKeyDown sur la ScrollBox. Rien n'est intercepté pour les touches du clavier, seul le clic gauche déclenche cet évènement.
    Citation Envoyé par Informt2026 Voir le message
    et après la création du ScrollBox affecte l'evenment OnKeyDown ou KeyPress:
    déclaration pour accéder au OnKeyPress encore protégé
    Pensant que cela a été fait, je n'avais pas cherché, mais la formule "seul le clic gauche déclenche cet évènement", me fait douter, une confusion avec OnMouseDown ???


    Dans un EXE direct, cela fonctionne que très partiellement dans un EXE D10 Seattle
    Il faut vérifier en D6 dans une DLL qui en plus d'être ancien est un contexte différent d'un EXE Delphi (rien que la gestion du SetParent par Handle, cela change le propagation de certains messages et peut perturbé le Focus, je l'ai massivement expérimenté en C++Builder qu'un EXE qui dans une TForm ancre via SetParent, un Panel, un ScrollBox issu d'une DLL, le contenu du ScrollBox venant d'une seconde DLL, il y a de quoi s'amuser )

    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
    procedure TForm1.BoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    begin
      case Key of
        VK_UP: ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 5; // Non capturé
        VK_DOWN: ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 5; // Non capturé
        VK_PRIOR : ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 20; // OK
        VK_NEXT : ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 20; // OK
        VK_LEFT: ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position - 5; // Non capturé
        VK_RIGHT: ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position + 5; // Non capturé
      end;
    end;
     
    type Acc = class(TWincontrol);
     
    procedure TForm1.Image1Click(Sender: TObject);
    begin
      ScrollBox1.SetFocus();
      Acc(Scrollbox1).OnKeyDown := BoxKeyDown;
    end;
    Aide via F1 - Utilisez l'I.A. - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité ! Sachez-le : l'IA remplace la très grande majorité des développeurs, pas seulement les ignares ...

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 292
    Par défaut
    Voici une variante fonctionnelle sous D10 Seattle en utilisant WM_GETDLGCODE donnant accès à DLGC_WANTARROWS

    A lire : Flèche droite clavier D6 et Windows 11 64bits


    J'ai ajouté Button et Edit pour vérifier que le clavier se comporte correctement à l'intérieur (quand ils ont le focus) et inversement quand c'est le ScrollBox qui a le focus, qu'il ne fasse pas de navigation entre contrôle mais bien un déplacement du scroll
    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
    unit Unit1;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
      Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.GIFImg, Vcl.ExtCtrls,
      Vcl.StdCtrls;
     
    type
      TScrollBox = class(Vcl.Forms.TScrollBox)
      protected
        procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
      end;
     
      TForm1 = class(TForm)
        ScrollBox1: TScrollBox;
        Image1: TImage;
        Button1: TButton;
        Edit1: TEdit;
        Button2: TButton;
        Edit2: TEdit;
        procedure FormCreate(Sender: TObject);
        procedure Image1Click(Sender: TObject);
      private
        procedure BoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TScrollBox.WMGetDlgCode(var Msg: TWMGetDlgCode);
    begin
      inherited;
      Msg.Result := Msg.Result or DLGC_WANTARROWS;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      ScrollBox1.TabStop := True; // TAB permet de naviguer entre le ScrollBox et aussi les Button\Edit (eux c'est True par défaut contrairement au ScrollBox)
      ScrollBox1.OnKeyDown := BoxKeyDown;
    end;
     
    procedure TForm1.Image1Click(Sender: TObject);
    begin
      ScrollBox1.SetFocus();
    end;
     
    procedure TForm1.BoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    begin
      case Key of
        VK_UP:    ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 5;
        VK_DOWN:  ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 5;
        VK_PRIOR: ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 20;
        VK_NEXT:  ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 20;
        VK_LEFT:  ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position - 5;
        VK_RIGHT: ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position + 5;
      end;
    end;
     
    end.
    Code dfm : 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
    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 299
      ClientWidth = 635
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object ScrollBox1: TScrollBox
        Left = 0
        Top = 0
        Width = 635
        Height = 299
        Align = alClient
        TabOrder = 0
        object Image1: TImage
          Left = 3
          Top = 3
          Width = 1280
          Height = 1532
          AutoSize = True
          OnClick = Image1Click
        end
        object Button1: TButton
          Left = 88
          Top = 104
          Width = 75
          Height = 25
          Caption = 'Button1'
          TabOrder = 0
        end
        object Edit1: TEdit
          Left = 192
          Top = 106
          Width = 121
          Height = 21
          TabOrder = 1
          Text = 'Edit1'
        end
        object Button2: TButton
          Left = 88
          Top = 135
          Width = 75
          Height = 25
          Caption = 'Button2'
          TabOrder = 2
        end
        object Edit2: TEdit
          Left = 192
          Top = 133
          Width = 121
          Height = 21
          TabOrder = 3
          Text = 'Edit2'
        end
      end
    end
    Aide via F1 - Utilisez l'I.A. - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité ! Sachez-le : l'IA remplace la très grande majorité des développeurs, pas seulement les ignares ...

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Invité de passage
    Homme Profil pro
    autre
    Inscrit en
    Septembre 2026
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Septembre 2026
    Messages : 2
    Par défaut
    Bonjour,

    Juste une remarque sur TabStop elle ne fonctionne qu'avec les contrôles ayant un parent VCL valide et figurent dans le liste interne Controls, si le ScrollBax est placé par Windows.SetParent, TabStop n'a aucun effet comme pas mal d'autres fonctionnalités

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 17
    Dernier message: 08/06/2005, 14h52
  2. [TP] Comment activer la souris dans l'éditeur ?
    Par hannon dans le forum Turbo Pascal
    Réponses: 2
    Dernier message: 27/03/2005, 00h29
  3. comment activer l'aide en ligne
    Par saibe dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 11/01/2005, 14h23
  4. Réponses: 9
    Dernier message: 15/09/2004, 21h35
  5. Réponses: 2
    Dernier message: 12/02/2004, 13h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo