Vraag & Antwoord

Programmeren

(VB6) een form ECHT sluiten

11 antwoorden
  • Ik ben bezig met een programmaatje waarbij ik in VB6 programmeer en ik gebruik meerdere forms. Hierbij switch ik van form waarbij de een verdwijnt en de ander zichtbaar wordt. Dit doe ik nu door: [code:1:b0e24811ad] form1.hide form2.show[/code:1:b0e24811ad] Maar nu ben ik tegen een probleem aangelopen, als ik namelijk na een bepaalde gebeurtenis 2 procedures aanroep, waarbij eerst de een en dan de andere wordt uitgevoerd dan gebeurt er het volgende: In de eerste procedure is er aan een bepaalde voorwaarde voldaan waardoor form1 gesloten moet worden en form2 getoond, maar als ik dat met de bovenstaande code doe dan wordt de tweede procedure nog uitgevoerd terwijl form1 al verstopt is en form2 al geopend en dat is dus niet de bedoeling Weet iemand misschien hoe ik een form ECHT kan sluiten en het niet alleen kan verstoppen??
  • dat doe je met: unload [formnaam] of in het form zelf: unload me
  • ok, bedankt
  • ook ik ben blij met dit antwoord :)
  • Daarmee is het form nog niet verdwenen. Na de unload zul je het form nog moeten opruimen met [code:1:56d48e9bfa] set Form1 = nothing [/code:1:56d48e9bfa] anders heb je kans dat bij de tweede keer openen variabelen hun oude waarde nog hebben en dat kan tot onverwachte resultaten leiden.
  • Hiermee zorg je er voor dat er geen referentie meer is naar het voorheen gebruikte geheugen, niemand kan garanderen dat wanneer er een nieuwe referentie gemaakt wordt, dat dit dan niet naar het zelfde stukje geheugen zou kunnen zijn. Sterker nog, als je programma niet veelvuldig met alloceren en de-alloceren doet, dan is de kans dat je hetzelfde stukje geheugen toegewezen krijgt best wel groot. Immers, het Windows geheugenbeheer is niet zo dynamisch als velen wel denken. Het zou natuurlijk heel mooi kunnen zijn wanneer je het gebruikte geheugen vrij kunt geven en meteen kunt "resetten" door alles op bijvoorbeeld '0' te zetten. Pas dan kun je echt spreken van een compleet verwijderd formulier. Misschien een leuke uitdaging?
  • Zet in je module bij de declaraties het volgende (ik gebruik even de naam frmMain als voorbeeld): Public fMain As frmMain En in je Sub: Set fMain = New frmMain fMain.Show En met deze code is de referentie weer foetsie en wordt het geheugen ook weer vrijgegeven: Unload fMain Set fMain=Nothing
  • Met unload [object] zal de procedure die bezig is in je form gestopt worden. unload Form1 zal dus doen wat je zoekt. Je moet het niet altijd te ingewikkeld maken!
  • heel simpel sub form_unload() end end sub
  • dan sluit ie wel het hele project af en niet maar één form..
  • [quote:2802a11e9c="DarkScribe"]Hiermee zorg je er voor dat er geen referentie meer is naar het voorheen gebruikte geheugen, niemand kan garanderen dat wanneer er een nieuwe referentie gemaakt wordt, dat dit dan niet naar het zelfde stukje geheugen zou kunnen zijn. Sterker nog, als je programma niet veelvuldig met alloceren en de-alloceren doet, dan is de kans dat je hetzelfde stukje geheugen toegewezen krijgt best wel groot. Immers, het Windows geheugenbeheer is niet zo dynamisch als velen wel denken. [/quote:2802a11e9c] Bij het creëren van een form genereert VB onderwater een hidden variable met dezelfde naam als het form. Door deze op nothing te zetten wordt de laatste referentie verwijderd waardoor het geheugen impliciet niet meer gealloceerd is. Dit moet je juist doen omdat de garbagecollector van vb niet zo actief is. Bij het opnieuw aanmaken van hetzelfde form wordt er een nieuwe referentie gemaakt omdat de oude domweg niet meer bestaat, daarmee wordt ook het geheugen opnieuw gealloceerd en geinitialiseerd. Dat dat misschien hetzelfde stuk is maakt natuurlijk niet uit. Het zou nogal raar zijn als je geheugen niet opnieuw mocht gebruiken. Het aanmaken van een hidden variable gebeurt overigens alleen maar als je een form direct aanmaakt. Als je het form netjes declareert en instantieert gebeurt dit niet omdat je dan zelf al die variabele (eigenlijk een handle) gemaakt hebt en vb dit dan niet meer voor je hoeft te doen. Deze variabele zou theoretisch direct moeten verdwijnen als hij out of scope raakt maar dat laat in de praktijk nog wel eens te wensen over. Dus ook deze zul je moeten opruimen met een = Nothing. En dan is hij echt weg, of je het nu leuk vindt of niet. Of het geheugen dan ook gewist is of niet is niet belangrijk want je programma kan er niet meer bij. Bij nieuwe allocatie is het geheugen tevens opnieuw geinitialiseerd. [quote:2802a11e9c] Met unload [object] zal de procedure die bezig is in je form gestopt worden. unload Form1 zal dus doen wat je zoekt. Je moet het niet altijd te ingewikkeld maken [/quote:2802a11e9c] Mee eens, maar het advies dat je geeft is gewoon niet juist. Kun je zelf testen door te kijken wanneer het terminate event afgaat. Die gaat pas af in de destructor van het form. Volg de volgende stappen om het verschil te zien: [list:2802a11e9c]Maak een projectje aan met 2 forms. Gebruik Form1 als opstart formulier. Zet hierop een knop met daaronder Form2.show[/list:u:2802a11e9c] [list:2802a11e9c]Zet op Form2 een knop met daaronder Unload Me[/list:u:2802a11e9c] [list:2802a11e9c]Zet in het terminate event van form2 een messagebox "Terminate"[/list:u:2802a11e9c] [list:2802a11e9c]Start het projectje.[/list:u:2802a11e9c] [list:2802a11e9c]Klik nu op de button in Form 1. Form2 wordt geopend. Klik nu op de button in form 2. Het formulier sluit zich. Er wordt geen messagebox getoond omdat het formulier niet echt vernietigd wordt.[/list:u:2802a11e9c] [list:2802a11e9c]Sluit nu form1 met het kruisje. Nu pas gaat het terminate event van Form2 af. M.a.w. het object bestond nog steeds.[/list:u:2802a11e9c] [list:2802a11e9c]Zet nu na de Unload me Set Form2 = Nothing. (Technisch niet helemaal correct omdat je nu binnen de instantie de betreffende instantie vernietigd, maar het is slechts een illustratie).[/list:u:2802a11e9c] [list:2802a11e9c]Start opnieuw je project en doe verder hetzelfde. Het terminate event gaat nu direct af bij het sluiten van Form2.[/list:u:2802a11e9c] Dat Darkscribe deels gelijk heeft met zijn opmerking zou je op ongeveer dezelfde manier kunnen proberen aan te tonen al zal dat wat minder eenvoudig zijn. Pak daarvoor hetzelfde projectje, maar maar zet onder de knop op Form1 de volgende code. Declareer onder de knop in Form1 een nieuwe instantie van Form2 [code:1:2802a11e9c] dim frmForm as Form2 set frmForm = New Form2 frmForm.show vbModal [/code:1:2802a11e9c] Haal onder de knop van Form2 de set Form2 = nothing weg. Start het project en klik opnieuw op de knoppen. De messagebox moet direct verschijnen bij het sluiten van Form2. In incidentele gevallen zal dit echter pas gebeuren bij het sluiten van Form1. Dit komt omdat de laatste referentie bij het out of scope raken altijd zou moeten verdwijnen. Soms is een programma echter zo intensief dat de garbagecollector niet op tijd ziet dat de referentie verdwenen is en de boel dus nog niet heeft opgeruimd. (Het spreekt voor zich dat bij dit kleine voorbeeldje deze situatie niet snel voor zal komen omdat er daarvoor veel te weinig in het programma gebeurt.) In die gevallen zal het terminateevent pas later afgaan af gaan al zal dat in de praktijk niet vaak voorkomen. Als je het terminate event echter gebruikt hebt om activiteiten binnen je programma te triggeren en je vertrouwt erop dat ze bij het verdwijnen van het formulier ook daadwerkelijk uitgevoerd zijn kan dit leiden tot nauwelijks te traceren fouten. Moraal van het verhaal is dat als je het gedrag je programma voorspelbaar wilt houden je er zelf moet zorgen dat je je objecten opruimt. PS. Hetzelfde verhaal zien we in VB.NET voorbij komen al is garbagecollection daar oneindig veel beter geregeld. Niettemin luidt ook daar de ongeschreven wet: Als een object over een Dispose() beschikt, gebruik hem dan ook.

Beantwoord deze vraag

Weet jij het antwoord op deze vraag? Registreer of meld je aan met je account

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.