Archief - Visual Basic 2008

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

bjornusken

Legacy Member
Beste,

Kheb een vraagje over Visual Basic 2008! Khoop datk hiervoor op de juiste plek zit, anders gelieve mij door te verwijze naar de juiste plek ;)

Ik moet een opdracht maken in visual basic (dus iets programmeren), we hebben een eindresultaat van de docent mee gekrege, als we dat van hem testen (we zien zijn programmacode NIET, we hebbe enkel een executable), dus de situatie is zo: als we op een knop klikke wordt er een bestand ingeleze in een venster (tis een lange lijst) dus al die zinnen worden onder elkaar weergegeven (er is ook een scrollbar voorzien) maar zodra da venster die zinne weergeeft, gaat het scherm ineens mee naar benede, dus ge moet trug naar boven scrollen om de eerste zin te zien! maar als ik dat programmeer (da bestand inleze en al lukt allemaal) maar hoe moet je ervoor zorge dat het scherm mee naar benede gaat met de tekst, zoda ge trug na bove moet scrolle? dat lukt me niet :(

alvast bedankt

grtz :applause:

Albireo

Legacy Member
Nadat je alle tekst ingelezen hebt, doe je dit:

Code:
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();

bjornusken

Legacy Member
Albireo zei:
Nadat je alle tekst ingelezen hebt, doe je dit:

Code:
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();

thx, dat is inderdaad ongeveer wat ik wilde , maar hoe kan ik er voor zorge dat ik elke lijntje apart in 1 keer kan inleze??
alsk jou code gebruik, dan lees ik in 1 keer dat bestand in en dan kom ik inderdaad onderaan het ingelezen bestand te staan, maar nu wil ik dat elk lijntje afzonderlijk geleze wordt (maar wel heel het bestand)
khoop dakt wa duidelijk em uitgelegd :p :D

grtz :help:

enticore

Legacy Member
Als je die tekstfile inleest met een loop, kan je dan niet gewoon de ScrollToCaret() method gebruiken telkens je een lij hebt ingelezen?

Gonzo

Legacy Member
Heeft geen nut, tenzij het een groot bestand is gaat da veel te snel om het effect da gij wilt te bekomen, EN single threaded ziet ge daar toch niks van want de GUI refresht niet.

Lijn per lijn inlezen --> System.IO.StreamReader

Albireo

Legacy Member
Ik had niks beters te doen dus ik heb wat meer research gedaan. Een TextBox heeft een AppendText()-methode en dat is blijkbaar de beste manier om automatisch mee te scrollen met de tekst die je invoegt. Ik heb het hele proces van lijn per lijn inlezen in een aparte thread gezet zodat de UI niet blokkeert.

Known issues: this.Invoke(d, new object[] {...}); werpt een uitzondering (<-- dat klinkt beter in het Engels) als je het formulier sluit terwijl het nog aan het inlezen is. Controleren op IsDisposed of IsDisposing helpt niet.

Code:
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace ASyncControlAccess {
    public partial class Form1 : Form {
        private delegate void TextBoxAccessDelegate(string text);
        private delegate void ButtonAccessDelegate(bool enable);
        public Form1() {
            InitializeComponent();
            openFileDialog.CheckFileExists = true;
            openFileDialog.CheckPathExists = true;
            openFileDialog.DereferenceLinks=true;
            openFileDialog.Filter="Text files (*.txt)|*.txt|All files|*.*";
        }

        private void openFileButton_Click(object sender, EventArgs e) {
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                Thread readThread = new Thread(new ThreadStart(ReadLineByLine));
                readThread.IsBackground = true;
                readThread.Start();
            }
        }
        private void ReadLineByLine() {
            EnableButton(false);
            SetText("");
            using (StreamReader reader = new StreamReader(openFileDialog.OpenFile())) {
                while (!reader.EndOfStream) {
                    SetText(reader.ReadLine() + Environment.NewLine);
                    System.Threading.Thread.Sleep(50);
                }
            }
            EnableButton(true);
        }
        private void SetText(string text) {
            if (this.fileTextBox.InvokeRequired) {
                TextBoxAccessDelegate d = new TextBoxAccessDelegate(SetText);
                this.Invoke(d, new object[] { text });
            }
            else {
                fileTextBox.AppendText(text);
            }
        }
        private void EnableButton(bool enable) {
            if (this.openFileButton.InvokeRequired) {
                ButtonAccessDelegate d = new ButtonAccessDelegate(EnableButton);
                this.Invoke(d, new object[]{enable});
            }
            else {
                openFileButton.Enabled = enable;
            }
        }
    }
}

bjornusken

Legacy Member
Albireo zei:
Ik had niks beters te doen dus ik heb wat meer research gedaan. Een TextBox heeft een AppendText()-methode en dat is blijkbaar de beste manier om automatisch mee te scrollen met de tekst die je invoegt. Ik heb het hele proces van lijn per lijn inlezen in een aparte thread gezet zodat de UI niet blokkeert.

Known issues: this.Invoke(d, new object[] {...}); werpt een uitzondering (<-- dat klinkt beter in het Engels) als je het formulier sluit terwijl het nog aan het inlezen is. Controleren op IsDisposed of IsDisposing helpt niet.

Code:
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace ASyncControllAccess {
    public partial class Form1 : Form {
        private delegate void TextBoxAccessDelegate(string text);
        private delegate void ButtonAccessDelegate(bool enable);
        public Form1() {
            InitializeComponent();
            openFileDialog.CheckFileExists = true;
            openFileDialog.CheckPathExists = true;
            openFileDialog.DereferenceLinks=true;
            openFileDialog.Filter="Text files (*.txt)|*.txt|All files|*.*";
        }

        private void openFileButton_Click(object sender, EventArgs e) {
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                Thread readThread = new Thread(new ThreadStart(ReadLineByLine));
                readThread.IsBackground = true;
                readThread.Start();
            }
        }
        private void ReadLineByLine() {
            EnableButton(false);
            SetText("");
            using (StreamReader reader = new StreamReader(openFileDialog.OpenFile())) {
                while (!reader.EndOfStream) {
                    SetText(reader.ReadLine() + Environment.NewLine);
                    System.Threading.Thread.Sleep(50);
                }
            }
            EnableButton(true);
        }
        private void SetText(string text) {
            if (this.fileTextBox.InvokeRequired) {
                TextBoxAccessDelegate d = new TextBoxAccessDelegate(SetText);
                this.Invoke(d, new object[] { text });
            }
            else {
                fileTextBox.AppendText(text);
            }
        }
        private void EnableButton(bool enable) {
            if (this.openFileButton.InvokeRequired) {
                ButtonAccessDelegate d = new ButtonAccessDelegate(EnableButton);
                this.Invoke(d, new object[]{enable});
            }
            else {
                openFileButton.Enabled = enable;
            }
        }
    }
}


dank je wel :p maar euh, kzou echt ni weten hoe ik dat in mijn programmacode zou moeten zetten...
En aangezien het program morgevroeg klaar moet zijn zal dit voor een andere keer zijn :p maar als je wilt mag je nog wel uitlegge hoe ik dit toch moet doen (mss handig voor later) !!

Thx mate

grtz:bow:

Gonzo

Legacy Member
Euhm als ge da zelfs nie weet, dan gebruikt ge het best ook niet, want dan geloven ze nooit da ge da zelf gedaan hebt :)

bjornusken

Legacy Member
Gonzo zei:
Euhm als ge da zelfs nie weet, dan gebruikt ge het best ook niet, want dan geloven ze nooit da ge da zelf gedaan hebt :)

da speelt toch gene rol of ik da nu zelf gedaan em of ni, tis de bedoeling dak da leer e..... die opdrachte moge we same me andere klasgenote make, dus waarom zouwk da ook ni in dit forum moge vrage? wa ik hier kan mee pikke is toch mooi meegenome zeker?! en tis ni datk nu moet gebruike he, mss in een toekomstig project (soort eindwerk) kan dat mss wel handig zijn, of zo'n extraatje..
mja ;)

grtz

Gonzo

Legacy Member
bjornusken zei:
da speelt toch gene rol of ik da nu zelf gedaan em of ni, tis de bedoeling dak da leer e.....

Uiteraard, maar er wordt vanuit gegaan dat 99% van de mensen die dat doen, gewoon klakkeloos code copy/pasten en er nooit ofte nimmer een letter van lezen, laat staan begrijpen. Dat kan dus weldegelijk in uw nadeel spelen bij een evaluatie... Vandaar dat 'k het zei ;)

Albireo

Legacy Member
Code:
        private void openFileButton_Click(object sender, EventArgs e) {
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                Thread readThread = new Thread(new ThreadStart(ReadLineByLine));
                readThread.IsBackground = true;
                readThread.Start();
            }
        }

Hier begint het. Als je op de knop "openFileButton" klikt wordt de OpenFiledialog genaamd "openFileDialog" geopend en kan je een bestand kiezen. Als je een bestand gekozen hebt, wordt er een nieuwe thread aangemaakt waarin de code wordt uitgevoerd om lijn per lijn in te lezen.


Code:
        private void ReadLineByLine() {
            EnableButton(false);
            SetText("");
            using (StreamReader reader = new StreamReader(openFileDialog.OpenFile())) {
                while (!reader.EndOfStream) {
                    SetText(reader.ReadLine() + Environment.NewLine);
                    System.Threading.Thread.Sleep(50);
                }
            }
            EnableButton(true);
        }

Ik disable eerst de knop zodat je geen ander bestand kan openen terwijl hij nog een bestand aan het inlezen is (al zou het geen "kwaad" kunnen om meerdere bestanden tegelijk in te lezen (en het zou leerijk kunnen zijn omdat je dan multithreading echt aan het werk ziet)). Ik maak de TextBox leeg en dan maak ik een StreamReader aan waarmee ik het bestand geselecteerd in de OpenFileDialog kan inlezen. Zolang het einde van het bestand niet bereikt is, lees ik de volgende lijn in en zet die in de TextBox. Na elke lijn pauzeer ik even. Omdat dit een aparte thread is, heeft dit geen gevolgen voor het programma, de UI blijft vlot toegankelijk. Eens alles ingelezen is, enable ik de knop weer zodat je een ander bestand kan kiezen.

Code:
        private void SetText(string text) {
            if (this.fileTextBox.InvokeRequired) {
                TextBoxAccessDelegate d = new TextBoxAccessDelegate(SetText);
                this.Invoke(d, new object[] { text });
            }
            else {
                fileTextBox.AppendText(text);
            }
        }
Dit stukje code heb ik op MSDN gevonden. De UI is enkel toegankelijk vanop de thread waarop de UI draait. Maar we moeten de TextBox kunnen aanpassen vanaf een aparte thread. Daarom hebben we wat speciale code nodig en meer bepaald Control.Invoke(). De delegate die hier gebruikt wordt, is gedefinieerd als
Code:
private delegate void TextBoxAccessDelegate(string text);
Zie http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
(En blijkbaar is dit niet de meeste efficiënte manier om met Invoke() om te gaan: http://msmvps.com/blogs/duniho/archive/2008/09/12/msdn-s-canonical-technique-for-using-control-invoke-is-lame.aspx)


nieuwe versie:
Code:
        private void SetText(string text) {
            this.Invoke((MethodInvoker)delegate() {
                fileTextBox.AppendText(text);
            });
        }
en die TextBoxAccessDelegate mag je wegsmijten. :)


Ik hoop dat deze uitleg je verder helpt.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan