![]() |
Problem mit Fenster positionierung
Hallöchen,
so ich blick jetzt gar nicht mehr durch. Kurz zum Ziel: Das Hauptformular wird normalerweise gecentert auf dem Display angezeigt. Nun habe ich in den Einstellungen eine CheckBox, womit ich entscheiden kann, ob die Fensterposition gespeichert werden soll oder nicht. Ist die also geChecked, so soll beim schliessen die letzte position des Hauptformulares gespeichert werden. Schaltet man die CheckBox wieder aus, so soll danch das Formular dann wieder geCentert angezeigt werden. Also eigentlich nichts schwieriges. So, jetzt ein bisschen Code:
Delphi-Quellcode:
Also Global!
var
MainFormMC2004: TMainFormMC2004; mHandle: THandle; MC2004: TMC2004; Pfad: String; FensterPosSave: Boolean; Geoeffnete: Boolean; Gespeicherte: Boolean;
Delphi-Quellcode:
procedure TMainFormMC2004.FormShow(Sender: TObject);
//Funktionen, Befehle, die beim Start des Programmes ausgeführt werden var ini: TIniFile; s, t, r, i, n, g: string; begin if not (FileExists('MC2004.ini')) then //Fals es die Datei es noch nicht gibt begin ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); //Datei Öffnen try ini.WriteString('Einstellungen', 'Port', 'COM1'); //Standardwert COM1 schreiben ini.WriteString('Einstellungen', 'Baud', '19200'); //Standardwert 19000Baud speichern ini.WriteString('Einstellungen', 'Format', '2'); //Standardwert Müt schreiben ini.WriteBool('Einstellungen', 'Geoeffnete', False); //Zuletzt geöffnete laden ini.WriteBool('Einstellungen', 'Gespeicherte', False); //Zuletzt gespeicherte laden ini.WriteString('Programme', 'Monitor', ''); //Programmpfad für's Datenmonitor ini.WriteString('Programme', 'SAM', ''); //Programmpfad für's Signal-Anzeige-Modul ini.WriteString('Programme', 'MC2004W', ''); //Programmpfad für's MC2004W ini.WriteBool('Fensterdaten', 'Fensterposition', False); //Fensterposition speichern; Nein ini.WriteInteger('Fensterdaten', 'Links', 0); //Position von Links auf 0 ini.WriteInteger('Fensterdaten', 'Oben', 0); //Position von Oben auf 0 ini.WriteInteger('Fensterdaten', 'Breite', 0); //Breite auf 0 ini.WriteInteger('Fensterdaten', 'Hoehe', 0); //Hoehe auf 0 s := 'COM1'; //ComPort Port t := '19200'; //ComPort Baudrate r := '2'; //Format auf Müt Geoeffnete := False; //Zuletzt geöffnete Nein Gespeicherte := False; //Zuletzt gespeicherte Nein FensterPosSave := False; //Fensterposition Nein finally FreeAndNil(ini); //Datei Schliessen/Freigeben end; end else if FileExists('MC2004.ini') then begin ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); //Datei Öffnen try s := ini.ReadString('Einstellungen', 'Port', ''); //ComPort Port t := ini.ReadString('Einstellungen', 'Baud', ''); //ComPort Baudrate r := ini.ReadString('Einstellungen', 'Format', ''); //Format; Std., Erw., Müt Geoeffnete := ini.ReadBool('Einstellungen', 'Geoeffnete', False); //Zuletzt geöffnete Gespeicherte := ini.ReadBool('Einstellungen', 'Gespeicherte', False); //Zuletzt gespeicherte i := ini.ReadString('Programme', 'Monitor', ''); //Pfad des Datenmonitor's auslesen n := ini.ReadString('Programme', 'SAM', ''); //Pfad des Signal-Anzeige-Modul's auslesen g := ini.ReadString('Programme', 'MC2004W', ''); //Pfad des MC2004W FensterPosSave := ini.ReadBool('Fensterdaten', 'Fensterposition', False); //Fensterposition if FensterPosSave = True then begin MainFormMC2004.Left := ini.ReadInteger('Fensterdaten', 'Links', 0); MainFormMC2004.Top := ini.ReadInteger('Fensterdaten', 'Oben', 0); MainFormMC2004.Width := ini.ReadInteger('Fensterdaten', 'Breite', 0); MainFormMC2004.Height := ini.ReadInteger('Fensterdaten', 'Hoehe', 0); end else if FensterPosSave = False then begin Position := poScreenCenter; end; finally FreeAndNil(ini); //Datei Schliessen/Freigeben end; end; // ComPort.Port := s; //ComPort Port setzen // ComPort.CustomBaudRate := StrToInt(t); //ComPort Baudrate setzen // ComPort.Open; //ComPort Öffnen SetStandard; //Standardwerte setzen // ZentralenStatus; Check; end;
Delphi-Quellcode:
Und die Einstellungen:
procedure TMainFormMC2004.FormClose(Sender: TObject;
var Action: TCloseAction); //Funktionen, Befehle, die beim Beenden des Programmes ausgeführt werden var ini: TIniFile; begin if not IsAllClear then begin if Application.MessageBox('Wollen Sie die vorhandenen Daten Speichern?', 'Speichern?', MB_YESNO) = mrYes then begin SpeichernClick(Sender); end; end; ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); //Datei Öffnen try ini.WriteBool('Einstellungen', 'Geoeffnete', Geoeffnete); ini.WriteBool('Einstellungen', 'Gespeicherte', Gespeicherte); ini.WriteBool('Fensterdaten', 'Fensterposition', FensterPosSave); if FensterPosSave = True then begin ini.WriteInteger('Fensterdaten', 'Links', MainFormMC2004.Left); ini.WriteInteger('Fensterdaten', 'Oben', MainFormMC2004.Top); ini.WriteInteger('Fensterdaten', 'Breite', MainFormMC2004.Width); ini.WriteInteger('Fensterdaten', 'Hoehe', MainFormMC2004.Height); end else if FensterPosSave = False then begin ini.WriteInteger('Fensterdaten', 'Links', 0); ini.WriteInteger('Fensterdaten', 'Oben', 0); ini.WriteInteger('Fensterdaten', 'Breite', 641); ini.WriteInteger('Fensterdaten', 'Hoehe', 375); end; finally FreeAndNil(ini); end; // ComPort.WriteStr(#113#0); // ComPort.Close; //ComPort Schliessen end;
Delphi-Quellcode:
procedure TEinstellungen.FormShow(Sender: TObject);
//ComPorts ermitteln und in ComboBox Anzeigen var reg: TRegistry; sl: TStrings; i: integer; ini: TIniFile; s: string; begin ShowMessage('Bei Änderungen, kann gleich mit den neuen Werten weiter gearbeitet' + #13 + 'werden. Das Programm muss nicht neu gestartet werden!'); reg := TRegistry.Create; reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey('hardware\devicemap\serialcomm', False); sl := TStringList.Create; reg.GetValueNames(sl); ComboBoxPort.Items.Clear; for i:=0 to sl.Count -1 do begin ComboBoxPort.Items.Add(reg.ReadString(sl.Strings[i])); end; sl.Free; reg.CloseKey; reg.free; ComboBoxPort.ItemIndex := StrToInt( AnsiLastChar(MainFormMC2004.ComPort.Port)) -1; ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); try s := ini.ReadString('Einstellungen', 'Baud', ''); FensterPosSave := ini.ReadBool('Einstellungen', 'Fensterposition', False); Geoeffnete := ini.ReadBool('Einstellungen', 'Geoeffnete', False); Gespeicherte := ini.ReadBool('Einstellungen', 'Gespeicherte', False); finally ini.Free; end; if Geoeffnete = True then begin CheckBox1.Checked := True; end else if Geoeffnete = False then begin CheckBox1.Checked := False; end; if Gespeicherte = True then begin CheckBox2.Checked := True; end else if Gespeicherte = False then begin CheckBox2.Checked := False; end; if FensterPosSave = True then begin CheckBox3.Checked := True; end else if FensterPosSave = False then begin CheckBox3.Checked := False; end; if s = '2400' then begin ComboBoxBaud.ItemIndex := 0; end else if s = '4800' then begin ComboBoxBaud.ItemIndex := 1; end else if s = '9600' then begin ComboBoxBaud.ItemIndex := 2; end else if s = '14400' then begin ComboBoxBaud.ItemIndex := 3; end else if s = '19200' then begin ComboBoxBaud.ItemIndex := 4; end else if s = '28800' then begin ComboBoxBaud.ItemIndex := 5; end else if s = '38400' then begin ComboBoxBaud.ItemIndex := 6; end; end;
Delphi-Quellcode:
Und die Ini:
procedure TEinstellungen.FormClose(Sender: TObject;
var Action: TCloseAction); var s, t, r: string; ini: TIniFile; begin ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); //Datei Öffnen try ini.WriteBool('Fensterdaten', 'Fensterposition', Main.FensterPosSave); //Neuen Wert Schreiben ini.WriteBool('Einstellungen', 'Geoeffnete', Geoeffnete); ini.WriteBool('Einstellungen', 'Gespeicherte', Gespeicherte); finally //Neue Werte Einlesen s := ini.ReadString('Einstellungen', 'Port', ''); //ComPort Port t := ini.ReadString('Einstellungen', 'Baud', ''); //ComPort Baudrate r := ini.ReadString('Einstellungen', 'Format', ''); //ComPort Format FreeAndNil(ini); //Datei Schliessen/Freigeben end; end;
Code:
Ich sagte ja, ein bisschen Code. ;)
[Einstellungen]
Port=COM1 Baud=19200 Format=2 Geoeffnete=1 Gespeicherte=1 [Programme] Monitor= SAM= MC2004W= [Fensterdaten] Fensterposition=0 Links=0 Oben=0 Breite=0 Hoehe=0 Das schlimmste, beim ersten Start, da wird auch die .ini angelegt und bei Fensterposition steht die 0! Bei Start erhalte ich aber die Fehlermeldung: "Cannot change in OnShow or OnPaint". Aha, gut zu wissen. Das nächste ist, wenn ich in den Einstellungen die CheckBox setze, wird beim Schliessen die 1 geschrieben. Beim starten ist auch ncoh die 1 drin, auch noch wenn ich das Einstellungenfenster öffne, das Problem ist, wenn die 1 in der ini ist, dann sollte die CheckBox geChecked sein, ist sie aber nicht! Irgend welche Ideen? Vielen Dank. Grüsse, Daniel :hi: |
Farum liest du die Ini in OnShow ein? Da wird sie ja jedesmal eingelesen, wenn das Fenster angezeigt wird? Mach es in OnCreate. Dann bekommst du auch diese "Cannot change in OnShow or OnPaint" Fehlermeldung nicht mehr.
|
Zitat:
Grüsse, Daniel :hi: |
Das hat zwar nichts mit deinem Problem zu tun, aber mir ist grad aufgefallen, warum schreibst du für den Zustand der Checkboxen nicht z.B.
Delphi-Quellcode:
anstatt
CheckBox1.Checked := Geoeffnete
Delphi-Quellcode:
Gruß
Geoeffnete = True then
begin CheckBox1.Checked |
Hi Thomas,
keine Ahnung, vielleicht ne schlechte angewohnheit?!?!?! Ich bin eher der if..then..begin..end-Typ. :mrgreen: Grüsse, Daniel :hi: |
Moin Daniel,
also einen boolschen Ausdruck mit = true oder = false abzufragen kann Fehler verursachen. Und ein Ausdruck wie if Ausdruck = true then else if Ausdruck = false then ist irgendwie leicht überflüssig, denn wenn es nicht true ist, kann es nur noch false sein. ;-) Ein if Ausdruck then ... else... würde das Ganze doch deutlich lesbarer machen. Soviel mal kurz zu Zitat:
Nun mal zu Deinem Problem: Dein ganzes Problem wird eventuell sein, dass Du den Eintrag 'Fensterposition' einmal im Abschnitt 'Fensterdaten' speicherst und liest (im Hauptformular) und einmal unter 'Einstellungen' (im Einstellungsformular). Vielleicht solltest Du Deine Einstellungen mal zentralisieren. Ausserdem wäre es ganz sinnvoll solche Texte wie die 'Einstellungen' usw. als Konstanten zu deklarieren. Das vermeidet Probleme durch Schreibfehler. Also für Einstellungen verwende ich immer ein Settings Objekt, aus dem ich dann nur noch die Daten abrufe, so dass es dem Programm egal ist, wo und wie die Einstellungen gespeichert werden. BTW: Einstellungen initial laden ist meist im OnCreate gut untergebracht, speichern im OnDestroy. (OnClose wird z.b. bei Application.Terminate nicht ausgeführt) |
Hallo Daniel B,
ich habe die Stelle, an der die Fehlermeldung kommt, auch erhalten. Zu dem warum und wieso kann ich auch nichts sagen. Nach dem Fehler ist das Formular bei mir unter Win2000 nicht mehr sichtbar (nur als Symbol auf der Start-Leiste). Folgende Änderung schafft Abhilfe:
Delphi-Quellcode:
//.....
end else begin // if FensterPosSave = False then begin // MainFormMC2004.Position := poScreenCenter; MainFormMC2004.Left := (Screen.Width - MainFormMC2004.Width) div 2; MainFormMC2004.Top := (Screen.Height - MainFormMC2004.Height) div 2; end; finally FreeAndNil(ini); //Datei Schliessen/Freigeben end; // .... Zu Deinen seltsamen Boolschen Abfragen hat sich ja Christian schon geäußert. Mir sind noch Deine doppelten Abfragen aufgefallen:
Delphi-Quellcode:
Wenn not FileExists falsch ist, dann ist die Datei vorhanden und der else-Zweig kann so aussehen:
// ....
if not (FileExists('MC2004.ini')) then begin //.... end else if FileExists('MC2004.ini') then begin //.... end;
Delphi-Quellcode:
Programmtechnisch ist es zwar egal, aber die Übersichtlichkeit leidet unnötig und es ist mehr Schreibaufwand.
// ....
if not (FileExists('MC2004.ini')) then begin //.... end else begin //.... end; mfg eddy PS: habe erst nach dem Schreiben festgestellt, daß Christian das auch schon behandelt hat. Man muß eben doch alles Probieren!! Bin noch dem Hinweis von Christian gefolgt und habe Deine OnShow-Procedure nach OnCreate verschoben. Danach funktioniert auch Deine Variante ohne Fehler. Tschüß |
Hallo eddy,
Zitat:
Das Formular erscheint, jedoch im oberen, linken viertel des Displays. Komisch, komisch... Zitat:
Wobei ich noch eine Vermutung habe. Bei poScreenCenter, erscheint das Formular im 2-Monitor Betrieb, in der mitte des linken Monitores. Bei Deiner Lösung, bzw. bei poDesktopCenter, würde das Formular in der mitte der zwei Monitoren erscheinen, somit muss man auch erst wieder verschieben. Zu Deinen seltsamen Boolschen Abfragen hat sich ja Christian schon geäußert. Zitat:
Zitat:
Danke Dir. Grüsse, Daniel :hi: |
Moin Daniel,
hast Du eine Vorstellung, wie oft das OnPaint aufgerufen wird? Das sollte immer dann geschehen, wenn das Formular neu gezeichnet werden muss. Da würde dann doch ein bisschen oft initialisiert ;-) |
Moin CHristian,
Zitat:
Grüsse, Daniel :hi: |
Hallo Daniel B,
ich habe die Ini-Datei noch mal gelöscht, Programm neu gestartet -> keine Fehler erzielbar. Allerdings ist mir aufgefallen, daß dieser Teil in TMainFormMC2004.FormClose überflüssig ist:
Delphi-Quellcode:
weil in TMainFormMC2004.FormCreate immer der else-Zweig abgearbeitet wird, wenn FensterPosSave false gilt:
//.....
end else //if FensterPosSave = False then begin ini.WriteInteger('Fensterdaten', 'Links', 0); ini.WriteInteger('Fensterdaten', 'Oben', 0); ini.WriteInteger('Fensterdaten', 'Breite', 641); ini.WriteInteger('Fensterdaten', 'Hoehe', 375); end;
Delphi-Quellcode:
Du hast ja schon geschrieben, daß Du auf if-else-Konstruktionen stehst, aber vielleicht solltest Du Dir selbst das Leben erleichtern und so etwas:
FensterPosSave :=
ini.ReadBool('Fensterdaten', 'Fensterposition', false); if FensterPosSave then begin // MainFormMC2004.Left := ini.ReadInteger('Fenst.... // .... ('Fensterdaten', 'Hoehe', 0); end else begin // if FensterPosSave = False then begin MainFormMC2004.Position := poScreenCenter; end;
Delphi-Quellcode:
doch besser so schreiben:
if Geoeffnete = True then
begin CheckBox1.Checked := True; end else if Geoeffnete = False then begin CheckBox1.Checked := False; end;
Delphi-Quellcode:
Ist doch irgendwie übersichtlicher und leichter verständlich.
CheckBox1.Checked := Geoeffnete;
Und wenn ich schon dabei bin, aus:
Delphi-Quellcode:
hätte ich folgendes gemacht:
if s = '2400' then
begin ComboBoxBaud.ItemIndex := 0; end else if s = '4800' then begin ComboBoxBaud.ItemIndex := 1; end else if s = '9600' then begin ComboBoxBaud.ItemIndex := 2; end else if s = '14400' then begin ComboBoxBaud.ItemIndex := 3; end else if s = '19200' then begin ComboBoxBaud.ItemIndex := 4; end else if s = '28800' then begin ComboBoxBaud.ItemIndex := 5; end else if s = '38400' then begin ComboBoxBaud.ItemIndex := 6; end;
Delphi-Quellcode:
Endlich mal eine sinnvolle Anwendung für diese Funktion, die ich aus einer Zeitung habe:
const
maxB = 7; Bauds : array[0..maxB] of string = ('1200','2400','9600','14400','19200','28800','38400','55600'); //..... ComboBoxBaud.ItemIndex := NofStr(s, Bauds); //....
Delphi-Quellcode:
Wahrscheinlich wäre ich noch einen Schritt weiter gegangen und hätte statt String-Werte für die Baudrate Integer in meinem Array verwendet.
{liefert 0 ... n zurück, wenn s in sarr gefunden wurde, -1, wenn nicht}
function NofStr( s : string; sarr : array of string) : integer; var erg, i : integer; begin erg := -1; s := uppercase(s); for i := 0 to high(sarr) do begin if s = uppercase(sarr[i]) then begin erg := i; break; end; end; Result := erg; end; Vorsichtshalber: Das soll kein Mäkeln an Deinem Programm sein, sondern nur ein Hinweis zum Reduzieren von Aufwand. mfg eddy |
Nachtrag:
Hallo Daniel B, schau mal ins Thema "Mengen mit kompletten Strings?". Vielleicht sind diese Anregeungen für Deine Baudraten nützlich. mfg eddy |
Hello eddy,
Zitat:
Und ich sollte wirklich auf "CheckBox1.Checked := Geoeffnete;" umsteigen. Ich musss sowieso noch einiges "umkrempeln", da sich die Datenstruktur doch erheblich geändert hat. Das mit den ComPorts ist auch nciht schlecht, wobei ich da noch ein Filter mit rein bauen werde, damit die ganzen AVM-Karten usw. nicht erkannt werden. Denn die brauch ich ja nicht, sondern nur die serielle mit meinen BaudRaten, die die Du aufgelistet hast sind für mich nciht ganz zu gebrauchen, da ich nur die verwenden kann/darf die ich im Source drin habe. Aber ansonsten gefällt mir was Du geschrieben hast, vielleicht schaffe ich es doch noch unter 10.000 Zeilen zu bleiben. Danke Dir, aber erst muss ich noch ein Film schauen. :mrgreen: Grüsse, Daniel :hi: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:08 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz