Med venlig hilsen
Lars
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.
Tak - ovenstående løste problemet.
mvh. Lars
>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>
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.
> 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
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.
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).
Det var så den "fare" jeg snakkede om :-]