Results 1 to 5 of 5

Thread: MessageDlg in Datamodule ?

  1. #1
    TDigitalTrain user Hans Brenkman's Avatar
    Join Date
    Mar 2002
    Location
    Weert
    Posts
    1,861

    MessageDlg in Datamodule ?

    Hi,

    Ik gebruik soms MessageDlg o.i.d. in een DataModule bijv. als ik iets te melden heb in een BeforePost. Die MessageDlg hoort daar in feite niet thuis en zou dus beter vanuit een form getoond moeten worden.
    Ik ben dus op zoek naar hoe ik dit voor elkaar kan krijgen. Is TMessage / TMessageManager een gebruikte oplossing of iets anders? Zoals in een form zelf een DoOnBeforePost-event maken en dan koppelen aan OnBeforePost-event in de DataModule en vanuit de datamodule doorgeven wat ik te melden heb ?
    Wat is de geijkte weg om dit te goed aan te pakken ?

    TMessage / TMessageManager:
    http://docwiki.embarcadero.com/CodeE...aging_(Delphi)
    Testen kan niet de afwezigheid van fouten aantonen, slechts de aanwezigheid van gevonden fouten.

    Het is verdacht als een nieuw ontwikkeld programma direct lijkt te werken: waarschijnlijk neutraliseren twee ontwerpfouten elkaar.

  2. #2
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Ik gebruik daar zelf een eenvoudige log/message/progress-interface voor die iedere class mee kan krijgen als hij wat te melden heeft of meldingen wil hebben.

    Een datamodule kan bijvoorbeeld dan een bericht geven en een visueel control (zoals de mainform) kan hier dan op reageren door een MessageDlg te tonen.
    Als er ook een log-module aanwezig is, dan kan deze tegelijkertijd (of in plaats van) de melding loggen naar schijf of database.

    TMessage/TMessageManager ken ik niet, ik werk nog met Delphi uit het jaar nul.
    TMemoryLeak.Create(Nil);

  3. #3
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    TMessage lijkt mij een nieuwe universele manier van berichten tonen wat met showmessage ook kan.
    DoOnBeforePost-event kan je aanmaken, maar dan kan je de vraag stellen: hoort deze op mijn form gezet te worden?

    Ik speel een beetje vals, maar ik heb een unit, waarin d.m.v. een memdataset variabelen met waarden gezet kunnen worden. Deze kan als singleton worden opgevraagd.

    De beste manier is het maken van een eigen procedure
    Delphi Code:
    1. type TMijnBericht = procedure(const aBericht : string) of object
    Deze koppelen aan een procedure in je form.
    Delphi is great. Lazarus is more powerfull

  4. #4
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Zo'n event-oplossing is eigenlijk alleen geschikt als je maar een handvol forms, datamodules en andere objecten hebt.

    Ik heb een stuk uit mijn code gekoppie-peest en alleen de basis (tekstberichten) erin gelaten en in een demo gezet
    Name:  NLDMessageDemo.png
Views: 287
Size:  14.5 KB
    In mijn gehele code heb ik een heleboel soorten afgeleiden die kunnen zenden naar de interface ("ILogListener"), zodat
    je verder niets meer hoeft te doen dan een object van het "Oude" type te hernoemen naar het "Nieuwe" type.

    TMyForm = class(TForm) wordt dan bijvoorbeeld TMyForm = class(TMessengerForm)
    en
    TMyDataModule = class(TDataModule) wordt dan TMyDataModule = class(TMessengerDataModule)

    Vervolgens kun je dan de berichten-methods (DoMessage, DoProgress, ...) in je object aanroepen wanneer nodig.


    Objecten die willen luisteren naar de interface hoeven alleen deze toe te voegen aan de class-definitie en de methods
    van de interface te implementeren:
    TMyForm = class(TForm, ILogListener)

    Zelf maak ik hiervoor ook weer dummy/template afgeleiden waarin ik de interface en methods al implementeer, maar
    er niets mee doe.
    Een afgeleide die uiteindelijk wel iets met een bericht wil doen hoeft dan alleen maar de method te overriden.
    Attached Files Attached Files
    TMemoryLeak.Create(Nil);

  5. #5
    TDigitalTrain user Hans Brenkman's Avatar
    Join Date
    Mar 2002
    Location
    Weert
    Posts
    1,861
    Quote Originally Posted by jkuiper View Post
    DoOnBeforePost-event kan je aanmaken, maar dan kan je de vraag stellen: hoort deze op mijn form gezet te worden?.
    Mee eens, maar de gedachte was het dan zo op te splitsen, dat de controle in de Datamodule in de OnBeforePost plaatsvindt en de tekst die voortvloeit uit die controle naar het Form.DoOnBeforePost te sturen, die op zijn beurt de tekst in een MessageDlg laat zien. Optimaal is het w.s. niet.


    Ik heb zelf een soort gelijk systeem opgezet als VideoRipper, alleen dan niet in met aparte class dus iets minder geavanceerd, maar het voelde niet lekker.

    Basis datamodule:
    Code:
    type
      TEventOnException          = procedure(const aSource: string; E: Exception) of object;
      TEventOnExecuteToGUI       = procedure(const aMsg: string)                  of object;
      TEventOnExecuteToLog       = procedure(const aMsg: string)                  of object;
    
      TDmBasis = class(TDataModule, IBasisLogging)
      private
        FOnExecuteToGUI: TEventOnExecuteToGUI;             
        FOnExecuteToLog: TEventOnExecuteToLog; 
        FOnException: TEventOnException;   
      private
        procedure DoOnGUI(const aMsg: string);
        procedure DoOnLog(const aMsg: string);
        procedure DoOnLogException(const aMsg: string; E:Exception); overload;
      public
        property  OnExecuteToGUI: TEventOnExecuteToGUI read FOnExecuteToGUI write FOnExecuteToGUI;
        property  OnExecuteToLog: TEventOnExecuteToLog read FOnExecuteToLog write FOnExecuteToLog;
        property  OnException: TEventOnException read FOnException write FOnException;
      end;
    
    
    procedure TDmBasis.DoOnLog(const aMsg: string);
    begin
      if Assigned( FOnExecuteToLog ) then
        FOnExecuteToLog( aMsg )
      else
        LogApplication( Format('%s (FOnExecuteToLog) not assigned. %s', [ GetMyProcName(True), aMsg ], Globals.FormatSettings ));
    end;
    Basis class t.b.v. een Task (in dit geval geen form als class maar een class t.b.v. een service applicatie waarin e.e.a. gelogd wordt).

    Code:
    type
      TTaskBasis = class(TInterfacedObject, IBasisLogging)
      private
        procedure DoOnGUI(const aMsg: string);
        procedure DoOnLog(const aMsg: string);
        procedure DoOnLogException(const aMsg: string; E:Exception); overload;
      end;
    
    procedure TTaskBasis.DoOnLog(const aMsg: string);
    begin
      TThread.Synchronize(TThread.Current,
        procedure
        begin
          WriteLog( FTaskLogFile, aMsg )
        end);
    end;
    In afgeleide Datamodule en afgeleide class t.b.v. de Task de zaken aan elkaar koppelen:
    Code:
    FDmAanvragen.OnExecuteToLog := DoOnLog;   // DoOnLog = TTaskBasis.DoOnLog
    Vervolgens kan ik in beide afgeleide naar dezelfde logfile e.e.a. loggen:
    Code:
    DoOnLog( Format('Bestand %s is aangemaakt', [ FFile ] , Globals.FormatSettings));
    Met TMessage (in principe een singleton) in een applicatie kun je waarschijnlijk nog meer code scheiden. Zoals ik hierboven (in een verkorte versie) heb getoond zijn Dm en class (of form) toch aan elkaar gekoppeld. Weliswaar "loosely coupled" maar ik vroeg me af of dat anders c.q. beter zou kunnen.

    Bedankt voor de reacties, ik ga e.e.a. verder uitproberen.
    Testen kan niet de afwezigheid van fouten aantonen, slechts de aanwezigheid van gevonden fouten.

    Het is verdacht als een nieuw ontwikkeld programma direct lijkt te werken: waarschijnlijk neutraliseren twee ontwerpfouten elkaar.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •