2008-12-19 8 views
3

J'y arrive régulièrement, et je suis à la recherche de meilleures pratiques/approches. J'ai une application contenant la base de données/datamodule, et je veux lancer la base de données/datasets au démarrage sans avoir "active at runtime" défini sur true au moment du design (l'emplacement de la base de données varie). Également exécuter une routine Web "vérifier les mises à jour" lorsque l'application démarre.Delphi: initialisation de l'application - meilleures pratiques/approche

Compte tenu des séquences d'événements TForm, et les résultats de divers essais et d'erreurs, je suis actuellement en utilisant cette approche:

J'utilise un enregistrement « Globals » mis en place sous la forme principale pour stocker tous les vars mondiaux, disposent d'un élément de celui appelé Globals.AppInitialized (boolean), et le définir à False dans la section Initialisation du formulaire principal. Lors de l'événement OnShow du formulaire principal (tous les formulaires sont créés à ce moment-là), je teste Globals.AppInitialized;

si c'est faux, je lance mon truc "Initialization", et termine en définissant Globals.AppInitialized: = True.

Cela semble fonctionner plutôt bien, mais est-ce la meilleure approche? Vous cherchez un aperçu de l'expérience, des idées et des opinions des autres. TIA ..

+0

une vidéo il y a 10 ans: https://youtu.be/_PJdZjM2oTw qui couvre ce un peu . – Alister

Répondre

10

Je tourne généralement toujours hors création automatique de toutes les formes SAUF pour la forme principale et peut-être le datamodule primaire.

Un truc que j'ai appris que vous pouvez faire, est d'ajouter votre module de données à votre projet, lui permettre de créer automatiquement et de créer AVANT votre formulaire principal. Ensuite, lorsque votre formulaire principal est créé, l'onCreate pour le module de données aura déjà été exécuté.Si votre application a du code à dire, définissez le focus d'un contrôle (ce que vous ne pouvez pas faire lors de la création, puisqu'il n'est pas encore visible), puis créez un message utilisateur et postez-le sur le formulaire dans votre oncréer. Le message DEVRAIT (sans garantie) être traité dès que la boucle de message de formulaires est traitée. Par exemple:

const 
    wm_AppStarted = wm_User + 101; 


type 
    Form1 = class(tForm) 
    : 
    procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted; 
    end; 

// in your oncreate event add the following, which should result in your wmAppStarted event firing. 
PostMessage(handle,wm_AppStarted,0,0); 

Je ne peux pas penser à une seule fois que ce message n'a jamais été traité, mais la nature de l'appel est qu'il est ajouté à la file d'attente de messages, et si la file d'attente est pleine il est tombé". Sachez juste que ce cas de bordure existe.

+3

+1 pour l'indice de désactivation de la création automatique de formulaire. C'est l'une des raisons pour lesquelles les applications Delphi démarrent plus lentement qu'elles ne le devraient. Les messages Windows pour traitement différé méritent également d'être examinés. – mghie

+0

Que devrait être dans le corps de la procédure wmAppStarted? – Wojtas

+0

@Wojtas quelle que soit la logique que vous souhaitez effectuer compte tenu de l'application est en cours d'exécution et le traitement des messages. – skamradt

1

Je ne suis pas sûr de comprendre pourquoi vous avez besoin des variables globales? De nos jours, j'écris TOUTES mes applications Delphi sans une seule variable globale. Même quand je les ai utilisés, je n'ai jamais eu plus d'un couple par application.

Alors peut-être que vous devez d'abord penser à pourquoi vous en avez réellement besoin.

+1

En général, je les évite, mais dans certains cas, j'ai trouvé qu'il y a quelques variables qui semblent appartenir le mieux à l '"application elle-même". Ceci est un exemple. Parfois, je vérifie avant d'exécuter une routine sous une autre forme. Il peut également être configuré en tant que "propriété" d'un formulaire ou d'un DM à la place. – Jamo

2

Il n'existe pas de notion de "variable globale" dans Delphi. Toutes les variables sont limitées à l'unité dans laquelle elles se trouvent et aux autres unités qui utilisent cette unité.

Assurez les choses AppInitialized et Initialisation dans le cadre de votre module de données. Fondamentalement, ont une classe (ou datamodule) pour gouverner tous vos trucs non-UI

vous pouvez également (un peu comme celui-Ring, à l'exception pas tout le mal et tel.):

  • Appel à partir votre écran de démarrage.
  • Faites-le lors de la connexion à
  • Exécutez le « vérifier la mise à jour » dans un thread d'arrière-plan - ne pas les forcer à mettre à jour en ce moment. C'est un peu comme Firefox.
+0

Merci Jim - utile. Point noté aussi re: distinction "variable globale". Timing-sage, voyez-vous des problèmes w/"tirant" la substance d'initialisation de l'événement OnShow du formulaire principal? (J'aime votre idée de loger le * code * réel pour cela dans le module de données, cependant). – Jamo

+0

Le problème avec OnShow est que montrer le formulaire n'a aucun rapport avec les choses que vous voulez faire. Tout ne doit pas nécessairement se produire dans le contexte d'un formulaire. –

+0

Merci pour l'entrée, Rob! – Jamo

7

Vous pouvez interférer directement avec la source du projet (fichier .dpr) après les appels de création de formulaire et avant Application.Run. (. Ou encore plus tôt en cas)

Voici comment je gère habituellement comme initialisations:

... 
Application.CreateForm(TMainForm, MainForm);  
... 
MainForm.ApplicationLoaded; // loads options, etc.. 
Application.Run; 
... 
+3

Oui! Il est important de savoir que le "formulaire principal" n'est pas le point d'entrée du programme, et OnShow n'est pas le point d'entrée d'un formulaire. –

3

Je ne sais pas si cela est utile, mais certains de mes applications ne pas auto forme créée, à savoir qu'ils n'ont pas mainform dans l'IDE.

Le premier formulaire créé avec l'objet Application en tant que propriétaire deviendra automatiquement la forme principale. Ainsi, je ne fais qu'autocréer un seul datamodule en tant que loader et laisser celui-ci décider quels datamodules créer quand et quelles formes créer dans quel ordre. Ce datamodule a une méthode StartUp et ShutDown, qui sont appelés "crochets" autour de Application.Run dans le dpr. La méthode ShutDown donne un peu plus de contrôle sur le processus d'arrêt.

Cela peut être utile lorsque vous avez conçu différentes « mainforms » pour les différents cas d'utilisation de votre application ou vous pouvez utiliser des fichiers de configuration pour sélectionner différents mainforms.

+0

C'est assez créatif, et je peux penser à quelques exemples pour lesquels cela serait utile. Merci de l'avoir posté! – Jamo

0

Une astuce que j'utilise est de placer un TTimer sur la principale forme, régler le temps à quelque chose comme 300ms, et effectuer une initialisation (connexion db, des copies de fichiers réseau, etc.). Le démarrage de l'application fait apparaître la forme principale immédiatement et permet à toute «chose» d'initialisation de se produire. Les utilisateurs ne démarre pas plusieurs instances de penser « Oh..I n'a pas DBL-cliquez sur ... Je vais le faire à nouveau .. »

+0

Et, si votre minuteur n'est pas assez long? Faites votre initialisation, puis envoyez votre main pour un message Windows. – Mawg

1

J'utilise un module de données primaire pour vérifier si la connexion DB est OK et si elle ne constitue pas, montrer une forme de composant personnalisé pour configurer la connexion db et charge alors la forme principale:

Application.CreateForm(TDmMain, DmMain); 

    if DmMain.isDBConnected then 
    begin 
     Application.CreateForm(TDmVisualUtils, DmVisualUtils); 
     Application.CreateForm(TfrmMain, frmMain); 
    end; 

    Application.Run; 
+0

Merci pour cette entrée, Gedean! – Jamo