[PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

[PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hallo und guten Abend @all,

Ich bin mir bewusst, meine Fragen sind etwas skurril und befassen sich mit recht altem Code zum Teile.
Da ich gerade auch da meistens das passende gefunden hatte.

Und so verhält es sich leider auch dieses Mal wieder.
Es geht im Wesentlichen um einen Patcher Code.

Da ist es so, dass der bestehende Code, folgt am Ende, aus zwei Prozeduren besteht.
Einmal Patch erstellen, einmal Patch gebrauchen.

Nun, der Knackpunkt, das Verzeichnis, Source resp. Target Files und Patch Destination sind in der Procedure nicht fix.
Wenn ich jetzt eine GUI für mich erstelle, da ich mit Konsolen Programmierung zu wenig Erfahrung habe, muss ich diese
drei Werte herleiten. (GUI = OK)

Aber ich bin natürlich die ganze Zeit am Suchen und verstehen wie ich denn diese Procedure jetzt ansprechen soll.
Ich stehe wieder mal auf dem Schlauch, wahrlich habe ich mich wohl auch komplett ins AUS manövriert, das mag auch sein.

Ich habe das Ganze in zwei Dateien, der Procedure sowie meinem GUI. (Danke an Axolotl der mir immer wieder mal auf den Hinterkopf schlägt.)
Er hatte mir etwas geholfen mit der GUI.

Aber auch Euch allen, welche mir immer wieder mit neuen Erkenntnissen beflügelt weiter zu machen an meinem kleinen Projekt, das
leider sich ausgeweitet hatte.

Sorry, ich schweife ab.......

Frage: Wie kann ich diese Procedure ansprechen, nachdem ich die Verzeichnisse ausgewählt habe?

Vielen lieben Dank und Euch allen ein ganz schönes Wochenende
Grüsse aus Bern

Christian

PS: Die beiden einzigen Teile an welchen ich bis jetzt Hand angelegt hatte, waren die GUI sowie create-patch.
[/UPDATE: gesamter Source vorhanden auf pcloud mit Link. [\UPDATE]

Patch Maker Source

GUI:

Code: Alles auswählen

;- Top
; -----------------------------------------------------------------------------
;           Name:
;    Description:
;         Author:
;           Date: 2024-08-22
;        Version:
;     PB-Version:
;             OS:
;         Credit:
;          Forum:
;     Created by: IceDesign
; -----------------------------------------------------------------------------

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;- Enumerations
Enumeration Window
  #Window_0
EndEnumeration

Enumeration Gadgets
  #Btn_Execute
  #Btn_Path_1
  #Btn_Path_2
  #Str_Path_1
  #Str_Path_2
  #Str_Path_3
EndEnumeration

;- Global
Global InitialPath1$
Global Path1$
Global InitialPath2$
Global Path2$
Global InitialPath3$
Global Path3$


;- Declare
Declare Resize_Window_0()
Declare Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)

;- Procedure Main Window
Procedure Resize_Window_0()
  Protected Window_0_WidthIni = 540, Window_0_HeightIni = 400
  Protected ScaleX.f, ScaleY.f

  ScaleX = WindowWidth(#Window_0) / Window_0_WidthIni : ScaleY = WindowHeight(#Window_0) / Window_0_HeightIni
  ResizeGadget(#Btn_Path_1, ScaleX * 40, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Path_2, ScaleX * 170, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Execute, ScaleX * 320, ScaleY * 270, ScaleX * 130, ScaleY * 45)
EndProcedure

;- Procedure Open Main Window
Procedure Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)
  If OpenWindow(#Window_0, X, Y, Width, Height, "Title", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    ButtonGadget(#Btn_Path_1, 40, 270, 100, 45, "Path 1")
    ButtonGadget(#Btn_Path_2, 170, 270, 100, 45, "Path 2")
      DisableGadget(#Btn_Path_2, #True)
    ButtonGadget(#Btn_Execute, 320, 270, 130, 45, "Execute")
      DisableGadget(#Btn_Execute, #True)

    StringGadget(#Str_Path_1, 8,  80, 306, 20, Path1$, #PB_String_ReadOnly) ;Path$
    StringGadget(#Str_Path_2, 8,  100, 306, 20, Path2$, #PB_String_ReadOnly) ;Path$
    StringGadget(#Str_Path_3, 8,  120, 306, 20, Path3$, #PB_String_ReadOnly) ;Path$

    BindEvent(#PB_Event_SizeWindow, @Resize_Window_0(), #Window_0)
    PostEvent(#PB_Event_SizeWindow, #Window_0, 0)
    ProcedureReturn #True
  EndIf
EndProcedure

; XIncludeFile "createpatch.pbi"

CompilerIf #PB_Compiler_IsMainFile
;- Main Program
If Open_Window_0()

  ;- Event Loop
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break

        ;-> Event Gadget
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Btn_Path_1   ; Path 1
            InitialPath1$ = "C:\Users\cschaer\Documents\my Basic\PureBasic"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Path1$ = PathRequester("Bitte wählen Sie einen Pfad aus", InitialPath1$)
            If Path1$
              SetGadgetText(#Str_Path_1, Path1$) 
              DisableGadget(#Btn_Path_1, #True)   ;<-- disable ??? 
              DisableGadget(#Btn_Path_2, #False)  ;<-- 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf

          Case #Btn_Path_2   ; Path 2
            InitialPath2$ = "C:\Users\cschaer\Documents\my Basic\PureBasic"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Path2$ = PathRequester("Bitte wählen Sie einen Pfad aus", InitialPath2$)
            If Path2$
              SetGadgetText(#Str_Path_2, Path2$) 
              DisableGadget(#Btn_Path_2, #True) 
              DisableGadget(#Btn_Execute, #False) 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf
          Case #Btn_Execute   ; Execute
            InitialPath3$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\my Patch\new"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Path3$ = PathRequester("Bitte wählen Sie einen Pfad aus", InitialPath3$)
            If Path3$
               SetGadgetText(#Str_Path_3, Path3$) 
               DisableGadget(#Btn_Execute, #True) ;<-- 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf
        EndSelect

    EndSelect
  ForEver
EndIf
CompilerEndIf
create Procedure:

Code: Alles auswählen

;createpatch(file1.s,file2.s,patchpath.s)
;file1 = Pfad zur alten Version einer Datei
;file2 = Pfad zur neuen Version einer Datei
;Patchpath = Speicherpfad des Patches 

Procedure createpatch(Path1$,Path2$,Path3$)
  Protected MemPoint.l = 0 , LenOfFile1.l , LenOfFile2.l
  Protected ByteOld.b , ByteNew.b
  Protected *Data1, *Data2, *Data3
  
  UseMD5Fingerprint() 
  
  ;Wenn file1 = file2, Prozedure verlassen
  If FileFingerprint(Path1$, #PB_Cipher_MD5) = FileFingerprint(Path2$,#PB_Cipher_MD5)
    ProcedureReturn #False
  EndIf
  
  ReadFile(0,Path1$)
  ReadFile(1,Path2$)
  LenOfFile1 = Lof(0)
  LenOfFile2 = Lof(1)
  *Data1 = AllocateMemory(LenOfFile1)
  *Data2 = AllocateMemory(LenOfFile2)
  *Data3 = AllocateMemory(LenOfFile2+33)  ; '+33' für den MD5 Header
  ReadData(0,*Data1,LenOfFile1)
  ReadData(1,*Data2,LenOfFile2)
  
  PokeS(*Data3,FileFingerprint(Path1$,#PB_Cipher_MD5)) ; Speichert MD5Fingerprint
  
  While MemPoint < LenOfFile2
    
    If MemPoint < LenOfFile1
      ByteOld = PeekB(*Data1+MemPoint)
    Else
      ByteOld = 0
    EndIf
    
    ByteNew = PeekB(*Data2+MemPoint)
    
    If ByteOld = ByteNew
      PokeB(*Data3+33+MemPoint,0) ;ja nicht den MD5 Header überschreiben
    Else
      PokeB(*Data3+33+MemPoint,ByteOld-ByteNew)
    EndIf
    
    MemPoint = MemPoint + 1
    
  Wend
  
  CreatePack(0,Path3$ ,9) 
  AddPackMemory(0,*Data3,LenOfFile2+33,Path2$)
  ClosePack(0)
  CloseFile(0)  ;keine Ahnung wann man am besten file1 u. file2 closed              
  CloseFile(1)
  FreeMemory(*Data1)
  FreeMemory(*Data2)
  FreeMemory(*Data3)
  ProcedureReturn #True
EndProcedure
patch it:

Code: Alles auswählen

;patchit(file1.s,pak.s)
;file1 = Pfad zur alten Version einer Datei
;pak = Pfad zum Patch

Procedure patchit(file1.s,pak.s)
  Protected ByteOld.b , ByteDiff.b
  Protected PakMD5.s
  Protected PakSize.l, i.l
  Protected *Patch, *DataFile
  
  OpenPack(0,pak)
  *Patch = NextPackEntry(0)
  PakSize = PackEntrySize(0)
  PakMD5 =  PeekS(*Patch,32)
  
  If FileFingerprint(file1, #PB_Cipher_MD5) <> PakMD5  ;MD5 überprüfen
    ProcedureReturn #False
  EndIf
  
  CopyFile(file1,file1+".backup") ;Backup erstellen
  OpenFile(0,file1)
  
  For i = 33 To PakSize ;Nachdem MD5Header weiterlesen
    FileSeek(0,i-33)
    ByteOld = ReadByte(0)
    ByteDiff = PeekB(*Patch+i)
    FileSeek(0,i-33)
    WriteByte(0,ByteOld-ByteDiff)
  Next i
  
  If (PakSize-33) < Lof(0)  ;Wenn Original-Datei > Update Datei, dann....
    FileSeek(0,0)
    *DataFile = AllocateMemory(PakSize-33)
    ReadData(0,*DataFile,PakSize-33)
    CloseFile(0)
    DeleteFile(file1)
    CreateFile(0,file1)
    WriteData(0,*DataFile,PakSize-33)
  EndIf
  
  CloseFile(0)
  ClosePack(0)
  FreeMemory(*Patch)
  FreeMemory(*DataFile)
  ProcedureReturn #True
EndProcedure
Zuletzt geändert von ChrigiGee am 31.08.2024 20:07, insgesamt 2-mal geändert.
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
jacdelad
Beiträge: 404
Registriert: 03.02.2021 13:39
Wohnort: Riesa
Kontaktdaten:

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von jacdelad »

Ich bin vielleicht gerade etwas zu sehr gelangweilt und es ist auch gerade kurz nach Mitternacht, aber ich verstehe die Frage nicht. Willst du wissen, wie du die Funktion, die du selbst geschrieben hast, aufrufst? Also

Code: Alles auswählen

patchit(MeineDatei,MeinPak)
?
Guten Morgen, das ist ein schöner Tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3 TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von HeX0R »

Wenn Du Fragen hast, bitte kurz und knapp auf den Punkt gebracht.
Bei Deinen Texten steige ich (und vermutlich auch viele andere) spätestens bei dem zweiten Absatz aus und was auch immer danach kommt (vermutlich die eigentliche Frage), interessiert mich dann nicht mehr.

Bedenke:
Das ist ein Programmier-Forum, kein Philosophie-Forum.
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Prozedure mit variabler Abhängigkeit ? | Nachtrag Erklärung

Beitrag von ChrigiGee »

Hallo HeX0R,
Hallo jacdelad,

Ich glaube, es war auch etwas der Zeit geschuldet, dass ich mich einem zu langen Text hingegeben hatte.
Ich hätte wohl doch besser gewartet auf heute Morgen.

Bestehender Code Teile sind die beiden Proceduren.
Mein Code ist "nur" die GUI

Die Procedure alleine kann ich nicht ein Verzeichnis übergeben, also machte ich dazu eine GUI.
Die GUI ist momentan so weit wie möglich von Schnickschnack entfernt, sodass ich schneller zum Resultat komme.

Wie kann ich jetzt aber von der GUI aus nach dem das letzte Verzeichnis bekannt ist zurück zur Procedure und dass diese verarbeitet würde?
Oder habe ich etwas komplett Essenzielles in den beiden Proceduren übersehen, dass die GUI himself überflüssig wäre?

[*] GUI spricht Procedure an sobald letztes verzeichnis exisiert als Variable
[*] Procedure bekommen die Einträge "Path Source" & "Path Target" sowie "Path Patch" aus der GUI hinübergereicht und wird ausgeführt.

In der GUI kann ich mir ja dann noch etwas einbauen, dass mir mitteilt, dass die Procedure erfolgreich war......
Aber ich scheitere mit der Überlegung, die Procedure wird erst nach dem Bekanntwerden der Verzeichnisse ausgeführt.

Liebe Grüsse
Christian
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von Kiffi »

Zusätzlich zu dem, was HeX0R geschrieben hat: Bitte nicht "[Open]" oder ähnliches von Anfang an in den Betreff schreiben. Ich habe das jetzt korrigiert. Du kannst später gerne in den Betreff Deines Ursprungspostings "Erledigt" schreiben, wenn das Problem gelöst worden ist
a²+b²=mc²
Axolotl
Beiträge: 265
Registriert: 31.12.2008 16:34

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von Axolotl »

Hallo ChrigiGee,

ich habe mal mein letztes Beispiel (aus dem anderen Gesprächsfaden) weiter angepasst:
Bitte studiere mal was da so passiert.

Vorab zur Erklärung:
1. Ich habe die Eingabelogik "offener" gestaltet. D.h. der User kann jederzeit die Pfade ändern.
2. Ich prüfe auf "Gültigkeit" der Pfade und in Abhängigkeit vom Ergebnis wird der "Execute-Button == Patch Now " aktiv oder nicht.
3. Ich habe die globalen Variablen eliminiert und arbeite mit lokalen Variablen in den Proceduren. (Das ist mehr mein Stil, aber das ist am Ende Geschmackssache)
4. Die Procedure, die hinterher die Arbeit tun soll heißt: DoTheJobNow() . Die notwendigen Parameter werden übergeben. (Müsste man bei globalen Variablen nicht tun.)
5. Aktuell simuliert die Procedure nur und zeigt einen Fortschrittsbalken. Hier ist noch viel Verbesserungspotential.
Denn je nach Ausführungsdauer wird Windows erkennen dass das Programm die Nachrichtenschlange nicht mehr bearbeitet. Erkennt man daran, dass der Fenstertitel etwas von "Reagiert nicht...." anzeigt.
Da sind dann Maßnahmen wie Threads, Statemachine, etc. je nach Geschmack notwendig. (Würde hier aber den Rahmen sprengen....)

Und jetzt erstmal viel Spaß beim nachvollziehen.

Fragen? Fragen!

Code: Alles auswählen

;- Top
; -----------------------------------------------------------------------------
;           Name:
;    Description:
;         Author:
;           Date: 2024-08-22
;        Version:
;     PB-Version:
;             OS:
;         Credit:
;          Forum:
;     Created by: IceDesign
; -----------------------------------------------------------------------------

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;- Enumerations
Enumeration Window
  #Window_0
EndEnumeration

Enumeration Gadgets
  #Btn_Execute

  #Btn_Path_Source
  #Btn_Path_Target
  #Btn_Path_Patch 

  #Str_Path_Source
  #Str_Path_Target
  #Str_Path_Patch

  #Progressbar 
EndEnumeration

; ;- Global
; Global InitialPathSource$ 
; Global PathSource$
; Global InitialPathTarget$ 
; Global PathTarget$
; Global InitialPathPatch$  
; Global PathPatch$

; -----------------------------------------------------------------------------

;- Declare
Declare Resize_Window_0()
Declare Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)

Procedure Resize_Window_0()
  Protected Window_0_WidthIni = 540, Window_0_HeightIni = 400
  Protected ScaleX.f, ScaleY.f

  ScaleX = WindowWidth(#Window_0) / Window_0_WidthIni : ScaleY = WindowHeight(#Window_0) / Window_0_HeightIni
  ResizeGadget(#Btn_Path_Source, ScaleX * 40, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Path_Target, ScaleX * 170, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Path_Patch, ScaleX * 320, ScaleY * 270, ScaleX * 130, ScaleY * 45)
EndProcedure 

Procedure Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)
  If OpenWindow(#Window_0, X, Y, Width, Height, "Template Patcher Programm", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    ButtonGadget(#Btn_Path_Source, 40, 270, 100, 45, "Source ...") 
    ButtonGadget(#Btn_Path_Target, 170, 270, 100, 45, "Target ...") 
    ButtonGadget(#Btn_Path_Patch,  320, 270, 130, 45, "Patch ...") 

    ButtonGadget(#Btn_Execute, 205, 340, 130, 45, "Patch Now") 

    StringGadget(#Str_Path_Source, 8,  80, 306, 20, "C:\") ;, #PB_String_ReadOnly) 
    StringGadget(#Str_Path_Target, 8, 100, 306, 20, "C:\") ;, #PB_String_ReadOnly) 
    StringGadget(#Str_Path_Patch,  8, 120, 306, 20, "C:\") ;, #PB_String_ReadOnly) 

    ProgressBarGadget(#Progressbar, 8, 180, 500, 20, 0, 100)  
    HideGadget(#Progressbar, 1) 

    BindEvent(#PB_Event_SizeWindow, @Resize_Window_0(), #Window_0)
    PostEvent(#PB_Event_SizeWindow, #Window_0, 0)
    ProcedureReturn #True
  EndIf
EndProcedure

; -----------------------------------------------------------------------------

Procedure.s EnterFile(Gadget) 
  Protected result$, temp$ 

  temp$ = GetGadgetText(Gadget)  
  temp$ = OpenFileRequester("Bitte wählen Sie eine Patch-Datei aus", temp$, "Patch (*.patch;*.patch)|*.*|All files (*.*)|*.*", 0) 
  If temp$ 
    result$ = temp$ 
  EndIf 
  SetGadgetText(Gadget, result$) 
  ProcedureReturn result$ 
EndProcedure 

Procedure.s EnterPath(Gadget) 
  Protected result$, path$ 

  path$ = GetGadgetText(Gadget)  
  If path$ = "" : path$ = GetCurrentDirectory() : EndIf 
  path$ = PathRequester("Bitte wählen Sie einen Pfad aus", path$) 
  If path$ 
    result$ = path$ 
;   Else
;     MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
  EndIf 
  SetGadgetText(Gadget, path$) 
  ProcedureReturn result$ 
EndProcedure 

Procedure PathIsCorrect(Gadget)   ; BOOL  
  Protected result, path$ 

  path$ = GetGadgetText(Gadget) 
  If path$ <> "" And FileSize(path$) = -2 
    result = #True  ; <-- correct  
  EndIf 
  ProcedureReturn result 
EndProcedure 

Procedure FileIsCorrect(Gadget)   ; BOOL  
  Protected result, file$ 

  file$ = GetGadgetText(Gadget) 
  If file$ <> "" And FileSize(file$) > 0  
    result = #True  ; <-- correct  
  EndIf 
  ProcedureReturn result 
EndProcedure 


Procedure InputsAreCorrect()   ; BOOL  
  Protected result, p1$, p2$, p3$ 

  p1$ = GetGadgetText(#Str_Path_Source) 
  p2$ = GetGadgetText(#Str_Path_Target)
  p3$ = GetGadgetText(#Str_Path_Patch)

  If p1$ <> "" And p2$ <> "" And p3$ <> ""  ; all gadgets filled 
    If FileSize(p1$) = -2 And   ; <-- Source Path is a existing folder 
       FileSize(p2$) = -2 And   ; <-- Target Path is a existing folder 
       FileSize(p3$) = -2       ; <-- Patch is an existing folder ??  (should this be a file?) 
      ;FileSize(p3$) > 0        ; <-- Patch is an existing file 
      result = #True  ; <-- correct 
    EndIf 
  EndIf                           ; : Debug #PB_Compiler_Procedure + " -- result  = " + result 
  ProcedureReturn result 
EndProcedure 


Procedure UpdateUI(State) 

  DisableGadget(#Btn_Execute, State ! 1)  ; <-- disable 
  ; ... 
  ; add more gadgets 
  ; 
EndProcedure 

Procedure DoTheJobNow(Source$, Target$, Patch$) 
  Protected result, index, count  

  ; so what you need to do..... 
  count = 100 

  SetGadgetAttribute(#Progressbar, #PB_ProgressBar_Maximum, count) 
  HideGadget(#Progressbar, 0) 

  For index = 0 To count 
    Delay(100) 
;   Debug " ==> Index counter = " + index 
    SetGadgetState(#Progressbar, index) 
  Next index 
  HideGadget(#Progressbar, 1) 

  result = #True 

  ProcedureReturn result 
EndProcedure 


CompilerIf #PB_Compiler_IsMainFile

; -----------------------------------------------------------------------------
;- Main Program

Procedure main() 
  Protected state, p1$, p2$, p3$ 

  If Open_Window_0()

    ; init UI 
    ; 
    UpdateUI(InputsAreCorrect()) 

    ;- Event Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break

        ;-> Event Gadget
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case #Str_Path_Source, #Str_Path_Target, #Str_Path_Patch 
            If EventType() = #PB_EventType_Change 
              UpdateUI(InputsAreCorrect()) 
            EndIf 
            
;           Case #Str_Path_Target 
;             If EventType() = #PB_EventType_Change
;               UpdateUI(InputsAreCorrect()) 
;             EndIf 

;           Case #Str_Path_Patch  
;             If EventType() = #PB_EventType_Change
;               UpdateUI(InputsAreCorrect()) 
;             EndIf 

          Case #Btn_Path_Source 
            EnterPath(#Str_Path_Source) 
            UpdateUI(InputsAreCorrect()) 

          Case #Btn_Path_Target 
            EnterPath(#Str_Path_Target) 
            UpdateUI(InputsAreCorrect()) 

          Case #Btn_Path_Patch  
            EnterPath(#Str_Path_Patch) 
            UpdateUI(InputsAreCorrect()) 

          Case #Btn_Execute   ; Execute
            p1$ = GetGadgetText(#Str_Path_Source) 
            p2$ = GetGadgetText(#Str_Path_Target)
            p3$ = GetGadgetText(#Str_Path_Patch) 

            If DoTheJobNow(p1$, p2$, p3$) 
              ; on success !!! 
            EndIf 

        EndSelect

      EndSelect
    ForEver
  EndIf
EndProcedure 

End main() 

CompilerEndIf
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
Axolotl
Beiträge: 265
Registriert: 31.12.2008 16:34

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von Axolotl »

So ChrigiGee,

ich bin's nochmal..... :oops:

Ich habe mir deine beiden Beispiele angesehen.
create Procedure:
patch it:
Spontaner Kommentar:
1. Bitte beachte, dass Path$ nicht gleich Filename$ ist.
Die Procedure createpatch(Path1$,Path2$,Path3$) benötigt Filename$ anstelle von Path$.
Lerne: Variablennamen sind wichtig! Gute "sprechende" Variablennamen ersparen einen Kommentar und erhöhen die Lesbarkeit.

2. Variablentypen.
Prüfe, ob .b und .l hier die richtigen Typen sind. Mindestens bei Length und Size Variablen würde ich .i (ggf. .q bei 32bit compiler) verwenden.
Empfehlung: Ich verwende (außer in Structure und API functions) nur .i

3. Forum Beispiele sind häufig (sehr) einfach gehalten.
Hier fehlt (aus meiner Sicht) die Abfrage der Rückgabewerte. Z.B. ReadFile() kann auch schiefgehen......
Empfehlung: Funktionsweise der Beispiele mit Hilfe der Hilfe nachvollziehen und prüfen was man anders (besser) machen kann.

4. Kommentare
Füge ausführliche Kommentare da ein wo sie dem Verständnis helfen. (auch oder gerade wenn es nicht dein eigener Code ist)
Z.B. ; '+33' für den MD5 Header
Hntergrund: Die Länge von einem MD5 String ist immer 32.

5. CreatePack
Ich habe damit noch nie gearbeitet, aber du must laut Hilfe vorher noch ein packer plugin registrieren.
Entweder UseZipPacker() oder UseBriefLZPacker().
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von HeX0R »

o.k., ich denke ich hab's verstanden, hier mal eine etwas intuitivere GUI, habe allerdings der Faulheit wegen Dialoge verwendet hier:

Code: Alles auswählen

Runtime Enumeration Gadgets
	#frame_browse_source
	#string_browse_source
	#button_browse_source
	#frame_browse_target
	#string_browse_target
	#button_browse_target
	#frame_browse_patch
	#string_browse_patch
	#button_browse_patch
	#button_go
EndEnumeration


Procedure.s GetXMLString()
	Protected XML$

	XML$ + "<?xml version='1.0' encoding='UTF-16'?>"
	XML$ + ""
	XML$ + "<dialogs><!--Created by Dialog Design0R V1.85 => get it from: https://hex0rs.coderbu.de/en/sdm_downloads/dialogdesign0r/-->"
	XML$ + "  <window flags='#PB_Window_SystemMenu | #PB_Window_ScreenCentered' text='Template Patcher Programm' name='window_main' xpos='1704' ypos='518'>"
	XML$ + "    <vbox>"
	XML$ + "      <frame text='Path to Source' id='#frame_browse_source'>"
	XML$ + "        <hbox expand='item:1'>"
	XML$ + "          <string width='250' id='#string_browse_source' onchange='OnChange_String()'/>"
	XML$ + "          <button text='...' id='#button_browse_source' onevent='OnClick_Browse_Source()'/>"
	XML$ + "        </hbox>"
	XML$ + "      </frame>"
	XML$ + "      <frame text='Path to Target' id='#frame_browse_target'>"
	XML$ + "        <hbox expand='item:1'>"
	XML$ + "          <string width='250' id='#string_browse_target' onchange='OnChange_String()'/>"
	XML$ + "          <button text='...' id='#button_browse_target' onevent='OnClick_Browse_Target()'/>"
	XML$ + "        </hbox>"
	XML$ + "      </frame>"
	XML$ + "      <frame text='Path to Patch' id='#frame_browse_patch'>"
	XML$ + "        <hbox expand='item:1'>"
	XML$ + "          <string width='250' id='#string_browse_patch' onchange='OnChange_String()'/>"
	XML$ + "          <button text='...' id='#button_browse_patch' onevent='OnClick_Browse_Patch()'/>"
	XML$ + "        </hbox>"
	XML$ + "      </frame>"
	XML$ + "      <hbox align='center' expand='no'>"
	XML$ + "        <button text='Patch Now' flags='#PB_Button_Default' disabled='yes' id='#button_go'/>"
	XML$ + "      </hbox>"
	XML$ + "    </vbox>"
	XML$ + "  </window>"
	XML$ + "</dialogs><!--DDesign0R Definition: PureBasic|1|1|1|__|example_with_declares|1|AddOn:3:0-->"
	XML$ + ""

	ProcedureReturn XML$
EndProcedure

Runtime Procedure OnChange_String()
	Protected a$, Disabled = 1
	
	a$ = GetGadgetText(#string_browse_source)
	If a$ And FileSize(a$) = -2
		a$ = GetGadgetText(#string_browse_target)
		If a$ And FileSize(a$) = -2
			a$ = GetGadgetText(#string_browse_patch)
			If a$ And FileSize(a$) = -2
				Disabled = 0
			EndIf
		EndIf
	EndIf
	
	DisableGadget(#button_go, Disabled)
	
EndProcedure

	
Runtime Procedure OnClick_Browse_Source()
	Protected path$
	
	path$ = PathRequester("Bitte wählen Sie einen Pfad aus", GetGadgetText(#string_browse_source))
	If path$
		SetGadgetText(#string_browse_source, path$)
	EndIf
	OnChange_String()
EndProcedure

Runtime Procedure OnClick_Browse_Target()
	Protected path$
	
	path$ = PathRequester("Bitte wählen Sie einen Pfad aus", GetGadgetText(#string_browse_target))
	If path$
		SetGadgetText(#string_browse_target, path$)
	EndIf
	OnChange_String()
EndProcedure

Runtime Procedure OnClick_Browse_Patch()
	Protected path$
	
	path$ = PathRequester("Bitte wählen Sie einen Pfad aus", GetGadgetText(#string_browse_patch))
	If path$
		SetGadgetText(#string_browse_patch, path$)
	EndIf
	OnChange_String()
EndProcedure

Procedure main()
	Protected a$
	
	a$ = GetXMLString()
	ParseXML(0, a$)
	If XMLStatus(0) = #PB_XML_Success
		CreateDialog(0)
		If OpenXMLDialog(0, 0, "window_main")
			GadgetToolTip(#button_browse_source, "Browse source path...")
			GadgetToolTip(#button_browse_target, "Browse target path...")
			GadgetToolTip(#button_browse_patch, "Browse patch path...")
			Repeat
				Select WaitWindowEvent()
					Case #PB_Event_CloseWindow
						Break
				EndSelect
			ForEver
		EndIf
	EndIf
	
EndProcedure

main()
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von ChrigiGee »

Hallo Axolotl,

Vielen Dank an Dich und die vielen hier im Forum.
Dieses Mal habe ich "versucht" den Code von der GUI
zu "verbessern" bevor ich zurückkomme und Poste.

Ich hoffe, ich konnte so etwas mitbringen an dem, was Ihr mir versucht beizubringen.
Etwas besser strukturierten Code und vielleicht auch mal eine Erklärung mehr.

[OFF TOPIC]
Ich bin mir bewusst, dass ich noch Meilen davon entfernt bin Code zu schreiben, der so gut ist wie Euere.

Es gibt zwei Punkte weshalb ich vielleicht so extrem Komplex Formulieren, zum eine Schweizer der versucht die Deutsche Sprache zu beherrschen.
Zum anderen ein Legastheniker, der eigentlich sehr gern schreiben würde, aber manchmal den Faden verliert.

Ich versuche step by step Eure Einwände und Anregungen mitzunehmen.
Gelingt wohl nicht immer, dafür danke ich, dass Ihr mir entgegenkommt.
[\OFF TOPIC]

[*] Ich habe unterdessen den Path durch den OpenFileRequest ersetzt und versucht das zu dokumentieren.
[*] Ich habe versucht, die zu kryptischen Bezeichner etwas besser an die Begebenheiten der Anwendung anzupassen.
[*] Variablennamen habe ich geändert, das mit den entsprechenden Erweiterungen schaue ich gern in der Hilfe nochmals durch.
[*] Create Pack oder Patcher muss ich nochmals besser durchgehen,
[*] Ich habe "leider" auch noch nicht alles verstanden, was dort zusammen getragen wurde.
[*] Bin momentan noch so zwischen der GUI und der procedure am hin und her schauen.

So, ich wollte meinen KLEINEN Meilenstein von heute der Allgemeinheit noch vorstellen.
Auch wenn es nicht perfekt ist.

Liebe Grüsse aus dem heissen Bern.
Christian
Axolotl hat geschrieben: 24.08.2024 13:56 So ChrigiGee,

ich bin's nochmal..... :oops:

Ich habe mir deine beiden Beispiele angesehen.
create Procedure:
patch it:
Spontaner Kommentar:
1. Bitte beachte, dass Path$ nicht gleich Filename$ ist.
Die Procedure createpatch(Path1$,Path2$,Path3$) benötigt Filename$ anstelle von Path$.
Lerne: Variablennamen sind wichtig! Gute "sprechende" Variablennamen ersparen einen Kommentar und erhöhen die Lesbarkeit.

2. Variablentypen.
Prüfe, ob .b und .l hier die richtigen Typen sind. Mindestens bei Length und Size Variablen würde ich .i (ggf. .q bei 32bit compiler) verwenden.
Empfehlung: Ich verwende (außer in Structure und API functions) nur .i

3. Forum Beispiele sind häufig (sehr) einfach gehalten.
Hier fehlt (aus meiner Sicht) die Abfrage der Rückgabewerte. Z.B. ReadFile() kann auch schiefgehen......
Empfehlung: Funktionsweise der Beispiele mit Hilfe der Hilfe nachvollziehen und prüfen was man anders (besser) machen kann.

4. Kommentare
Füge ausführliche Kommentare da ein wo sie dem Verständnis helfen. (auch oder gerade wenn es nicht dein eigener Code ist)
Z.B. ; '+33' für den MD5 Header
Hntergrund: Die Länge von einem MD5 String ist immer 32.

5. CreatePack
Ich habe damit noch nie gearbeitet, aber du must laut Hilfe vorher noch ein packer plugin registrieren.
Entweder UseZipPacker() oder UseBriefLZPacker().

Code: Alles auswählen

;- Top
; -----------------------------------------------------------------------------
;           Name: myPatch app
;    Description: GUI & patch maker + patcher
;         Author: Christian & all of the PureBasic Forum
;           Date: 2024-08-22
;        Version: Alpha 6
;     PB-Version: 6.11
;             OS: WIN 11
;         Credit:
;          Forum:
;     Created by: IceDesign
; -----------------------------------------------------------------------------

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;- Enumerations
Enumeration Window
  #Window_0
EndEnumeration

Enumeration Gadgets
  #Btn_Execute
  #Btn_Source
  #Btn_Target
  #Str_Source_DIR
  #Str_Target_DIR
  #Str_Patch_DIR
EndEnumeration

;- Global
Global Pattern$        ;- Auswahl welcher Dateien verwendet werden

Global File1$          ;- Source Datei für den Patch
Global File2$          ;- Target Datei für den Patch
Global File3$          ;- Patch Datei himself
Global InitialPath1$   ;- Welches  verzeichnis für Source und Target
Global InitialPath2$   ;- Welches  verzeichnis für Source und Target
Global InitialPath3$   ;- Welches Verzeichnis für den Patch himself

;- Define 
Define Pattern

;- Declare
Declare Resize_Window_0()
Declare Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)

;- Procedure Main Window
Procedure Resize_Window_0()
  Protected Window_0_WidthIni = 540, Window_0_HeightIni = 400
  Protected ScaleX.f, ScaleY.f

  ScaleX = WindowWidth(#Window_0) / Window_0_WidthIni : ScaleY = WindowHeight(#Window_0) / Window_0_HeightIni
  ResizeGadget(#Btn_Source, ScaleX * 40, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Target, ScaleX * 170, ScaleY * 270, ScaleX * 100, ScaleY * 45)
  ResizeGadget(#Btn_Execute, ScaleX * 320, ScaleY * 270, ScaleX * 130, ScaleY * 45)
EndProcedure

;- Procedure Open Main Window
Procedure Open_Window_0(X = 0, Y = 0, Width = 540, Height = 400)
  If OpenWindow(#Window_0, X, Y, Width, Height, "Patch my App", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    ButtonGadget(#Btn_Source, 40, 270, 100, 45, "Source Dir")
    ButtonGadget(#Btn_Target, 170, 270, 100, 45, "Target Diir")
      DisableGadget(#Btn_Target, #True)
    ButtonGadget(#Btn_Execute, 320, 270, 130, 45, "Execute")
      DisableGadget(#Btn_Execute, #True)

    StringGadget(#Str_Source_DIR, 8,  80, 306, 20, File1$, #PB_String_ReadOnly)   ;- Datei DIR
    StringGadget(#Str_Target_DIR, 8,  100, 306, 20, File2$, #PB_String_ReadOnly)  ;- Datei DIR
    StringGadget(#Str_Patch_DIR, 8,  120, 306, 20, File3$, #PB_String_ReadOnly)   ;- Datei DIR

    BindEvent(#PB_Event_SizeWindow, @Resize_Window_0(), #Window_0)
    PostEvent(#PB_Event_SizeWindow, #Window_0, 0)
    ProcedureReturn #True
  EndIf
EndProcedure


CompilerIf #PB_Compiler_IsMainFile
;- Main Program
If Open_Window_0()

  ;- Event Loop
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break

        ;-> Event Gadget
      Case #PB_Event_Gadget
        Select EventGadget()
          Case   #Btn_Source  ; DIR Source File
          
  ;  Mit dem nächsten String werden die Pattern (mit "|" als Trennzeichen) für anzuzeigende
  ;  Dateitypen festgelegt:
  ;  Erster:  "App's (*.exe)" als Name, ".exe" und ".dll" als erlaubte Dateiendungen
  ;  Zweiter: "Alle Dateien (*.*) als Name, "*.*" als erlaubte Dateiendung, gültig für alle Dateien    
        
          
            InitialPath1$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\source.txt"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
            Pattern = 0    ; wir verwenden den ersten von drei möglichen Pattern als Standard
            File1$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath1$, Pattern$, Pattern)
            If File1$

              SetGadgetText(#Str_Source_DIR, File1$) 
              DisableGadget(#Btn_Source, #True)   ;<-- disable ??? 
              DisableGadget(#Btn_Target, #False)  ;<-- 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf

          Case #Btn_Target   ; DIR Target File
          
  ;  Mit dem nächsten String werden die Pattern (mit "|" als Trennzeichen) für anzuzeigende
  ;  Dateitypen festgelegt:
  ;  Erster:  "App's (*.exe)" als Name, ".exe" und ".dll" als erlaubte Dateiendungen
  ;  Zweiter: "Alle Dateien (*.*) als Name, "*.*" als erlaubte Dateiendung, gültig für alle Dateien    

            InitialPath2$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\target.txt"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
            Pattern = 1    ; wir verwenden den ersten von drei möglichen Pattern als Standard
            File2$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath2$, Pattern$, Pattern)
            If File2$
          
              SetGadgetText(#Str_Target_DIR, File2$) 
              DisableGadget(#Btn_Target, #True) 
              DisableGadget(#Btn_Execute, #False) 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf
          Case #Btn_Execute   ; Execute
          
  ;  Mit dem nächsten String werden die Pattern (mit "|" als Trennzeichen) für anzuzeigende
  ;  Dateitypen festgelegt:
  ;  Erster:  "App's (*.exe)" als Name, ".exe" und ".dll" als erlaubte Dateiendungen
  ;  Zweiter: "Alle Dateien (*.*) als Name, "*.*" als erlaubte Dateiendung, gültig für alle Dateien    
        
            InitialPath3$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\my Patch\new\patch.csp"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
            Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
            Pattern = 0    ; wir verwenden den ersten von drei möglichen Pattern als Standard
            File3$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath3$, Pattern$, Pattern)
            If File3$
            
            SetGadgetText(#Str_Patch_DIR, File3$) 
            DisableGadget(#Btn_Execute, #True) ;<-- 
            Else
              MessageRequester("Information", "Der Requester wurde abgebrochen.", 0) 
            EndIf
        EndSelect

    EndSelect
  ForEver
EndIf
CompilerEndIf
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: Prozedure mit variabler Abhängigkeit ?

Beitrag von ChrigiGee »

Hallo HeX0R,

Vielen lieben Dank für Deine Unterstützung natürlich.

Ich war etwas sehr euphorisch meine heutige Arbeit zu präsentieren und habe Dein Werk noch nicht bemerkt.

Um zu verstehen, was ich noch alles verbessern kann, werde ich mir Dein Beispiel sehr gerne durchgehen.
Und ich denke, ich werde verzweifelt sein, zu sehen, wie weit ich von Euch allen noch entfernt bin.

Ich werde mir aber sehr grosse Mühe geben alles zu verstehen und denke, dass ich erst Morgen damit mit einem Café
in Angriff nehmen werde.

Auf jeden Fall vielen Dank und ich wünsche Euch allen einen perfekten Samstag.

Liebe Grüsse aus Bern
Christian

HeX0R hat geschrieben: 24.08.2024 14:30 o.k., ich denke ich hab's verstanden, hier mal eine etwas intuitivere GUI, habe allerdings der Faulheit wegen Dialoge verwendet hier:
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Antworten