Lähes jokaisessa pelissä on latausta ilmaiseva progressbar-tyyppinen jutska, ja olen aina ollut kiinnostunut _miten_ toteutetaan että progressbar etenee sen mukaan ja sen mukaisella vauhdilla kun dataa ladataan, mutta en ole löytänyt yhtään mitään, enkä keksinyt yhtään mitään. Onko kellään mitään aavistustakaan ? Voidaan tässä yhdessä suunnitella jos ei muuten.
Kieltämättä olen samaa aina miettinyt.
Veikkaisin, että niissä isoissa peleissä on niin monta eri funktiota, jotka vievät aikaa, että jokaisen funktiokutsun väliin laitetaan tyyliin progress++.
(joo ei ajatus muutenkaa kulje tähän aikaan, peti kutsuu ->)
Kun datan kokonaismäärä ja tietyllä hetkellä ladatun datan määrä tunnetaan, jälkimmäinen jaetaan ensimmäisellä, jolloin saadaan latauksen valmistumista ilmaiseva suhdeluku väliltä 0-1. Tuo suhdeluku ilmaisee sitten, kuinka pitkä progressbar piirretään. Progressbarin_pituus = suhdeluku * progressbarin_pituus_latauksen_ollessa_valmis.
Palkkia täytyy tosiaan päivittää aina, kun dataa on taas ladattu vähän lisää. Yksinkertaisin tapa on sijoittaa koodiin ihan suoria lukuarvoja (esim. näytä tässä kohtaa "37 % ladattu"), mutta kaikenlaisia hunajavohvelin ehdottaman kaltaisia kaavoja voi toki myös käyttää. Jos ainoa ladattava on jokin todella suuri yksittäinen tiedosto, niin en kyllä tiedä, miten latauspalkin saa silloin toimimaan, jos koko lataus tapahtuu yhdellä ohjelmarivillä.
Oletteko muuten huomanneet, että latauspalkit eivät ole aina luotettavia, ainakaan jos tarkoituksena on kuvastaa ajan kulumista. Moni latauspalkki jumittuu johonkin kohtaan pitkäksi aikaa ja välillä taas liikkuu suuria harppauksia silmänräpäyksessä. Semmoistakin näkee (esim. Internet Explorer käyttäytyy muistaakseni näin), että latauspalkin mukaan lataus muka edistyy, mutta todellisuudessa ei tapahdu mitään.
Hunajavohvelin kekkaus on yksinkertainen mutta tuskin se menee tuon helpommin. VB:een pienissä ohjelmissa (itse olen tekemässä isompaa ohjelmaa VB:eellä mutta siinä ratkaisin että laittaa progressbarin "lataamaan" 4sek ajan 25:den hyppäyksen, samalla kun splash-ikkunan Form_Loadissa lukee form2.Show [enter] form2.Hide ...) ei ole käyttöä.
Antti Laaksonen kirjoitti:
Oletteko muuten huomanneet, että latauspalkit eivät ole aina luotettavia, ainakaan jos tarkoituksena on kuvastaa ajan kulumista. Moni latauspalkki jumittuu johonkin kohtaan pitkäksi aikaa ja välillä taas liikkuu suuria harppauksia silmänräpäyksessä. Semmoistakin näkee (esim. Internet Explorer käyttäytyy muistaakseni näin), että latauspalkin mukaan lataus muka edistyy, mutta todellisuudessa ei tapahdu mitään.
Ikävän tuttu tapaus, harvemmin todella eritoten selainten palkit toimivat, mutta ne taitavatkin olla pelkästään kuvastamaan että toiminta on yllä vaikka palkki ei liiku.
vielä lisäys noihin edellisiin..
Itse olen käyttänyt usein pictureboxia latausta osoittamaan.. DoEventsiä käyttämällä sen "liukuminen" onnistuu helposti (ei tosin varmaan kaikkein nopein vaihtoehto) ilman timereitä..
Antti Laaksonen kirjoitti:
Oletteko muuten huomanneet, että latauspalkit eivät ole aina luotettavia, ainakaan jos tarkoituksena on kuvastaa ajan kulumista. Moni latauspalkki jumittuu johonkin kohtaan pitkäksi aikaa ja välillä taas liikkuu suuria harppauksia silmänräpäyksessä. Semmoistakin näkee (esim. Internet Explorer käyttäytyy muistaakseni näin), että latauspalkin mukaan lataus muka edistyy, mutta todellisuudessa ei tapahdu mitään.
Ei noista aikaa kuvastavista latauspalkeista kauhesti iloa ole, sillä sitä ennustetta on mahdotonta laskea kun ei voi koskaan tietää mitä teet koneella juuri silloin, esim jos kesken latauksen ajat jotain raskasta, niin tästä huolimatta latauspalkin täytyy mennä eteenpäin tasasta vauhtia, ja lopulta jäädä jumittamaan siihen 100%:iin kunnes ohjelma on oikeasti ladannut.
Jos tuon jumituksen korjaisi, niin pitäisi sitä latauspalkkia vetää taaksepäin, tai sitten pysäyttää, ja jatkaa taas myöhemmin, mutta sitten ollaan taas samassa tilanteessa kuin sillä latauspalkilla joka ei kuvasta aikaa :P Eli parempi vain tehdä sellainen palkki joka kuvastaa kuinka paljon dataa on ladattu, ei siis aikaa, vaan tavaran määrää.
Tein pienen ohjelman, joka on hyvin yksinkertainen.
Tee Formi, jossa 2 PictureBox, 1 Label ja 1 CommandButton.
Ohjelma muuttaa kuvaa (pic), ja näyttää kuvassa PicPros tapahtumien etenemisen.
Formi
Option Explicit Private Sub ComStart_Click() PrKirj = 0 PX = Frm.Pic.ScaleWidth PY = Frm.Pic.ScaleHeight Jakaja = 1 'Jos iso kuva, muuta esim Jakaja = 32 KoMax = (PX / Jakaja) * (PY / Jakaja) LaskePros Colorize LaskePros End Sub Private Sub Form_Load() Pic.ScaleMode = vbPixels 'Kuva, jota muokataan With PicPros .ScaleMode = vbPixels 'Process bar W = .ScaleWidth H = .ScaleHeight End With lPR.Alignment = 2 ' Center lPR.Caption = "0 %" End Sub Private Sub Form_Unload(Cancel As Integer) End End Sub
moduuliin..
Option Explicit Public Declare Function GetPixel Lib "gdi32" (ByVal HDC As Long, ByVal X As Long, ByVal Y As Long) As Long Public Declare Function SetPixel Lib "gdi32" (ByVal HDC As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long Public Type t_RGB R As Long G As Long B As Long End Type Public W%, H% 'Prosessipalkin koko Public PX&, PY& 'Kuvan Koko Public KoMax As Long ' Kokonaismäärä Public PrKirj As Long ' Kirjoitettujen määrä Public Jakaja As Integer 'Millä luvulla jaetaan? Sub LaskePros() Dim L&, I%, C&, Pr% L = (PrKirj / KoMax) * 100 I = L ': If I > 100 Then I = 100 'Varmistetaan, että väytetään vain 100 % Frm.lPR.Caption = Str$(I) & "%" If L > 0 Then Pr = W / (100 / L) Else Pr = 0 Frm.PicPros.Line (0, 0)-(Pr, H), vbGreen, BF End Sub Sub Colorize() 'Muuttaa kuvaa, hauskan näköiseksi Dim C2&, X%, Y% Dim C As t_RGB, B As t_RGB B = ChangeToRGB(vbBlue) Do Do C2 = GetPixel(Frm.Pic.HDC, X, Y) C = ChangeToRGB(C2) C.B = Abs(C.G - B.R) Xor 255& C.R = Abs(C.G - B.B) Xor 255& C.G = Abs(C.B - B.B) Xor 255& SetPixel Frm.Pic.HDC, X, Y, RGB(C.R, C.G, C.B) X = X + 1 'Jos kuva kovin suuri suurennettava lisäysväliä, jotta PrKirj ei aiheuttaisi ylivuotoa! 'Lisätään tapahtumien määrää esim. 32 pikselin välein. If Int(X / Jakaja) = X / Jakaja And Int(Y / Jakaja) = Y / Jakaja Then PrKirj = PrKirj + 1 LaskePros End If Loop Until X = PX Frm.Pic.Refresh Y = Y + 1 X = 0 DoEvents Loop Until Y = PY 'Varmistetaan vielä, että näytetään 100% PrKirj = KoMax LaskePros End Sub 'Muutetaan väri RGB-arvoiksi Function ChangeToRGB(Color&) As t_RGB Dim C As t_RGB C.R = Color Mod 256& C.G = ((Color And &HFF00) / 256&) Mod 256& C.B = (Color And &HFF0000) / 65536 If C.R < 0 Then C.R = 0 If C.G < 0 Then C.G = 0 If C.B < 0 Then C.B = 0 ChangeToRGB = C End Function
Aihe on jo aika vanha, joten et voi enää vastata siihen.