Traduction du NVDA 2011.1 Developer Guide
Introduction
Ce guide fournit des informations pour les nouveaux développeurs qui souhaitent développer des composants pour NVDA. Notez que ce n'est qu'une introduction. Les développeurs devraient consulter la documentation du code pour avoir une information plus complète.
Remarque à propos de Python
NVDA et ses composants sont principalement écrits en langage de programmation Python. Le but de ce guide n'est pas de vous apprendre Python, bien des exemples sont fournis tout au long de ce guide, ils vous aideront à vous familiariser avec la syntaxe de Python. La documentation et d'autres ressources liées au langage Python se trouve sur le site http://www.python.org/
Greffons logiciels
Aperçu
Les plugins vous permettent de personnaliser la façon dont se comporte NVDA en général ou dans une application particulière. Ils sont capables de :
- Répondre à des évènements particuliers tels que la prise de focus ou les changements dans les propriétés des objets, par exemple quand un contrôle change de nom.
- Mettre en œuvre les commandes qui sont liées à des touches spécifiques ou d'autres entrées.
- Personnaliser le comportement ou mettre en œuvre des fonctionnalités supplémentaires pour des contrôles spécifiques.
- Personnaliser ou ajouter un nouveau support pour le contenu textuel et les documents complexes.
Types de greffons
Il existe deux types de greffons :
- Les Modules App : code spécifique à une application particulière,
le module App reçoit tous les événements d'une application précise, même si ce n'est pas l'application courante. Lorsque l'application est active, toutes les commandes que le module App a associé aux touches ou à une autre entrée peuvent être exécutées par l'utilisateur.
- Plugins Globaux : le code Global de NVDA, C'est à dire utilisé dans toutes les applications.
Les plugins Globaux contiennent tous les événements liés à tous les contrôles du système d'exploitation. Toutes les commandes associées à un Plugin global peuvent être exécutées par l'utilisateur, où qu'elles soient dans le système d'exploitation, indépendamment de l'application.
Si vous souhaitez améliorer l'accès de NVDA à une application donnée, il est plus probable que vous vouliez écrire un module App.
En revanche, si vous souhaitez ajouter des fonctionnalités à NVDA en général (par exemple un script donnant la puissance instantanée du réseau sans fil quelque soit l'application), un greffon global est ce qu'il vous faut.
Tous deux, modules et Plugins App Globaux se présente de la même manière. Ce sont des fichiers source Python (avec une extension .Py), ils définissent tous deux une classe spéciale contenant tous les événements, les scripts et les bindings, et ils peuvent définir des classes personnalisées pour les accès, le contenu du texte et les documents complexes. Cependant, ils diffèrent à certains égards.
Les quelques sections suivantes traitent séparément les modules App et les greffons globaux. Après cela, la discussion est à nouveau plus générale.
Les bases d'un module App
Les fichiers des modules App ont l'extension .Py, et portent le même nom que l'exécutable principal de l'application pour laquelle vous souhaitez les utiliser. Par exemple, un module d'application pour Notepad seraient appelés notepad.py, puisque l'exécutable principal de Notepad est appelé notepad.exe.
Les fichiers du module App doivent être placés dans le sous-répertoire appModules du répertoire configuration de NVDA de l'utilisateur. Pour plus d'informations sur la localisation du répertoire de configuration de l'utilisateur, consultez, s'il-vous-plaît, le guide utilisateur de NVDA.
Les Modules App doivent définir une classe appelée AppModule, qui hérite de appModuleHandler.AppModule. Cette classe peut alors définir des événements et des méthodes pour les scripts, des gesture bindings et d'autres codes. Tout cela sera abordé en profondeur plus tard.
NVDA charge un module App pour une application dès qu'il détecte que l'application est exécutée. Le module App est déchargé une fois l'application fermée ou lorsqu'on quitte NVDA.
Exemple 1: Un module App qui génère un Bip lors des événements de changement du Focus
L'exemple suivant de module App, fait biper NVDA chaque fois que le focus change dans l'application Notepad. Cet exemple vous montre le schéma de base d'un module app.
Dans un nouveau fichier texte appelé notepad.py, qui doit être sauvegardé dans le répertoire AppModules, copiez et collez le code entre les marqueurs de début et de fin, sans les inclure. Faite très attention de garder tous les tabulations et les espaces intacts.
Une fois enregistré à l'emplacement correct, vous pouvez redémarrer NVDA ou choisir de Recharger les Plugins. Vous trouverez ceci dans le sous-menu Outils du menu NVDA.
Pour finir, ouvrez le Bloc-notes et déplacer le focus dans l'application. Par exemple déplacer-vous le long de la barre de menu, ouvrez certaines boîtes de dialogue, etc. Vous devriez entendre des bips chaque fois que le focus change. Notez cependant que si vous vous déplacez en dehors de Notepad - par exemple, dans l'Explorateur Windows - vous ne devriez pas entendre de bips.
--- start --- # Notepad App Module for NVDA # Developer guide example 1 import appModuleHandler class AppModule(appModuleHandler.AppModule): def event_gainFocus(self, obj, nextHandler): import tones tones.beep(550, 50) nextHandler() --- end ---
Le fichier de Ce Module App commence par deux lignes de commentaires, qui décrivent à quoi le fichier est destiné.
Il importe alors le module appModuleHandler, de sorte que le module App a alors accès à la classe AppModule base.
Ensuite, il définit une classe appelée AppModule, qui est héritée de appModuleHandler.AppModule.
A l'intérieur de cette classe, il définit un ou plusieurs événements, des scripts ou des gesture bindings. Dans cet exemple, il définit une méthode pour l'évènement recevoir le Focus (event_gainFocus), qui émet un bip court à chaque fois qu'il est exécuté. La mise en oevre de cet évènement n'est pas ce qui importe pour cet exemple ; la partie la plus importante est la classe elle-même. Les événements seront traîtés plus en détail ultérieurement.
De la même façon que pour d'autres exemples de ce guide, n'oubliez pas de supprimer le module Application créé lorsque vous avez terminé les essais ; puis redémarrez NVDA ou bien recharger les plugins, afin que la fonctionnalité d'origine soit restaurée.
Les bases d'un plugin global
Les fichiers de Plugin globaux ont une extension .Py, et devrait avoir un nom court et unique identifiant ce qu'ils font.
Les Fichiers de Plugin globaux doivent être placés dans le sous-répertoire globalPlugins du répertoire configuration de l'utilisateur du NVDA de l'utilisateur. Pour plus d'informations sur la localisation du répertoire de configuration de l'utilisateur, consulter, s'il vous plaît, le guide utilisateur de NVDA.
Les plugins globaux doivent définir une classe appelée GlobalPlugin, qui hérite de globalPluginHandler.GlobalPlugin. Cette classe peut alors définir des évènements et des méthodes de script, des gesture bindings et d'autres codes. Tout cela sera abordé plus précisément par la suite.
NVDA charge tous les plugins globaux au démarrage, et les décharge à la fermeture.
Exemple 2: un Plugin global qui Fourni un script annonçant la version de NVDA
L'exemple suivant de Plugin global vous permet d'appuyer sur NVDA + Maj + V depuis n'importe où dans le système d'exploitation pour connaitre la version de NVDA. Cet exemple est seulement là pour vous montrer la structure de base d'un greffon global.
Dans un nouveau fichier texte nommé example2.py, qui doit être sauvegardé dans le répertoire globalPlugins, copiez et collez le code entre les marqueurs de début et de fin, sans les inclure. Faite très attention de garder tout les tabulations et les espaces intacts.
Une fois enregistré à l'emplacement correct, vous pouvez redémarrer NVDA ou choisir de Recharger les Plugins. Vous trouverez ceci dans le sous-menu Outils du menu NVDA.
Vous pouvez maintenant, de n'importe où, appuyer sur les touches NVDA + Maj + V pour entendre ou lire en braille la version de NVDA.
--- start --- # Version announcement plugin for NVDA # Developer guide example 2 import globalPluginHandler import ui import versionInfo class GlobalPlugin(globalPluginHandler.GlobalPlugin): def script_announceNVDAVersion(self, gesture): ui.message(versionInfo.version) __gestures={ "kb:NVDA+shift+v": "announceNVDAVersion", } --- end ---
Le fichier de ce Plugin global commence par deux lignes de commentaires, qui décrivent à quoi ce fichier doit servir.
Il importe alors le module globalPluginHandler, afin que le plugin global ai accès à la classe GlobalPlugin de base.
Il importe également quelques autres modules, à savoir ui et VERSIONINFO, dont un de ses plugins spécifiques est nécessaire pour effectuer l'ensemble des actions requises afin d'annoncer la version.
Puis il définit une classe appelée GlobalPlugin, qui est héritée de globalPluginHandler.GlobalPlugin.
x A l'intérieur de cette classe, il définit un ou plusieurs événements, des scripts ou des gesture bindings. Dans cet exemple, il définit une méthode de script qui effectue l'annonce de version, et lie NVDA + Maj + V a ce script. Toutefois, les détails du script et de son affectation importent peut dans cet exemple. La partie la plus importante est la classe elle-même.
De la même façon que pour d'autres exemples de ce guide, quand vous aurez terminé les essais n'oubliez pas de supprimer le plugin global que vous avez créé ; puis redémarrez NVDA ou bien recharger les plugins, afin que la fonctionnalité d'origine soit restaurée.
Objets NVDA
NVDA représente les contrôles et d'autres éléments d'interface graphique sous forme d'objets NVDA. Ces objets contiennent des propriétés NVDA standardisées, comme le nom, le rôle, la valeur, les Etats et la description, ce qui permet à d'autres parties de NVDA de demander ou d'afficher des informations à propos d'un contrôle d'une manière générale. Par exemple, le bouton OK d'une boîte de dialogue serait représenté par un objet NVDA avec un nom "OK" et un rôle de bouton. De même, une case à cocher avec une étiquette J'accepte aurait le nom J'accepte, un rôle de case à cocher et si elle est cochée, un état coché.
Comme il y a beaucoup de différents Toolkits GUI, plateformes et API d'accessibilités, les objets NVDA font abstraction de ces différences dans un formulaire standard, utilisable par NVDA, indépendamment du tooltip ou de l'API avec lequel le contrôle est effectué. Par exemple, le bouton Ok, dont nous venons de discuter, pourrait être un widget dans une application Java, un objet MSAA, un objet ou un élément IAccessible2 UI Automation.
Les objets NVDA ont de nombreuses propriétés, parmi les plus utiles on a :
- name (nom): l'étiquette du contrôle.
- rôle (rôle): l'une des constantes ROLE_* du module controlTypes de NVDA.
Button, dialog, editableText, window et checkbox sont des exemples de rôles.
- states (Etats): une série de 0 ou plusieurs des constantes STATE_* à du module NVDA controlTypes.
Focusable, focused, selected, selectable, expanded, collapsed et checked sont quelques exemples d'états.
- value (valeur): la valeur du contrôle ; par exemple le pourcentage d'une barre de défilement ou l'item sélectionné pour une liste déroulante.
- description (Description): une phrase ou deux décrivant ce que le contrôle fait (en générale identique à son info-bulle).
- location (Emplacement): la position de l'objet en coordonnées écran (gauche, en haut, la largeur et la hauteur).
- parent (parent): l'objet parent de cet objet.
Par exemple, le parent de l'objet élément de liste serait la liste qui le contient.
- next (suivant): l'objet juste après celui-ci au même niveau d'un ordre logique.
Par exemple, l'objet le plus susceptible de suivre un objet item du menu NVDA est un autre item du même menu.
- previous (précédent): comme next, mais dans l'ordre inverse.
- firstChild (premier enfant): l'objet premier enfant direct de cet objet.
Par exemple, le premier enfant d'une liste serait le premier élément de la liste.
- lastChild (dernier enfant): le dernier enfant direct de cet objet.
- children (enfants): une liste de tous les enfents dirrects de cet objet; par exemple tous les items du menu dans un menu. -
Il y a aussi quelques propriétés de navigation simplifiée tels que simpleParent, simpleNext, simpleFirstChild et simpleLastChild. Ce sont respectivement les mêmes propriétés de navigation que celle décrites ci-dessus, mais NVDA filtre les objets inutiles. Ces propriétés sont utilisées lorsque NVDA est en mode navigation simplifié, ce qui est le mode par défaut. Ces propriétés simples peuvent être plus faciles à utiliser, mais les propriétés de navigation réelle reflètent mieux la structure sous-jacente du system d'exploitation.
Lors du développement des plugins, généralement, il n'est pas important que le toolkit ou l'API rétrodiffuse un objet NVDA, puisque le plugin va la plus pare du temps n'accéder qu'aux propriétés standard, telles que le nom, le rôle et la valeur.
Cependant, comme les plugins deviennent plus avancés, il est certainement possible de creuser davantage sur les Objets NVDA pour trouver des informations sur les boîte à outils ou API spécifiques si nécessaire.
When developing plugins, most of the time, it is not important what toolkit or API backs an NVDA Object, as the plugin will usually only access standard properties such as name, role and value. However, as plugins become more advanced, it is certainly possible to delve deeper into NVDA Objects to find out toolkit or API specific information if required.
Les Plugins utilisent des objets NVDA pour trois raisons précises:
- La plupart des événements que les plugins reçoivent prennent en argument l'objet NVDA sur lequel l'événement s'est produit.
Par exemple, event_gainFocus prend l'objet NVDA qui représente le gain du focus par le contrôle.
- Les scripts, les événements ou d'autres codes peuvent aller chercher des objets d'intérêt tels que les objets NVDA en focus, les objets de navigation courante de NVDA, ou peut-être l'objet NVDA du bureau.
Le code peut alors récupérer des informations de cet objet ou peut-être même d'un objet liés à celui-ci (par exemple, son parent, le premier enfant, etc.)
- le plugin peut définir ses propres classes d'objets NVDA, elles seront utilisées pour contenir un contrôle spécifique afin de lui donner des fonctionnalités supplémentaires, muter ses propriétés, etc.
Tout comme les modules et plugins App globaux, les Objets NVDA peuvent également définir des événements, des scripts et des gesture bindings.
Scripts et Gesture Bindings
Les Modules App, les Plugins globaux et les Objets NVDA peuvent définir des méthodes spéciales qui peuvent être liés à un raccourci spécifique, ainsi, une touche NVDA se réfère à ces méthodes de scripts.
Un script est une méthode standard d'instance de Python possédant un nom commençant par "script_", par exemple "script_sayDateTime".
Une méthode de script prend deux arguments:
- self (auto): une référence au module App, au plugin global ou a une instance de l'objet NVDA du script qui a été appelé.
- gesture: un objet Input Gesture, qui représente l'entrée qui a déclenché le script à exécuter.
De même que la méthode de script, une certaine forme de gesture binding doit être définie, de sorte que NVDA sait quelle entrée doit exécuter le script.
Pour affecter la gesture à un script, un dictionnaire Python spécial "__gestures" peut être défini comme une variable de classe dans le module App, le Plugin global ou l'objet NVDA. Ces dictionnaires doivent contenir des chaînes d'identification de gesture pointant vers le nom du script demandé, sans le préfixe
Il ya des manières plus avancées de faire des gestures binding dans un mode plus dynamique, même si le dictionnaire __gestures est le plus simple.
Une chaîne d'identification de gesture est une chaîne simple représentant un raccourci. Il se compose d'un code de deux lettres en format caractères donnant la source de l'entrée, une partie facultative entre parenthèses, deux points (:) et un ou plusieurs noms séparés par un signe plus (+) désignant des touches réelles ou valeurs d'entrée.
Quelques exemples de chaînes d'identification de gesture sont:
- "kb:NVDA+shift+v"
- "br(freedomScientific):leftWizWheelUp"
- "kb(laptop):NVDA+t"
Actuellement, les seules sources des entrées de NVDA sont:
- kb: keyboard input (saisie au clavier)
- br: braille input (entrée braille)
Quand NVDA reçoit une entrée, il cherche les gestures bindings correspondantes dans un ordre précis. Une fois qu'une gesture binding est trouvée, le script est exécuté et aucune des bindings supplémentaires ne sont utilisées, Nore c'est que certain gesture sont transmis automatiquement au système d'exploitation.
L'ordre de recherche des gestures bindings est:
- les plugins globaux Chargés
- les Module App de l'application active
- l'arborescence d'interception de l'objet NVDA sous le focus si cas échéant, par exemple un virtualBuffer
- l'Objet NVDA sous le focus
- Commandes globales (intégrées dans les commandes comme quitter NVDA, les commandes d'objets de navigation, etc.)
Exemple 3: un Plugin global pour trouver la classe de fenêtre et le contrôle d'ID
Le plugin global ci-dessous, vous permet d'annoncer la window classe du focus actuelle en appuyant sur touche NVDA + Flèche gauche et l'ID du contrôle sous le focus dans la fenêtre avec touche NVDA + flèche droite. Cet exemple vous montre comment définir un ou plusieurs scripts avec gesture bindings dans une classe comme un module App, un plugin global ou un objet NVDA.
Dans un nouveau fichier texte nommé example3.py, qui doit être sauvegardé dans le répertoire globalPlugins, copiez et collez le code entre les marqueurs de début et de fin, sans les inclure. Faite très attention de garder tout les tabulations et les espaces intacts.
Une fois enregistré à l'emplacement correct, vous pouvez redémarrer NVDA ou choisir de Recharger les Plugins. Vous trouverez ceci dans le sous-menu Outils du menu NVDA.
--- start --- #Window utility scripts for NVDA #Developer guide example 3 import globalPluginHandler import ui import api class GlobalPlugin(globalPluginHandler.GlobalPlugin): def script_announceWindowClassName(self, gesture): focusObj = api.getFocusObject() name = focusObj.name windowClassName = focusObj.windowClassName ui.message("class for %s window: %s" % (name, windowClassName)) def script_announceWindowControlID(self, gesture): focusObj = api.getFocusObject() name = focusObj.name windowControlID = focusObj.windowControlID ui.message("Control ID for %s window: %d" % (name, windowControlID)) __gestures = { "kb:NVDA+leftArrow": "announceWindowClassName", "kb:NVDA+rightArrow": "announceWindowControlID", } --- end ---
Évènements
Quand NVDA détecte des toolkit particulier, l'API ou les événements du système d'exploitation, à it abstracts these and fires its own internal events on plugins and NVDA Objects.
Bien que la plupart des événements soient liés à un objet NVDA spécifique (par exemple changement de nom, gain du focus, changement d'état, etc.), ces événements peuvent être traités à différents niveaux. Quand un événement est géré, il est empêché d'aller plus loin dans la chaîne. Toutefois, le code dans l'événement peut choisir de se propager davantage si nécessaire.
L'ordre des niveaux par lequel passe l'événement jusqu'à ce qu'une méthode d'événement soit trouvée est:
- les plugins globaux Chargés
- les Module App associés à l'objet NVDA dont l'événement est actif
The App Module associated with the NVDA Object on which the event was fired
- l'arborescence d'interception de l'objet NVDA dont l'évènement est actif si cas échéant
The Tree Interceptor (if any) associated with the NVDAObject on which the event was fired
- l'Objet NVDA lui-même.
Les événements sont des méthodes d'instance Python, possédant un nom commençant par "event_" suivie par le nom de l'événement (par exemple gainFocus).
Ces méthodes d'événement prennent des arguments légèrement différents selon le niveau auquel ils sont définis.
Si un événement d'un objet NVDA est défini pour lui-même, la méthode prend un seul argument obligatoire, le 'self' argument: à savoir l'instance d'objet NVDA). Certains événements peuvent prendre des arguments supplémentaires, mais cela est assez rare.
Si un événement d'un objet NVDA est définie sur un greffon global, un module App ou l'arborescence d'interception, l'événement prend les arguments suivants:
- self (auto): l'instance du plug-in Global, du Module App ou de l'arborescence d'interception
- obj (objet): objet NVDA sur lequel l'événement a été appelé
- nextHandler: une fonction qui sera appelé lorsque l'événement se propage loin dans la chaîne.
Certains événements communs aux objets NVDA sont:
- foreground (avant-plan): cet objet NVDA est passé en avant-plan, c'est à dire l'objet actif de plus haut niveau
- gainFocus (obtention du focus)
- loseFocus (perte du focus)
- nameChange (Changement du nom)
- valueChange ((Changement de la valeur)
- stateChange (((Changement de l'état)
- caret (curseur): lorsque le curseur (point d'insertion) se déplace au sein de cette objet NVDA
- locationChange (Changement de l'emplacement): changements physiques de l'emplacement à l'écran
Il existe beaucoup d'autres événements, bien que ceux énumérés ci-dessus sont généralement les plus utiles.
Pour voir un exemple d'un événement géré par un module App, référez-vous à l'exemple 1
La variable App SleepMode module
Les Modules App ont une propriété très utile appelée "sleepMode", qui, si elle est à "true" désactive presque complètement NVDA au sein de cette application. Le mode veille est très utile pour les applications auto vocalisée qui possèdent leur propre fonctionnalité de lecture d'écran, ou peut-être même certains jeux qui ont besoin d'utiliser pleinement le clavier.
Bien que le mode veille puisse être activé et désactivé par l'utilisateur avec la commande touche NVDA + MAJ + S, un développeur peut choisir d'activé le mode veille par défaut pour une application donnée. Ceci est fait en fournissant un module App pour cette application, dans la classe AppModule sleepMode est simplement à True.
Exemple 4: Un module App mode veille
Vous pouvez copier coller Le code suivant dans un fichier texte, puis l'enregistrer dans le répertoire appModules en lui donnant le nom de l'application pour laquelle vous souhaitez activer le mode veille. Le fichier doit avoir l'extension .Py, Comme d'habitude.
--- start --- import appModuleHandler class AppModule(appModuleHandler.AppModule): sleepMode = True --- end ---
Fourniture de Classes d'Objets pour personnaliser NVDA
Fournir des classes d'objet NVDA à l'intérieur d'un plugin NVDA est probablement le moyen le plus puissant et le plus utile pour améliorer l'utilisation d'une application. Cette méthode vous permet de placer l'ensemble de tout ce qui est nécessaire pour un contrôle précis dans une classe d'objet NVDA, plutôt que de disperser le code des contrôles dans les événements de nombreux plugin.
Il ya deux étapes pour créer une classe d'objet NVDA personnalisée :
- Définir la classe d'Objet NVDA et de ses évènements, scripts, gesture bindings et propriétés de remplacement.
- Dire à NVDA d'utiliser cette classe d'objet NVDA pour des situations spécifiques en le définissant dans la méthode chooseNVDAObjectOverlayClasses du plugin.
Lors de la définition d'une classe d'Objet NVDA personnalisé, vous pouvez choisir entre de nombreuses classes de NVDAObjec de base. Ces classes de base contiennent le support de base notamment pour l'accessibilité ou une OS API sous-jacente au contrôle, tels que Win32, MSAA ou Java access Bridge. Vous devriez normalement hériter vos classes personnalisées NVDAObject de la classe de base la plus élevée dont vous avez besoin pour que votre classe soit choisi en premier. Par exemple, si vous choisissez d'utiliser votre classe NVDAObject personnalisée lorsque le nom de la window classe est "Edit" (Edition) et l'ID du window contrôle est de 15, vous devriez probablement hériter de NVDAObjects.window.Window, aussi clairement que vous êtes conscient que c'est un Window object. De même, si vous lui associez la propriété accRole de MSAA, vous aurez probablement besoin d'hériter d'NVDAObjects.IAccessible.IAccessible. Vous devriez également songer à quelles propriétés vous allez substituer dans les objets personnalisés NVDA. Par exemple, si vous substituez une propriété IAccessible spécifiques tels que shouldAllowIAccessibleFocusEvent, alors vous aurez besoin d'hériter de NVDAObjects.IAccessible.IAccessible.
La méthode chooseNVDAObjectOverlayClasses peut être implémenté dans des modules app ou des classes de plugins globaux. Elle prend 3 arguments:
- self (auto): l'instance du module app ou du plugin global.
- obj (objet): le NVDAObject pour lequel les classes sont choisies.
- clsList: une liste de classes Python de NVDAObject qui sera utilisées pour obj.
A l'intérieur de cette méthode, vous devez décider de l'usage des classe(es) d'objet NVDA (si cas échéant) si cet objet NVDA doit être utilisé en vérifiant ses propriétés, etc. Si une classe personnalisée doit être utilisée, elle doit être insérée dans la liste de classe, généralement au début. Vous pouvez également supprimer de la liste de classe des classes choisies par NVDA, bien que cela soit rarement nécessaire.
Exemple 5: étiquetage du champ d'édition de Notepad à l'aide d'un objet de personnalisation NVDA
Ce module app pour Notepad fait NVDA rapport du Bloc-notes zone d'édition principale comme ayant le nom "content". Qui est, lorsqu'il reçoit le focus, NVDA dira "Content edit" (éditer le contenu).
This app module for notepad makes NVDA report Notepad's main edit field as having a name of "content". That is, when it receives focus, NVDA will say "Content edit".
Le code suivant peut être copié et collé dans un fichier texte, puis enregistré dans le répertoire appModules en le nommant notepad.py.
--- start --- import appModuleHandler from NVDAObjects.window import Window class AppModule(appModuleHandler.AppModule): def chooseNVDAObjectOverlayClasses(self, obj, clsList): if isinstance(obj, Window) and obj.windowClassName == "Edit" and obj.windowControlID == 15: clsList.insert(0, LabelledEditField) class LabelledEditField(Window): name="Content" --- end ---