Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Kørsel uden brugerindgreb

0 views
Skip to first unread message

Mik

unread,
Jan 18, 2004, 6:27:42 AM1/18/04
to
Jeg har et lille Delphi7 program som sender nogle regnskabsdata til en anden
maskine (email).
Programmet virker fint, men jeg vil gerne, at programmet viser en meddelelse
på skærmen, sender filen og derefter afslutter - uden brugerindgreb.
Bruger jeg Event OnActivate på min Form virker det fint - bortset fra at
meddelelsen (Label) aldrig vises på skærmen.
Hvordan får jeg startet afsendelsen - efter meddelelsen vises på skærmen?

Med venlig hilsen
Lars


Klaus Petersen

unread,
Jan 18, 2004, 6:36:05 AM1/18/04
to

> Programmet virker fint, men jeg vil gerne, at programmet viser en
meddelelse
> på skærmen, sender filen og derefter afslutter - uden brugerindgreb.
> Bruger jeg Event OnActivate på min Form virker det fint - bortset fra at
> meddelelsen (Label) aldrig vises på skærmen.

Det er nok ikke så godt at bruge OnActivate, da den event udløses hver gang
vinduet bliver aktiveret - dvs. skifter du til et andet program og tilbage
igen køres eventhandleren een gang til.

Een måde at lave det på er at have en Timer komponent på formen. Timeren
skal disabled på formen.

På formens OnShow kan du enable timeren - og på timeren's event kan du
starte afsendelsen.

> Hvordan får jeg startet afsendelsen - efter meddelelsen vises på skærmen?

Meddelsen bliver ikke vist, fordi hændelsen (OnActivate) indetræffer før den
når at vise den.

Det skyldes sikkert også, at du ikke afvikler meddelser (her snakker jeg om
windows' egne messages) mens du afvikler afsendelsen.

Det har samme effekt som når et program ikke svarer i windows.

Løsningen er som regel simpel - du skal bare indsætte følgende linje:

application.ProcessMessages;

... i løkker (repeat .. until ... do ... while ... ) i din afsendelses
rutine.

mvh.
Klaus.


Mik

unread,
Jan 18, 2004, 8:54:17 AM1/18/04
to
>"Klaus Petersen skrev:

>
> Løsningen er som regel simpel - du skal bare indsætte følgende linje:
>
> application.ProcessMessages;
>
> mvh.
> Klaus.

Tak - ovenstående løste problemet.

mvh. Lars


Ove Kjeldgaard

unread,
Jan 18, 2004, 3:37:02 PM1/18/04
to
"Klaus Petersen" <spec...@getTOnet.dk> wrote:

>Løsningen er som regel simpel - du skal bare indsætte følgende linje:
>
>application.ProcessMessages;
>
>... i løkker (repeat .. until ... do ... while ... ) i din afsendelses
>rutine.

Det er egentlig en god ting altid at indsætte ProcessMessages i løkker, det er
noget nemmere hvis man får lavet en uendelig løkke ;-)

Det er kun få dage siden jeg havde en While, hvor jeg igen glemte både at
incremente en variabel og ProcessMessages linien...


--
Med venlig hilsen, Ove Kjeldgaard, nospam AT privat DOT dk
Natur og Friluftsliv: <http://hiker.dk>

Nicolai Hansen

unread,
Jan 19, 2004, 3:03:06 AM1/19/04
to
Ove Kjeldgaard <ReadM...@The.Signature> wrote in message news:<d7rl00l59ajf8fnug...@4ax.com>...

> "Klaus Petersen" <spec...@getTOnet.dk> wrote:
>
> >Løsningen er som regel simpel - du skal bare indsætte følgende linje:
> >
> >application.ProcessMessages;
> >
> >... i løkker (repeat .. until ... do ... while ... ) i din afsendelses
> >rutine.
>
> Det er egentlig en god ting altid at indsætte ProcessMessages i løkker, det er
> noget nemmere hvis man får lavet en uendelig løkke ;-)
>
> Det er kun få dage siden jeg havde en While, hvor jeg igen glemte både at
> incremente en variabel og ProcessMessages linien...

Maaaan skal passe på her. Man roder sig ud i noget asynkron
programmering ;)

Hvis man indsætter en Application.ProcessMessages; i en handler for
f.eks. et tryk på en knap (hvor man har en laaaaang løkke i), vil man
kunne starte løkken inden i løkken, inden i løkken, inden i ... indtil
der kommer et stack overflow, bang, crash, forfra :o)

Hvis man bare vil ha en label tegnet på skærmen, vil jeg foreslå
label.caption:='hej'; label.update;
istedet.

Mik

unread,
Jan 19, 2004, 6:50:18 AM1/19/04
to
"Nicolai Hansen" <n...@aub.dk> skrev i en meddelelse
news:d96764ff.04011...@posting.google.com...

> Hvis man bare vil ha en label tegnet på skærmen, vil jeg foreslå
> label.caption:='hej'; label.update;
> istedet.

Fuldt tilstrækkeligt i mit tilfælde - tak

mvh. Mik


Klaus Petersen

unread,
Jan 20, 2004, 6:00:10 PM1/20/04
to
> Hvis man bare vil ha en label tegnet på skærmen, vil jeg foreslå
> label.caption:='hej'; label.update;
> istedet.

Med fare for at tage fejl ... opdatering af en label foregår vel som alle
grafiske opdateringer af vinduer foregår i windows ... ved at sende en
WM_PAINT til vinduet, som så tegner sig selv.

Men hvis du ikke afvikler meddelser, så når du aldrig at få meddelsen før
den afvikler meddelser igen - dvs. efter løkken er afsluttet.

Hvis man vi undgå, at løkken bliver startet 2 gange er der mange muligheder.
Den nemeste er vist at disable knappen - den sikreste at sætte et flag, som
den tjekker inden den går ind i løkken.

Nicolai Hansen

unread,
Jan 21, 2004, 8:15:33 AM1/21/04
to
"Klaus Petersen" <spec...@getTOnet.dk> wrote in message news:<SpiPb.361$ia...@news.get2net.dk>...

> > Hvis man bare vil ha en label tegnet på skærmen, vil jeg foreslå
> > label.caption:='hej'; label.update;
> > istedet.
>
> Med fare for at tage fejl ... opdatering af en label foregår vel som alle
> grafiske opdateringer af vinduer foregår i windows ... ved at sende en
> WM_PAINT til vinduet, som så tegner sig selv.

Sådan KAN det foregå. TControl.Update gennemtvinger en optegning uden
om Windows message pumpen.

Fra (VCL) TControl.Update hjælpen i Delphi 6:

procedure Update; virtual;

Description

Call Update to force the control to be repainted before any more,
possibly time-consuming, processing takes place. Use Update to provide
immediate feedback to the user that cannot wait for the Windows paint
message to arrive.

Update does not invalidate the control, but simply forces a repaint of
any regions that have already been invalidated. Call Repaint instead
to invalidate the control as well.

> Men hvis du ikke afvikler meddelser, så når du aldrig at få meddelsen før
> den afvikler meddelser igen - dvs. efter løkken er afsluttet.

.Update sender ikke en besked - den tegner direkte og med det samme.
Hvis du vil sende en besked er der også en metode til det -
PostMessage eller noget i den dur - som lægger en besked i køen.

> Hvis man vi undgå, at løkken bliver startet 2 gange er der mange muligheder.
> Den nemeste er vist at disable knappen - den sikreste at sætte et flag, som
> den tjekker inden den går ind i løkken.

Det kommer skam an på hvor asynkront man har lyst til at programmere.
Det man skal være klar over er at hvis man starter løkke A, og
midtvejs i denne starter løkke B - så kører den løkke B færdig før den
genoptager sit arbejde med løkke A.
Så hvis man -inde fra løkke A- kalder ProcessMessages() eller
HandleMessage() skal man være 101% sikker på at løkke A er HELT
adskilt fra resten af programmet, da man vil have en uspecificeret
tilstand af denne løkke i måske flere sekunder.
Det svarer lidt til at programmere i tråde; det er fint så længe de
ikke skal dele variable.

Prøv følgende lille program ...

Lav en form med to knapper, Button1 (caption="count") og Button2
(caption="reset") og en editbox (Edit1). Lav en privat variabel
"count: Integer;".

Skriv følgende OnClick handlers:

Button1Click:

begin
Count:=0;
repeat
inc(count);
Edit1.Text:=IntToStr(count);
Application.ProcessMessages;
until count>1000000;
ShowMessage('finito!');
end;

Button2Click:

begin
Count:=0;
end;

prøv at starte med at trykke på knap 1 - og så trykke på knap to af og
til. Counteren startes forfra hver gang.

Prøv så at fjerne Application.ProcessMessages og erstat linien med
"Edit1.Update". Så kører programmet som det skal (knap 1 tæller og
knap 2 resetter).

Klaus Petersen

unread,
Jan 21, 2004, 11:46:57 AM1/21/04
to
> Sådan KAN det foregå. TControl.Update gennemtvinger en optegning uden
> om Windows message pumpen.

Det var så den "fare" jeg snakkede om :-]


0 new messages