Wie fange ich am besten eine Fensteranwendung an?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Wie fange ich am besten eine Fensteranwendung an?

Beitrag von Xaby »

Tja, ich hab zwar nun schon das eine oder andere kleine Programm geschrieben. Aber so richtig sauber von der Struktur sind sie meist nicht.
Und es gibt ja doch immer wieder die gleichen Dinge in einer Anwendung, die man irgendwie immer benötigt.

Code: Alles auswählen

;{- Aplication: HonigProgramm
;/ Autor: Folker Linstedt (xaby)
;- funct: Datenbank, WWS, Verwaltung, Adressen, Honig, Zuweisungen
;/ State: 2007|06|20
;/ Begin: 2007|06|20
;/ Versi: 0.0.1
;}/

#Progname="FLHonig"

Enumeration
  ;/ Winodws
  
  #MainWin
  
  ;/ Gadgets
  
  #ListGad
  #TreeGad
  #ButtonGad
  #StringGad
  
  ;/ Menu and ToolBar
  #MainMenu
  #MainToolbar
  #About
  
  
EndEnumeration

;{- Globale Variablen, Sprache, etc.
;/ MainWin-Position
Global WinPosX_MainWin
Global WinPosY_MainWin
Global WinMaxX_MainWin
Global WinMaxY_MainWin

;/ Preferences
Global Language
;{- Translation 
Global Dim lang.s(24,1) 
;German 
lang(0,0)  = "Datei" 
lang(1,0)  = "Hilfe"
lang(2,0)  = "Über ..."
;English 
lang(0,1)  = "file" 
lang(1,1)  = "help"
lang(2,1)  = "about"
;} 

;}/

Procedure LoadPreferences(n$)
  OpenPreferences(n$)
  WinPosX_MainWin.l=ReadPreferenceLong("WINDOW_XPOS_MAIN",50);
  WinPosY_MainWin.l=ReadPreferenceLong("WINDOW_YPOS_MAIN",50);
  WinMaxX_MainWin.l=ReadPreferenceLong("WINDOW_XMAX_MAIN",750);
  
  If WinMaxX_MainWin<750
    WinMaxX_MainWin=750
  EndIf 
  
  WinMaxY_MainWin.l=ReadPreferenceLong("WINDOW_YMAX_MAIN",550);
  
  If WinMaxY_MainWin<550
    WinMaxY_MainWin=550
  EndIf
  
  Language.l=ReadPreferenceLong("LANGUAGE",0);
  ClosePreferences()
EndProcedure

Procedure SavePreferences(n$)
  CreatePreferences(n$)
  WritePreferenceLong("WINDOW_XPOS_MAIN",WindowX(#MainWin))
  WritePreferenceLong("WINDOW_YPOS_MAIN",WindowY(#MainWin))
  WritePreferenceLong("WINDOW_XMAX_MAIN",WindowWidth(#MainWin))
  WritePreferenceLong("WINDOW_YMAX_MAIN",WindowHeight(#MainWin))
  WritePreferenceLong("LANGUAGE",Language)
  ClosePreferences()
EndProcedure

Procedure StandardMenu()
  If CreateMenu(#MainMenu,WindowID(#MainWin))
    MenuTitle(lang(0,Language))
    MenuTitle(lang(1,Language))
    
    MenuItem(#About,lang(2,Language))
    
  EndIf
EndProcedure

LoadPreferences(#Progname+".ini")


If OpenWindow(#MainWin,WinPosX_MainWin,WinPosY_MainWin, WinMaxX_MainWin,WinMaxY_MainWin,":: FL :: "+#Progname) And CreateGadgetList(WindowID(#MainWin))
  StandardMenu()
  



Repeat

  Event= WaitWindowEvent()
  
  If  Event=#PB_Event_CloseWindow
    If EventWindow()=#MainWin
      Quit=1
    EndIf
    
  ElseIf  Event=#PB_Event_Gadget
    ;{/  Gadgets
    GadgetNr=EventGadget()
    If GadgetNr
      
      
    EndIf
    ;}
    
  ElseIf Event=#PB_Event_Menu
    ;{/  Menu and ToolBar
    MenuNr=EventMenu() 
    If MenuNr=#About
      Debug "About Window aus Include-Datei"
      
    EndIf
    ;}
    
  ElseIf Event=#PB_Event_SizeWindow
    ;{/  resize Gadgets
    If EventWindow()=#MainWin
      
      
      
    EndIf
    ;}
    
  EndIf


Until Quit


SavePreferences(#Progname+".ini")


CloseWindow(#MainWin)

EndIf
Nun wollte ich mal von den Experten wissen, wie ein guter oder sogar der beste Anfang für eine Anwendung aussehen könnte.

Möglichst einfach zu handhaben. Erweiterbar. Modular.

Meine Preference-Datei ist wohl noch nicht ideal wegen der globalen Variablen und wenn das Programm abstürzen sollte, speichert es natürlich auch seine Position nicht.

Breite und Höhe des Fensters werden mitgespeichert, falls man doch lieber ein RESIZE-Able-Window haben möchte.
Später dürfte es ein leichtes sein, dann in die Preference-Datei die Variablen für "Unterfenster" und andere Variablen hinzuzufügen.
Wie Options-Einstellungen, oder favorisierte Pfadeinstellungen beim Laden und Speichern von Dokumenten.

Hatte auch überlegt, ob Menu und Toolbar nicht eigentlich in jeden guten Anfang schon mit integriert werden sollten.
Genauso ein System, was es ermöglicht, später einfach die Sprache umzustellen.

Allerdings bin ich mir da nicht sicher, was günstiger wäre.
Ob man einfach eine neue Exe erstellt. Oder wirklich für jedes Wort eine Variable aus einer "Übersetzer-Textdatei" laden sollte.

Ich bevorzuge IF-Anweisungen statt Case. Von der Geschwindigkeit nehmen sie sich nichts. Find ich übersichtlicher.

Das Problem wäre nun, wie macht man es, wenn man 6 Fenster in einem Programm hat und die Preference-Datei alle Variablen enthalten soll?

Man könnte die Sache umgehen, in dem man bei jedem Schließen eines Fensters die Preference-Datei erneuert. Und die Abfrage, wie hoch und breit ein Fenster ist und an welcher Stelle es sich befindet, legt man in die Speicherung der Preference-Datei. Und beim Laden der Preference-Datei erstellt man auch die Fenster.

Aber schon da ist das Problem, dass ja nicht alle Fenster gleich auf sein müssen. Und jedes mal eine Datei laden, wenn ein Fenster geöffnet wird?

Ein Array oder eine LinkedList vielleicht? Ich weiß es nicht.
Aber bei vielen Fenstern wird es mit globalen Variablen doof.



>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Was haltet ihr im Allgemeinen von meinem Anfang?

Würde gern eure Anfangs-Vorschläge sehen und euch gleich vorweg bitten,
nicht sowas zu schreiben wie: Ist doch jedem selbst überlassen, wie er anfängt ...

>> Die Sache mit der Sprache müsste man sicherlich bei vielen Worten dann auch eher seperat in einer IncludeDatei oder in einer Textdatei machen.
Aber wenigstens die Standard-Sprachen sollten im Programm integriert sein, nicht dass man raten muss, welche Menüs vorhanden sind, wenn die Textdatei beschädigt wird.


Dank euch. Gruß, Folker
Zuletzt geändert von Xaby am 20.06.2007 17:23, insgesamt 1-mal geändert.
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Tsuki-Namida
Beiträge: 633
Registriert: 17.11.2005 13:27
Kontaktdaten:

Beitrag von Tsuki-Namida »

naja ich kann dir jetzt was empfehlen aber der eine oder andere sagt dann son blöödsin oder das wollte ich auch sagen oder wie auch immer... ist ja egal... ich sage einfach was ich bzw/wie ich das löse

ich habe mir erst überlegt was es für eine anwendung sein soll und was sie können soll.
ich setze meine fenster immer zentrier und ein übergeordnetes fenster setze ich zentriert zu dem unterliegenden fenster.
mit merkender position habe ich zwar noch nicht gearbeitet aber das dürfte nicht wirklich schwer sein.
ich würde beim aufruf des programme als erstes meine datei auslesen wie die positionen stehen und das für alle fenster und in globale variabeln speichern.
dann muss ich werend des ausfürens des programms nicht nocheinmal die datei auslesen.

um nach einen absturz dennoch die fenster an der selben position zu haben könnte man es so machen das man nach einer bewegung der fenster gleich die neuen positionen speichert, das dürfrte auch kein problem sein das ist schnell gemacht ;)
Bild
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

ja, wenn sich die Position ändert, das zu speichern ist auch ne Überlegung.

Folgendes: ich nutze eine Auflösung von 1600 x 1200 Pixeln.
Bin da etwas verwöhnt. Rechner mit 800 x 600, sollte man selbst bei älteren Rechnern mit Windows 98 zum Beispiel als Standard nehmen, oder wie siehst du das?

Da man ja seine Startleiste noch hat, rechne ich 50 ab. Aber nur so als Richtwert. Kann sich ja dann jeder selbst verändern.

Speichern beim direkten Ändern der Größe hat aber den Nachteil, dass du unter Umständen ständigen Festplattenzugriff hast.
Denn wenn gerade jemand rumprobiert, wie er seine Größe am liebsten hätte ... speichert das Programm ja dann öfter.

Oder zeitgesteuert. Überprüfung nur alle 5 min. Speicherung nur, wenn was geändert wurde.

Aus deinem Beitrag entnehme ich, dass du die Globalen Variablen in diesem Fall auch favorisierst.

Bei kleineren Bildschirmauflösungen macht es ja fast keinen Unterschied, ob man die Fenster in der Mitte hat oder bei NULL, NULL.
Bei mir wie gesagt, macht es allerdings einen Unterschied von rund 400 Pixeln. Ich würde auch vier Aplikationen ohne Überlappen nebeneinander bekommen. Beim Speichern wird allerdings nur das letzte Fenster dann berücksichtigt, was geschlossen wird. Weil es die Datei überschreibt, die die anderen Fenster schon erstellt haben.

/:->
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Tsuki-Namida
Beiträge: 633
Registriert: 17.11.2005 13:27
Kontaktdaten:

Beitrag von Tsuki-Namida »

naja man kann ja überprüfen was dann in der datei steht mit den größen...
ich möchte damit sagen das du ja überprüfen kannst was drinne steht wenn drinne steht das die position und die größe jewas X und Y = 0 ist kannst du ja sagen das fenster wird in der mitte des bildschirmes erstellt andernfans werden die werte genommen
somit hast du keine probleme mehr mit bildschirmen mit einer kleineren auflösung (war anfangs mal ein verhängniss bei mir -.-)

okay wenn du dann nur das letzte fenster schließt und möchtest forsichsts salber noch einmal speichern dann speichere komplet von allen fenstern...

wenn du nicht alle auf einmal speichern möchtest kannst du auch nur die werte vom letzten fenster übernehemn das ist aber etwas umständlich...
das könnte so aussehen:

Code: Alles auswählen

If OpenFile(0,"Fensterwerte.txt") And CreateFile(1,Temp.txt)
  While Eof(0) = 0
    Temp$ = ReadString(0)
    If FindString(Temp$,"Fenster5x: ",1)
      WriteStringN(1,"Fenster5x: " + Fenster5x$)
    ElseIf FindString(Temp$,Fenster5y: ",1)
      WriteStringN(1,"Fenster5y: " + Fenster5y$)
    Else
      WriteStringN(1,Temp$)
    EndIf
  Wend
  CloseFile(0):CloseFile(1)
  CopyFile(Temp.txt, Fensterwerte.txt)
  Delay(5)
  DeleteFile("Temp.txt")
Else
  MessageRequester("Fehler","Es ist ein fehler aufgetreten")
EndIf
komplizierter deshalb da es passieren kann das man sich schneller verschreibt und dann nichts geht....

aber ich denke mal du weist was ich sagen möchte damit....


ach ja globale variabeln nutze ich nur wenn ich in einer Procedure ebenfals auf einer zugreifen muss zum beispiel wenn die procedure in einer repeat schleife ist ;) das mache ich in diesen fällen aber auch mit strings...
Bild
Benutzeravatar
D@nte
Beiträge: 324
Registriert: 24.04.2007 15:33
Wohnort: Berlin

Beitrag von D@nte »

Mein Grundgerüst für'n Programm sieht eigentlich fast immer so aus:

Code: Alles auswählen

;{- Aplication:
; Autor:
; Infos zum Programm halt
;}

;- EnableExplicit - Section
EnableExplicit
Define Variable.s
Define Variable.l
Declare.s Procedure(String.s)

;- Programparam  - Section
#Version      = "0.0"
#Title        = "Programmname"
#WindowWidth  = 640
#WindowHeight = 480

;- IncludeFile - Section
XIncludeFile "procedures.pbi"

;- Programvar - Section
Directory = GetCurrentDirectory()
ElapsedMS = ElapsedMilliseconds()
Topic     = "URL Diskussionsthread"

;- Sprach Section
;{
Global Dim language.s(24,1)
;Deutsch
  language(0,0)  = "&Datei"
;Englisch
  language(0,1)  = "&File"
;}
;- IncludeBinary Section
;{
Global Image0

Image0 = CatchImage(0, ?Image0)

DataSection
  Image0:
    IncludeBinary "C:\Pfad\icon.ico"
  Text0:
    IncludeBinary "C:\Pfad\About.txt"
EndDataSection
;}

;- Enumeration
Enumeration ;{
  #Window_0
EndEnumeration ;}

If OpenWindow(#Window_0, #PB_Ignore, #PB_Ignore, #WindowWidth, #WindowHeight, #Title + " | Version : " + #Version, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget)
Wichtig find ich das die Startposition vom Hauptfenster bei Programmen die sehr oft verwendet werden bzw in Verbindung mit anderen Programmen immer #PB_Ignore ist, für ChildWindow dann Grundsätzlich #PB_Window_WindowCentered.
Proceduren wenn se zusammen mehr als 50 Zeilen haben in ne 2te Datei auslagern.
Viel Sprungmarken setzen erleichtert die Erweiterung von Programmen ungemein, immer Aussagekräftige Procedure und Variablen namen verwenden unso weiter...

just my2cent
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Tja, die ShortCuts müsste man ja dann auch noch entsprechend der Sprache und er Unterstreichung festlegen.
Und diese auch wieder abspeichern, wenn man es individuell halten möchte.

:oops: Benutzerdefinierte Einstellungen sind schon ein Graus.

Naja, die "Unterfenster" immer mittig zu machen, ist bei Einstellungsfenstern und About-Fenstern noch in Ordnung.

Aber wenn es dann Suchfunktionen, oder Tools für ein Bildbearbeitungsprogramm sind, möchte ich die Fenster nicht alle in der Mitte haben. Vor allem, wenn man mehr als ein weiteres Fenster gleichzeitig auf hat.

Das macht dann richtig Arbeit.

Am besten wieder Text-Console und Befehle zum Eingeben.
Da braucht keiner sich die Fensterpositionen merken :mrgreen:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Ein Hauptfenster Screencentered zu erstellen ist fast immer verkehrt.
Bei Anwendungen, die sowieso alleine laufen sollten, also Setup-Programme
macht das Sinn, aber bei den meisten anderen Anwendungen ist diese
Einstellung völlig daneben. (Machen viele Anfänger, weil sie ihre eigene
Anwendung als besonders wichtig einstufen :mrgreen: ), auf jedenfall ein
Zeichen von Unprofessionalität.

Anwendungen die häufig mehrfach gestartet werden, sollten nur breite und
höhe speichern, für X und Y immer #PB_Ignore

Andere Anwendungen sollte die gespeicherte Position nehmen, bzw. wenns
keine gibt auch #PB_Ignore (hier wäre dann auch Screencentered
aktzeptabel, aber nur für den erstmaligen start)

Childfenster zu positioneren, ist Anwendungsabhängig, WindowCentered
ist auch dort meist nicht die richtige Wahl. Entweder relative position zum
Hauptfenster oder dieselben Regeln wie für Hauptfenster einhalten.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Captn. Jinguji
Beiträge: 397
Registriert: 07.06.2005 19:47
Computerausstattung: PB 4.73x64, i7, WIN 10x64, ATI NVidia RTX 2070
Wohnort: Witten

Beitrag von Captn. Jinguji »

Also, ich habe vor ca. einem Jahr mein erstes WindowsProgramm mit Purebasic geschrieben. (allerdings habe ich selbst vor fast 20 Jahren mal mein eigenes Curses-basiertes Window- und Menudesign Programm geschrieben,mit dem eine Laboranwendung realisiert wurde)
Auch wenn einige jetzt "Bäähh" sagen werden: Mir hat der Visual Designer sehr geholfen, mit den windows-spezifischen Gegebenheiten zurande zu kommen. Ausserdem kann er auf Wunsch das notwendige, rudimentäre Rahmenprogramm (vulgo: Eventschleife) kreiren -ok, das ist wahrlich nicht die Welt, aber ich fand's "convenient"-, in das man seine eigene Programmlogik einbringen kann.

Damit kann man sich (erstmal) auf das visuelle Designen von Windowoberflächen konzentrieren (bin auch eher ein visueller Typ),
und dafür dann gadgetweise seine Logik aufbauen.

Allerdings sollte man sich besser gleich eine eigene Namenskonvention für die Gadget-Konstanten einfallen lassen (das war mein größter Fehler in der ersten Version, nicht zu erkennen, dass die Gadget-Konstanten-namen, die der Designer generiert, alles andere als gottgegeben sind).

Ich bin so viel schneller zurande gekommen als wenn ich es ohne den VD angegangen wäre.

Ausserdem habe ich mir angewöhnt, die Reaktionen jedes Gadgets in eine eigene Procedure zu packen, und diese Procs wiederum zusammen in ein Include. Hilft letztlich bei der Pflege. Ausserdem kann man so leichter was wiederverwenden, auch in anderen Programmen.


PS: ich halte in meinen Programmen die Preference Daten jeweils in einer entsprechenden structure. Die lassen sich dann leicht in eine temporäre bzw. "re-init" structure kopieren. Und die "Current"-Variante der structure kann man dann an strategisch geschickt verteilten Punkten der Anwendung wegschreiben, um das dauernde Schreiben jeglicher Änderung auf Platte zu vermeiden (klar. das geht auch mit Deinen globalen Variablen, aber ich mag die eben nicht - also, generell jetzt, nicht nur DEINE ;) - und finde es sinnvoll, Zusammengehöriges eben in structures zu speichern.

Ansonsten kommt man dann eben gut voran, wenn man die Anwendung um weitere Fenster etc. ausbaut.

Nicht so dolle gelöst sind beim VD die Menüs, da eignet sich der VD eher weniger für Online-Editing der Menüelemente. Bin meist da geendet, dass ich eine Wegwerfversion zurecht editiert hatte, bis ich weiss, wo welches Menüelement hinkommt, dass dann wirklich lösche und dann neu sauber in der Endversion aufzubauen.

Aber, jeder nach seiner Art.
Ist das Kunst hier, oder kann das weg ?
Benutzeravatar
Captn. Jinguji
Beiträge: 397
Registriert: 07.06.2005 19:47
Computerausstattung: PB 4.73x64, i7, WIN 10x64, ATI NVidia RTX 2070
Wohnort: Witten

Beitrag von Captn. Jinguji »

[quote="ts-soft"]Ein Hauptfenster Screencentered zu erstellen ist fast immer verkehrt.
[quote]
und ich persönlich finde auch Programme nervend, die sofort den ganzen Bildschirm abdecken, ohne dass es wirklich erforderlich ist -auch, wenn sie netterweise die Taskleiste freilassen.
Ist das Kunst hier, oder kann das weg ?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

@Captn. Jinguji
Hab ich vergessen zu erwähnen:
Defaultmässig maximierte Fenster kann ich überhaupt nicht ausstehen.
Bei 1680 x 1050 ist das auch vollkommen unnötig.

Was ich noch vergessen habe:
Es ist immer besser das Fenster erst versteckt zu erstellen,
dann Gadgets erstellen, befüllen usw.
Einstellungen lesen und Fenster entsprechend anpassen
Mit While WindowEvent() : Wend alle ereignisse die durch den Fensteraufbau
enstanden sind abarbeiten und dann unmittelbar vor dem EventLoop das
Fenster anzeigen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten