WCM Forum

WCM Forum (http://www.wcm.at/forum/index.php)
-   Programmierung (http://www.wcm.at/forum/forumdisplay.php?f=17)
-   -   VB Frage: Wert aus anderem form/Beenden-button/Fortschrittsanzeige (http://www.wcm.at/forum/showthread.php?t=106380)

Nestrus 22.08.2003 14:12

VB Frage: Wert aus anderem form/Beenden-button/Fortschrittsanzeige
 
Hallo

Ich muss gerade ein kleines Backup-Programm in VB stricken und hab damit -wohl weil ich noch nicht so viel und schonn lange gar kein VB mehr gemacht hab- mehr Probleme als ich dachte.
Zuerst die einfachen:

Wiso kann ich in form2
Code:

Dim destp As String
destp = Dir1.List(Dir1.ListIndex)

sagen, aber wenn ich in form3
Code:

destp = Form2.Dir1.List(Dir1.ListIndex)
schreibe, dann kommt immer ein Fehler, er brauche ein Objekt??

Zweitens: Wie macht man einen Beenden-button?
Ich hab in der MSDN die Funktion nicht gefunden, mit der man das geschriebenen Programm beendet.... :(

Und das wohl schwerste:
Nachdem man Quelle und Ziel ausgewählt hat, kopiert es die Ordner.
Ich hätte da gerne eine Fortschrittsanzeige wie man sie auch im Betriebssystem sieht, wenn etwas verschoben wird.
Nach der Anregung einer Homepage hab ich eine Prozedur, der man sagen kann, dass sie x Fortschritt auf einer Skala von y anzeigen kann.
Zur Veranschaulichung:
Wenn die Prozedur zB Balken heißt verhaltet sie sich also so:
Balken 1,4: Das erste Viertel wird ausgemahlt
Balken 1,4: Das zweite, der Balken ist jetzt halb voll.
Balken 2,4: Weil jetzt zwei Schritte gemacht wurden ist er ganz voll.
Außerdem hab ich oberhalb des Balkens (ist ein image) ein label-Feld in dem immmer der Ordner angezeigt wird, der gerade dran ist.
Allerdings funktioniert das nicht so ganz, mit der Schleife wird zwar alles kopiert, allerdings bleibt der Balken und dessen label nach dem ersten mal stehen, der code der nach der For-Schleife ausgeführt werden sollte kommt gar nicht.
Weiß jemand wiso?

Code:

Private Sub Timer1_Timer()
Dim sourcep As String
'destp = Form2.Dir1.List(Dir1.ListIndex)
destp = "c:\test"
Dim ndestp As String

For i = 0 To (Form1.List1.ListCount)
    On Error GoTo error
    sourcep = Form1.List1.List(i)
    Label1.Caption = sourcep
    Fortschritt Picture1, 1, Form1.List1.ListCount
    Set nFSO = New FileSystemObject
    With nFSO
    ndestp = .BuildPath(destp, .GetBaseName(sourcep))
    nFSO.CopyFolder sourcep, ndestp, Overwrite
    End With
Next i

Label1.Caption = "fertig"
Command1.Visible = True

error:
    If Err.Number = 470 Then
        MsgBox ("Zugriff Verweigert.")
        Resume Next
    End If
End Sub

Public Sub Fortschritt(Bild As PictureBox, ByVal _
Fortschritt As Integer, _
Optional ByVal Maximum As Integer = 100)
    Dim Pix As Integer
    Set Bild.Picture = Nothing
    Pix = Int(Fortschritt / (Maximum / (Bild.Width - 5)))
    If Pix > 2 Then
        Bild.Line (1, 1)-(Pix - 2, Bild.Height - 6), RGB(255, 51, 0), BF
    End If
End Sub

Erklärungen: Den Timer hab ich, damit man gleich das aktuellen form zu gesicht bekommt und den Balken überhaupt von Anfang an sieht. (Bevor ich den hatte, sah man bis zum Ende des ersten Schleifendurchlaufs noch das vorherige form.)
In der dritten Zeile steckt der erste von mir beschriebene Fehler, deshalb hab ich die auskommentiert und die vierte geschrieben.
Der Rest sollte klar sein, glaub ich. (Außer die zwei Zeilen nach der For-Schleife, die gehen bei mir nicht, aber das hab ich ja schon gesagt.)

Weiß jemand hier eine Lösung, oder -noch besser- hat sogar jemand eine andere Idee, mit der man einen besseren Balken anzeigen kann?
Meiner zeigt ja nur an, wieviel Ordnern schon kopiert wurden und nicht den tatsächlichen Fortschritt...
Gut wäre ein zweiter Balken, der anzeigt, wie weit das Programm mit dem Ordner ist, der gerade kopert wird aber ich hab keine Ahnung wie man so was machen könnte....


Ich hoffe, ich hab nicht zu viel geschrieben und bedanke mich schon mal

Nestrus, der jetzt merkt wie lange das letzte mal mit VB WIRKLICH schon her ist....

renew 22.08.2003 14:25

kurz und bündig zum 1. Problem:

Du musst so auf das Objekt referenzieren:
Application.Forms("Form2").Dir1.List(Dir1.ListInde x)
:)


zum 2.: sorry, da hab ich jetzt net die Zeit mich rein zu denken - falls mir was einfällt, post ichs dir aber natürlich. :)

werner_q 22.08.2003 14:29

ad 1:

Nicht destp = Form2.Dir1.List(Dir1.ListIndex)
sondern destp = Form2.Dir1.List(Form2.Dir1.ListIndex)

Ich hoffe, es war wirklich so einfach ;)

ad 2: Des is ma zuviel zum lesen. Es gibt ein fertiges Objekt 'ProgressBar' in 'Microsoft Windows Common Controls 5.0 (SP2)'. Vielleicht is des geiler ?

werner_q 22.08.2003 14:34

bisschen mehr gelesen ....

Beenden Button ???

Private Sub Command1_Click()

Unload Me

End Sub

Oder ?

Fortschrittsanzeige, wieviel das OS wirklich schon kopiert hat: Keine Ahnung, Sorry. Weiss gar nicht, ob das in VB überhaupt geht.

Viel Spass sonst noch

Werner

Sesa_Mina 22.08.2003 17:29

Private Sub Command1_Click()
End
End Sub

Beendet das Programm.

werner_q 22.08.2003 18:08

OT @ Sesa_Mina
 
Image (c) by Merle, aber nix möglich gucken by Me, weil Server nix finden by IE ...

Seidl 22.08.2003 18:30

Hier ein Beispiel das rekursiv Files und Unterordner kopiert und den Fortschritt über zwei Progressbars anzeigt. Zusätzlich wird im Ausgangsordner ein Log-File geschrieben.
Die ganze Sache ist natürlich nicht besonders sauber oder schön programmiert aber eigentlich ging's ja nur um Progressbars.

Nestrus 25.08.2003 00:31

Danke alle.
Das erste Problem konnte ich noch nicht ausprobieren, ich hab eigentlich gedacht ich hab mir den code selbst geschickt aber wohl doch nicht....
Aber ich glaube euch dass einer von euch schon recht haben wird! :)
(Vor allem die Erklärung von werner_q klingt logisch.)


Mittlerweile bin ich auch dazu gekommen den Rest auszuprobieren:
@Sesa_Mina: Danke, ein simples end stimmt natürlich, wiso hab ich das blos nicht in der msdn gefunden?

@Seidl:
Besonderen dank an dich, das schaut echt gut aus. ( :cool: ) Ich werde das gleich am Montag einbaun!

deleted_150216 25.08.2003 09:23

ActiveVB

Als mein Geheimtipp!!!

Nestrus 25.08.2003 09:55

Ich hab jetzt das Beispiel von seidl eingebaut.
Allerdings muss ich zwei Sachen ändern: Erstens muss es möglich sein mehrere Ordner (die man zuvor ausgewählt und einer Liste hinzugefügt hat) in einem Rutsch zu kopieren und zweitens nimmt das Beispiel blos die Unterordner, es soll den ausgewählten Ordner aber auch mitkopieren.
Zum ersten nun eine einfache Frage (das zweite krieg ich hoffentlich noch hin):

Ich will eine For Each Next Schleife machen, um die Liste durchzugehn, was muss ich da als Objekt nehmen?

In der MSDN ist ein Beispiel dazu:
Code:

Dim Gefunden, Objekt1, Auflistung1
Gefunden = False  ' Variable initialisieren.
For Each Objekt1 In Auflistung1  ' Alle Elemente durchlaufen.
  If Objekt1.Text = "Hallo" Then  ' Wenn Text gleich "Hallo",
      Gefunden = True  ' Gefunden auf True setzen.
      Exit For  ' Schleife verlassen.
  End If
Next

Wie legt man das jetzt auf die Objekte in Form1.List1 um?

Ich dache, das geht einfach so, aber da kommt immer "Objekt unterstützt diese Eigenschaft oder Methode nicht (Fehler 438)":
Code:

Dim Obj
For Each Obj In Form1.List1


Seidl 25.08.2003 10:53

In Listen muss man leider über den Index arbeiten.

---------------------------------------------
Private Sub Form_Load()
Dim i As Integer
For i = 0 To Me.lstData.ListCount - 1
Debug.Print Me.lstData.List(i)
Next
End Sub
---------------------------------------------


MSDN

Nestrus 25.08.2003 11:51

So hatte ich es vorher auch. Nach dem was in der MSDN stand, dachte ich es geht auch anders...
Naja, jetzt hab ich das mit den einzlenn Files mal gelassen, ich muss jetzt mal eine Version haben, die halbwegs funktioniert.
@seidl: Der code von dir ist aber toll, ich werde ihn gelich einbaun wenn ich etwas Zeit habe.

Jetzt hab ich nur noch zwei einfache Fragen:
Wiso kommt zwischendurch bei dem label, bei dem steht welchen Einrag der Liste er grad sichert so ein weißer Fleck?
Ich hab jetzt extra ein refresh eingebaut...

Und: Wie kann ich es machen, dass sich das Programm merkt, welchen Pfad/welche Pfade man beim letzten Start ausgewählt hat bzw wie kann man für den Zielpfad einen Standardwert vorgeben?
Muss ich für das erste die Pfade in eine Datei schreiben und beim nächten Start auslesen?
Das bekomme ich glaube ich eh noch hin, aber wie schauts mit dem defaultwert aus?

edit: Ich bin wohl wirklich unfähig etwas selbst in der Hilf zu finden..
Wie bekomme ich den Pfad des Ordners in dem da Programm gerade läuft?
(Ich mache gerade das mit der Datei in der gespeichert wird, welche Ordner man gewählt hat.)

Seidl 25.08.2003 12:19

Die Werte in einer Textdatei zu speichern ist sicher eine gute Lösung. Du könntest natürlich auch in die Registry schreiben (am einfachsten mit den "Registry Access Functions") aber mit einem Textfile arbeitet es sich einfacher.

Das mit den weissen Flecken ist mir noch nicht aufgefallen. Ich werde es mir am Abend zu Hause mal ansehen.

Was den Defaultwert betrifft, so würde ich ihn an deiner Stelle auch in der Textdatei ablegen.

Pfad in dem das Programm läuft => App.Path

Nestrus 25.08.2003 12:31

Danke.

Das mit dem Pfad hab ich jetzt schon rausgefunden, ich schau mir grad ein Tutorial an, dass die API Funktionen für Standard-INI Datein erklärt.
Nur weiß ich noch nicht, wie ich der DirListBox einen Standarwert beibringen kann...

Seidl 25.08.2003 12:55

z.B.:
--------------------------
Private Sub Form_Load()
Me.Dir1.Path = "c:\programme\"
End Sub
--------------------------

Könntest du mir bitte den Link zu dem Tutorial posten? Würd' ich mir gerne mal ansehen.

Nestrus 25.08.2003 13:07

Weiße Flecken ist etwas blöd erklärt: Das Label ändert zuerst seien Wert auf den Eintrag in der Liste, der gerade dran kommt, dann allerdings wird es weiß bis es wieder den Wert ändert....

Das was ich gefunden hab ist ein Teil eines VB-Tutorials: http://www.vb-seminar.de/vb_38.htm
Es erklärt den Umgang mit WritePrivateProfileString und so, alledings schat es so as als ob MS davon abratet in INIs zu schreiben, die registry will ich aber nicht benutzen und ein TXT-file scheint mir etwas umständlich wenns da eh schon wa mit INIs gibt...

@Pfad vorgeben: Danke, da hätt ich eigentlich auch selbst draufkommen können, schließlich hab ich so was ja schon gmeacht um die File- mit der Dir- und die mit der DriveListBox abzugleichen... :rolleyes:

wbendl 25.08.2003 14:31

Hi!

Die "offizielle" Methode zum Speicher der zuletzt verwendeten Pfade und Defaulteinstellungen ist ein Eintrag in der Registry.

Textdateien sind aber durchaus eine gute Lösung. Man kann sie als "kleine Datenbank" verwenden. Schreiben und lesen geht ohne großen Aufwand.

Jetzt habe ich noch 3 Denkanstöße:

1.
Wenn ich richtig verstanden habe, gibt es mehere Forms.
Einfacher gehts wahrscheinlich mit einer. Damit ist wahrscheinlich auch das Problem mit dem Label gelöst

2.
Um Quell- und Zielpfad festzulegen könntest du das Windowseigene Dialogfeld verwenden.

3.
Mit der DIR-Funktion kann man die Ordner inklusive Unterordner abarbeiten, ohne das FSO zu verwenden.

Wenn du aber schon das FSO verwendest, könntest du zur Steuerung der Fortschrittsanzeige die zu kopierende Datenmenge verwenden. Das ist wahrscheinlich die exakteste Möglichkeit.
Fragt sich nur, ob es den Aufwand wert ist.

Falls ich irgendwo falsch liege, sags mir.

Wenn du Details wissen willst, melde dich mit möglichst genauen Angaben.
In meinem Programm zum Abgleichen von 2 Ordnern gibt es ziemlich sicher schon eine passende Funktion für den benötigten Zweck.

mfg

WB

Seidl 25.08.2003 14:48

@ wbendl: Windowseigenes Dialogfeld für ORDNER-Auswahl?

wbendl 25.08.2003 14:52

Hi!

Ich hab grad dein Programm getestet. Da ist mir ein Fehler aufgefallen:

Du hast vor dem Beginn der Fehlerbehandlung kein Exit.

Dadurch wird die Fehlerbehandlung durchgeführt, obwohl es gar keinen Fehler gab. Dadurch wird dann ein Fehler ausgelöst.
??? alles klar???

mfg

WB

Nestrus 25.08.2003 15:04

Hallo wbendl.

Zuerst mal danke dass du dir das auch angeschaut hast.
@1: Das Problem hab ich gar nicht mehr, werner_q hatte Recht: Man mus auch in der Klammer vom list das Form davor schreiben.
@2: Naja, man soll ja mehrere Ordner, Laufwerke und Dateien auswählen können. (Auch wenn mein Programm bis jetzt blos Ordner unterstützt...)
Außerdem arbeite ich mit VS6.0, da hat man das doch immer so gemacht, oder?
@3: "die zu kopierende Datenmenge" Klingt gut, doch woher weiß ich, wie viel ich schon kopiert hab? Mir ist nichts dergleichen in der Hilfe aufgefallen....
@4: Nein, das ist mir nicht ganz klar.
Da ich schon lange kein VB mehr gemacht hab, hab ich so gut wie alles nachschaun müssen, das mit der Fehlerbehandlung wurde so auf einer Homepage erklärt. Außerdem merke ich nichts von einem Fehler und es ist mir nicht klar, wieso er den Block nach "error:" abarbeiten soll, wenn ich ihm nicht sag, dass er dahinspringen soll..
Das Problem mit der progressbar und dem weißem label liegt wohl eher daran, dass win das form nicht refresht wenn es mit kopieren beschäftigt ist. (Deshalb sind in er Taskleiste auch noch beide Forms zu sehen.) Allerdings weiß ich nicht, wie ich das ändern könnte.

@all: Das Refresh-Problem ist eh das einzige, welches ich noch hab, ich hoffe ihr könnt mir helfen.
In INIs schreiben geht schon, das lesen zwar noch nicht, aber das bekom ich schon auch noch hin! :)

Seidl 25.08.2003 15:19

Du könntest versuchen die "AutoRedraw"-Property des Formulars auf TRUE zu setzen. Das kann allerdings unter Umständen viel Rechenleistung fressen.

Nestrus 25.08.2003 15:51

Ich hab jetzt mit AutoRedraw und FontTransparent des forms und BackStyle des labels gepsielt, aber geholfen hat es nicht... :(
Der Balken geht jetzt zwar (ist nicht an dem gelegen, sondern an komishcen leeren Einträgen in der Liste) aber das label ist immer noch weiß außer ganz kurz in dem Moment, in dem der Text des lables gewechselt wird. :heul: Der Abbrechen-button ist übrigens auch extrem träge...

Aber immerhin hab ich jetzt das mit dem INI hingekriegt, bald kann ich sagen es kann alles was es muss! (Das mit dem balken ist ja nicht so wichtig...)

Seidl 25.08.2003 16:20

Das mit dem Redraw werde ich mir nochmal ansehen wenn's sich heute abend ausgeht.

Was den Abbrechen-Button betrifft, so kann dieser nur reagieren wenn der Code die Steuerung an andere Prozesse abgibt (DoEvent).

wbendl 25.08.2003 16:21

Hi!

Ich denke auch das Problem mit dem weißen Fleck ist bei einem Formular leichter zu lösen.

Ich hab erst nachher gesehen, daß auch einzelne Dateien als Quelle ausgewählt werden können.
Mehrere Ordner hintereinander sind aber auch mit dem Dialogfeld kein Problem.

Mit FSO erfährst du die Dateigröße.
Zur Anzeige vird ein ProgressBar verwendet.
Ich meine aber der Aufwand lohnt sich nicht wirklich. Hauptsache der User sieht, daß das Progamm arbeitet.

Wenn vor der Sprungmarke kein Exit Sub oder Exit Function steht, wird der Code weiter ausgeführt.

@seidl

Dim hWnd As Long

Private Type BrowseInfo
hwndOwner As Long
pIDLRoot As Long
pszDisplayName As Long
lpszTitle As Long
ulFlags As Long
lpfnCallback As Long
lParam As Long
iImage As Long
End Type

Private Const BIF_RETURNONLYFSDIRS = 1
Private Const MAX_PATH = 260

Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)

Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, _
ByVal lpString2 As String) As Long

Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long

Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, _
ByVal lpbuffer As String) As Long

Property Get SelectedFolder() As String

SelectedFolder = BrowseForFolder(hWnd, "Bitte wählen Sie einen Ordner:")

End Property

Private Function BrowseForFolder(hwndOwner As Long, sPrompt As String) As String

Dim iNull As Integer
Dim lpIDList As Long
Dim lResult As Long
Dim sPath As String
Dim udtBI As BrowseInfo

With udtBI
.hwndOwner = hwndOwner
.lpszTitle = lstrcat(sPrompt, "")
.ulFlags = BIF_RETURNONLYFSDIRS
End With

lpIDList = SHBrowseForFolder(udtBI)

If lpIDList Then
sPath = String$(MAX_PATH, 0)
lResult = SHGetPathFromIDList(lpIDList, sPath)
Call CoTaskMemFree(lpIDList)
iNull = InStr(sPath, vbNullChar)
If iNull Then sPath = Left$(sPath, iNull - 1)
End If

BrowseForFolder = sPath

End Function


mfg

WB

Seidl 25.08.2003 16:57

@ wbendl: Besten Dank für den API-Aufruf! :) Den kann ich sicher nochmal brauchen.

Nestrus 26.08.2003 16:38

Bis auf das Refresh-Problem ist es jetzt eh schon ganz gut.
Leider kann ich hier nicht das fetig gepackte Setupfile anhängen, weil es ja ganze 652KB hat. (Und das, obwohl ich sogar eine andere progressbar genommen hab.)

Das Refreshproblem ist eigentlich gar nicht so schlimm, denn bei kleieren Kopierjobs fällt es gar nicht auf und sowiso sollte das Programm ja eigentlich erst gerstartet werden, wenn man am gehen ist damit es über Nacht die tägliche Sicherung erledigt.


Noch mals vielen Dank für eure Hilfe!
(Ein Tipp wegen dem Problem wäre natürlich schon noch super - ich will ja etwas gescheites machen...)


PS: Wer das Setup will: Ich kann es ja per mail verschicken...
PPS: Die Pfade sind dan standardmäßig auf d: (Quelle) und n: Ziel gestellt, also nicht wundern wenn eine Fehlermeldung kommt...

Nestrus 28.08.2003 11:10

Hmm... denn keiner einen Idee, wie man diesen kleinen Schönheitsfehler ausbessern könnte?

Seidl 28.08.2003 11:20

Aufgeschoben ist nicht aufgehoben. Bin leider zur Zeit ziemlich gestresst. Spätestens am Wochenende sollte ich aber Zeit haben, mir die Sache nochmal anzusehen.

Nestrus 29.08.2003 08:02

Ja okay, ist schon früh genug, ich wollte keine Kritk üben oder jemanden stressen...
Ich bin mir im Forum blos gewohnt die Beiträg immer nach oben zu schieben.

wbendl 29.08.2003 10:40

Hi!

Schick deinen Code an wb-soft@blackbox.net, ich schau mir das am Wochenende an.

Dein Beispiel hab ich mir angesehen. Wie schon gesagt, ich würde dafür nur eine Form verwenden. Dadurch würde das Problem wahrscheinlich von selbst verschwinden.

mfg

WB


Alle Zeitangaben in WEZ +2. Es ist jetzt 17:20 Uhr.

Powered by vBulletin® Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
© 2009 FSL Verlag