Entwickler-Ecke
Sonstiges (Delphi) - Komponente und Form mit .Close .Free sauber beenden
CoWa - Do 21.08.08 14:41
Titel: Komponente und Form mit .Close .Free sauber beenden
Hallo,
Verwendete Delphiversion: 5
Wenn ich auf den Reboot Button Klicke bekomme ich eine Zugriffsverletzung.
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| procedure KeyboardClose(); begin Form1.mfSoftkeysControl1.ClosePage; Form1.mfSoftkeysControl1.Destroy; Form1.mfSoftkeysControl1.free; end; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.BTNRebootClick(Sender: TObject); begin
KeyboardClose; ShellExecute(0, 'open', 'shutdown.exe', '-r -f -t 0', 'C:\WINDOWS\SYSTEM32\', SW_SHOWNORMAL); Form1.Close;
end; |
Wenn ich nur so einen Neustart erzwinge ohne die Form zu schließen bekomme ich die Fehlermeldung das eine Komponente (mfSoftkeysControl1) nicht beendet wurde.
Ideen wie ich das besser lösen kann?
Gruß CoWa
Martin1966 - Do 21.08.08 14:44
Titel: Re: Komponente und Form mit .Close .Free sauber beenden
Keine Ahnung was die Komponente macht aber pack auf jeden Fall das Destroy raus...
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure KeyboardClose(); begin Form1.mfSoftkeysControl1.ClosePage; Form1.mfSoftkeysControl1.free; end; |
Der Aufruf von Free ruft nämlich intern den Destruktor selbst auf.
Lg, Martin
Boldar - Do 21.08.08 14:44
Titel: Re: Komponente und Form mit .Close .Free sauber beenden
CoWa hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure KeyboardClose(); begin Form1.mfSoftkeysControl1.ClosePage; Form1.mfSoftkeysControl1.Destroy; Form1.mfSoftkeysControl1.free; end; |
|
[edit]Shit...Wo war den da wieder dieses Orange ding??[/edit]
Martin1966 - Do 21.08.08 14:45
Titel: Re: Komponente und Form mit .Close .Free sauber beenden
Boldar hat folgendes geschrieben: |
Niemals free und destroy gleichzeitig aufrufen! |
Soweit ich weiß sollte man NUR
destroy nie aufrufen!
Boldar - Do 21.08.08 14:50
Titel: Re: Komponente und Form mit .Close .Free sauber beenden
Martin1966 hat folgendes geschrieben: |
Boldar hat folgendes geschrieben: | Niemals free und destroy gleichzeitig aufrufen! |
Soweit ich weiß sollte man NUR destroy nie aufrufen! |
Wenn du destroy aufrufst, wird intern schon free aufgerufen. Wenn du dann nochmal free aufrufst, ist es einmal zu viel!
Martin1966 - Do 21.08.08 14:53
Titel: Re: Komponente und Form mit .Close .Free sauber beenden
Boldar hat folgendes geschrieben: |
Wenn du destroy aufrufst, wird intern schon free aufgerufen. |
Nein, eigentlich nicht.
Wenn man Free aufruft wird Destroy intern aufgerufen. Anders herum nicht.
Lg, Martin
Yogu - Do 21.08.08 14:57
Free prüft das Objekt zuerst auf
nil und ruft gegebenfalls
Destroy auf. Deshalb gelten zwei Regeln:
- Rufe Destroy niemals selber auf - dazu ist Free da.
- Globale oder kritische Objektvariablen müssen immer entweder auf ein gültiges Objekt zeigen, oder nil sein. Andernfalls würde ein Free auch eine Zugriffsverletzung auslösen. Also: nach Free die Variable immer auf nil setzen, oder einfach gleich FreeAndNil aufrufen.
Martin1966 - Do 21.08.08 15:06
Yogu hat folgendes geschrieben: |
Rufe Destroy niemals selber auf - dazu ist Free da. |
Ja, so hab ich es ja schon geschrieben. ;-)
Yogu hat folgendes geschrieben: |
Globale oder kritische Objektvariablen müssen immer entweder auf ein gültiges Objekt zeigen, oder nil sein. |
Das sehe ich nicht so. Ein Objekt das ich freigeben will sollte meiner Meinung nach nie NIL sein. Denn das würde ja bedeuten das ich entweder ein Objekt freigeben will das noch gar nicht erstellt wurde oder aber das ich ein Objekt freigeben will welches bereits freigegeben wurde. Beides ist meiner Meinung nach Fehler. Denn: Ein mal ein Objekt erzeugen heißt auch nur (genau) einmal das Objekt wieder freigeben!
Yogu hat folgendes geschrieben: |
Andernfalls würde ein Free auch eine Zugriffsverletzung auslösen. Also: nach Free die Variable immer auf nil setzen, oder einfach gleich FreeAndNil aufrufen. |
Genau das soll es ja auch damit ich als Entwickler auf diesen Fehler aufmerksam werde. ;-) FreeAndNil versteckt nur diesen Fehler.
Lg, Martin
Yogu - Do 21.08.08 15:16
Ok, vielleicht siehst du das anders. Aber meiner Meinung nach darf ein Objekt durchaus mal nil sein, bevor ich versuche, es freigebe. Ein Beispiel:
Eine 3D-Engine, die ein Sound-Modul besitzt. Dieses wird nicht automatisch erstellt, sondern durch eine Methode. Eine zweite gibt das Modul wieder frei. Weil die Engine aber saubar geschrieben ist, wird auch beim Entfernen der Engine das Sound-Modul wieder entfernt, falls das nicht manuell geschah. Wenn es jetzt durch die Methode freigegeben wird, muss das Objekt genillt werden, um anzuzeigen, dass es nicht mehr existiert.
Martin1966 - Do 21.08.08 15:33
Yogu hat folgendes geschrieben: |
Weil die Engine aber saubar geschrieben ist, |
Da du davon ausgehst, dass der Programmierer, der die Engine verwendet, nicht sauber programmiert hat, musst du das Objekt eventl. selbst freigeben. Ok. Aber das ist denke ich ein Sonderfall. Wie du die Überprüfung machst (ob auf NIL überprüfen oder eine Boolean Variable setzen) ist dann natürlich Geschmacksache.
Lg, Martin
Yogu - Do 21.08.08 15:43
Ok, dann eben noch ein Versuch, dich zu überzeugen: Der Programmierer will nun wissen, ob das Sound-Modul schon initialisiert wurde. Beziehungsweise noch verfügbar ist. Wenn das Modul einfach freigegeben wurde, liefert Assigned(SoundModule) True. Er weiß also nicht, ob er auf das Modul zugreifen darf oder nicht. Bevor du mir jetzt mit einer Boolean-Variable kommst: Wozu eine neue Variable vereinbaren, wo wir doch schon eine haben? Das ist nur eine zusätzliche Fehlerquelle, denn wenn die beiden widersprüchlich sind, dann ist es aus mit der Kontrolle.
Martin1966 - Do 21.08.08 15:54
Ich hatte doch schon angedeutet, dass es bei Bibliotheken eventl. Sinn machen könnte.
Zitat: |
Der Programmierer will nun wissen, ob das Sound-Modul schon initialisiert wurde. Beziehungsweise noch verfügbar ist. |
Dann stelle ich mal die Frage: Warum weiß der Programmierer das nicht? Entweder er hat das Sound-Modul initialisiert oder eben nicht. ;-) Aber wie auch immer: Ich will jetzt nicht rum diskutieren ob es in einer Bibliothek, wo ein Programmierer von Außen Objekt initialisieren und wieder frei geben kann, sinn macht oder nicht.
Lg, Martin
iKilledKenny - Do 21.08.08 16:00
Martin1966 hat folgendes geschrieben: |
Das sehe ich nicht so. Ein Objekt das ich freigeben will sollte meiner Meinung nach nie NIL sein. Denn das würde ja bedeuten das ich entweder ein Objekt freigeben will das noch gar nicht erstellt wurde oder aber das ich ein Objekt freigeben will welches bereits freigegeben wurde. Beides ist meiner Meinung nach Fehler. Denn: Ein mal ein Objekt erzeugen heißt auch nur (genau) einmal das Objekt wieder freigeben! |
Das sehe ich auch anders, z.B. finde ich folgendes ein sehr elegantes Konstrukt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| var list: TList;
begin list := nil; try if (irgendwas > irgendwasAnderes) then Exit;
list := TList.Create; finally list.Free; end; end; |
Martin1966 - Do 21.08.08 16:04
iKilledKenny hat folgendes geschrieben: |
z.B. finde ich folgendes ein sehr elegantes Konstrukt. |
Du findest es also elegant ein Objekt freizugeben welches nicht initialisiert wurde - also Sourcecode umsonst auszuführen? Hm... :gruebel: ich jedenfalls nicht. ;-)
Lg, Martin
iKilledKenny - Do 21.08.08 16:06
Initialisiert schon, aber eben mit nil. Analog verfahre ich auch mit Strings (''), Integern (0) etc.
:tongue:
Yogu - Do 21.08.08 16:12
Den
try ... finally-Block brauchst du nur um das
Create zu spannen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var list: TList; begin list := nil; if (irgendwas > irgendwasAnderes) then Exit;
list := TList.Create; try finally list.Free; end; end; |
Allerdings kommt dann die Meldung, dass
list zugewiesen wurde, der Wert aber nicht verwendet wurde. In diesem Fall kannst du die Initialisierung also weglassen. Aus diesem Grund initialisiert Delphi die Variablen nicht - dadurch werden Befehle und somit Zeit gespart. Du solltest Variablen nur dann initialisieren, wenn es auch notwendig ist.
iKilledKenny - Do 21.08.08 16:15
Das Beispiel war vielleicht ein bischen kurz und knapp. Wenn ich solch ein Konstrukt verwende, dann meistens in großen Routinen mit vielen Objekt-Variablen. Am Anfang initialisiere ich die alle mit nil und beim Verlassen ruf ich für alle ein free auf. Damit gehe ich sicher, dass ich jederzeit aus dieser Routine rauspringen kann und kein Speicherleck habe.
Das mit dem Rauspringen im Übrigen deshalb, weil es den Code wesentlich lesbarer macht. Man hat keine 14. Einrückung mehr in der 6 geschachtelten if-Abfrage und solch Zeug.
CoWa - Do 21.08.08 16:39
Hab das .destroy entfernt, Zugriffsfehler bleibt aber erhalten :(
Boldar - Do 21.08.08 16:44
Dann müsstest du vielleicht mehr code rausrücken, meine Kristallkugel hat grad nen Sprung!
elundril - Do 21.08.08 16:44
gibst du vielleicht etwas frei was noch gar nicht exisitiert??
Vielleicht wird die Procedure mit dem Create vorher gar nicht aufgerufen..
lg elundril
mkinzler - Do 21.08.08 16:46
elundril hat folgendes geschrieben: |
gibst du vielleicht etwas frei was noch gar nicht exisitiert??
Vielleicht wird die Procedure mit dem Create vorher gar nicht aufgerufen..
lg elundril |
Dann sollte
.Free() das aber erkennen
elundril - Do 21.08.08 16:47
Nicht zwangsläufig, denke ich. Ich habe so das gefühl das bei meinen Programmen, wenn ich da was gefreeed habe was noch nicht existierte das dann das programm gemeckert hat.
lg elundril
jaenicke - Do 21.08.08 18:45
Der Name der freizugebenden Variable sieht für mich so aus als ob es sich um eine Komponente handelt, die auf dem Formular liegt, und falls das so ist, dann sollte man die auch nicht einfach freigeben, denn das geschieht automatisch.
Freigeben sollte man nur, was man auch vorher per Code erstellt hat und was nicht zum automatischen Freigeben bei der Elternkomponente eingetragen wurde.
CoWa - Mo 25.08.08 15:47
So, mal mehr Code:
Sagt mir einfach wo ihr noch etwas sehen wollt:)
Ich kann gezielt per PM auch den kompletten Code versenden.
Gruß Cornelius
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, ComCtrls, OleServer, KBDLib_TLB, Registry, ShellApi, FileCtrl, ExtCtrls; type TForm1 = class(TForm) PageControlKonfiguration: TPageControl; TabSheetAllgemein: TTabSheet; TabSheetSystem: TTabSheet; TabSheetAnwendung: TTabSheet; Sicherheit: TTabSheet; TabSheet5: TTabSheet; TabSheet6: TTabSheet; TabSheet7: TTabSheet; TabSheetXPeSpeichern: TTabSheet; GroupBoxAdminpasswort: TGroupBox; lblPasswort: TLabel; EditPassword: TEdit; BTNPasswortOK: TButton; GroupBoxUserinterface: TGroupBox; BTNanwendung: TButton; BTNkalibrieren: TButton; GroupBoxTouchtastatur: TGroupBox; BTNTastaturEin: TButton; BTNTastaturAus: TButton; TrackBar1: TTrackBar; mfSoftkeysControl1: TmfSoftkeysControl; Label1: TLabel; StaticText1: TStaticText; StaticText2: TStaticText; GroupBoxComputername: TGroupBox; EditComputername: TEdit; BTNComputernameAendern: TButton; GroupBoxSystemsteuerung: TGroupBox; BTNSystemsteuerung: TButton; BTNExplorer: TButton; BTNCMD: TButton; BTNRegedit: TButton; BTNEditor: TButton; OpenDialog1: TOpenDialog; GroupBoxAnwendung: TGroupBox; LBLAnwendung: TLabel; BTNAnwendung_auswaehlen: TButton; Image2: TImage; Image1: TImage; Image3: TImage; Image4: TImage; Image5: TImage; Image6: TImage; Image7: TImage; Image8: TImage; GroupBoxTaskbar: TGroupBox; BTNshowtaskbarOn: TButton; BTNshowtaskbarOff: TButton; LBLshowtaskbar: TLabel; GroupBoxStartbutton: TGroupBox; GroupBoxDesktop: TGroupBox; BTNShowDesktopOn: TButton; BTNShowDesktopOff: TButton; BTNShowStartButtonOn: TButton; BTNShowStartButtonOff: TButton; LBLShowDesktop: TLabel; LBLShowStartButton: TLabel; GroupBoxShutdownWithoutLogon: TGroupBox; GroupBox2: TGroupBox; GroupBox3: TGroupBox; GroupBoxDisableLockWorkstation: TGroupBox; GroupBoxDisableChangePassword: TGroupBox; GroupBoxDisableTaskMgr: TGroupBox; GroupBox7: TGroupBox; GroupBox8: TGroupBox; BTNReboot: TButton; BTNShutdown: TButton; BTNReboot2: TButton; BTNShutdown2: TButton; BTNShutdownWithoutLogonOn: TButton; BTNShutdownWithoutLogonOff: TButton; BTNNoShutdownButtonOn: TButton; BTNNoShutdownButtonOff: TButton; BTNDisableLockWorkstationOn: TButton; BTNDisableLockWorkstationOff: TButton; BTNDisableChangePasswordOn: TButton; BTNDisableChangePasswordOff: TButton; BTNDisableTaskMgrOn: TButton; BTNDisableTaskMgrOff: TButton; Button9: TButton; Button10: TButton; Button11: TButton; Button12: TButton; Button13: TButton; Button14: TButton; LBLShutdownWithoutLogon: TLabel; LBLNoShutdownButton: TLabel; LBLDisableLockWorkstation: TLabel; LBLDisableChangePassword: TLabel; LBLDisableTaskMgr: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; procedure BTNPasswortOKClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure EditPasswordKeyPress(Sender: TObject; var Key: Char); procedure TrackBar1Change(Sender: TObject); procedure BTNTastaturEinClick(Sender: TObject); procedure BTNTastaturAusClick(Sender: TObject); procedure EditComputernameKeyPress(Sender: TObject; var Key: Char); procedure PageControlKonfigurationChange(Sender: TObject); procedure BTNComputernameAendernClick(Sender: TObject); procedure BTNSystemsteuerungClick(Sender: TObject); procedure BTNExplorerClick(Sender: TObject); procedure BTNEditorClick(Sender: TObject); procedure BTNRegeditClick(Sender: TObject); procedure BTNCMDClick(Sender: TObject); procedure BTNkalibrierenClick(Sender: TObject); procedure BTNAnwendung_auswaehlenClick(Sender: TObject); procedure URL4logistic(Sender: TObject); procedure BTNshowtaskbarOnClick(Sender: TObject); procedure BTNshowtaskbarOffClick(Sender: TObject); procedure BTNShowDesktopOnClick(Sender: TObject); procedure BTNShowDesktopOffClick(Sender: TObject); procedure BTNShowStartButtonOnClick(Sender: TObject); procedure BTNShowStartButtonOffClick(Sender: TObject); procedure BTNRebootClick(Sender: TObject); procedure BTNShutdownClick(Sender: TObject); procedure BTNanwendungClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure BTNShutdownWithoutLogonOnClick(Sender: TObject); procedure BTNShutdownWithoutLogonOffClick(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.DFM}
function RegReadStr(rootkey: hkey; Key,Value: String): String; [...]
function RegReadInt(rootkey: HKEY; Key,Value: String): Integer; [...]
function RegWriteStr(rootkey: HKEY; Key, Value: String; Content: String): Boolean; [...]
function RegWriteInt(rootkey: HKEY; Key, Value: String; Content: Integer): Boolean; [...]
function RegWriteDWORD(rootkey: HKEY; Key, Value: String; Content: DWORD): Boolean; [...]
function RegReadDWORD(rootkey: HKEY; Key,Value: String): DWORD; [...]
function GetComputerName: string; [...]
function SetComputerName(AComputerName: string): Boolean; [...]
procedure ShowTaskBar(AShow: Boolean); [...]
procedure ShowWindowsStartButton(bvisible: Boolean); [...]
procedure ShowDesktop(bVisible: boolean); [...]
procedure KeyboardClose(); begin Form1.mfSoftkeysControl1.ClosePage; Form1.mfSoftkeysControl1.free; end;
procedure TForm1.BTNPasswortOKClick(Sender: TObject); [...]
procedure TForm1.FormCreate(Sender: TObject); var I: Integer; begin LBLAnwendung.Caption := RegReadStr(HKEY_CURRENT_USER,'Software\4logistic\Anwendung\','Default'); TrackBar1.Position := RegReadInt(HKEY_CURRENT_USER,'Software\4logistic\Tastatur\','Blend'); with PageControlKonfiguration.Pages[0] do For I := 0 to PageControlKonfiguration.PageCount-1 do PageControlKonfiguration.Pages[I].TabVisible := False; PageControlKonfiguration.Pages[0].TabVisible := TRUE;
[...]
[...]
[...]
[...]
mfSoftkeysControl1.Hide;
end;
procedure TForm1.EditPasswordKeyPress(Sender: TObject; var Key: Char); [...]
procedure TForm1.TrackBar1Change(Sender: TObject); begin mfSoftkeysControl1.Blend := TrackBar1.Position;
RegWriteInt(HKEY_CURRENT_USER,'Software\4logistic\Tastatur\','Blend',TrackBar1.Position); end;
procedure TForm1.BTNTastaturEinClick(Sender: TObject); begin mfSoftkeysControl1.Blend := RegReadInt(HKEY_CURRENT_USER,'\Software\4logistic\Tastatur\','Blend');
mfSoftkeysControl1.Connect; mfSoftkeysControl1.LoadKeyboard( 'C:\Tastatur\BlackWhite_deutsch4.kbd' ); mfSoftkeysControl1.Position := 4; mfSoftkeysControl1.Top := 200; TrackBar1.Position := mfSoftkeysControl1.Blend; mfSoftkeysControl1.Show; end;
procedure TForm1.BTNTastaturAusClick(Sender: TObject); begin mfSoftkeysControl1.hide; end;
procedure TForm1.EditComputernameKeyPress(Sender: TObject; var Key: Char); begin if key = Char(VK_Return) then Form1.BTNComputernameAendern.Click; end;
procedure TForm1.PageControlKonfigurationChange(Sender: TObject); [...]
procedure TForm1.BTNComputernameAendernClick(Sender: TObject); [...]
procedure TForm1.BTNSystemsteuerungClick(Sender: TObject); [...]
procedure TForm1.BTNExplorerClick(Sender: TObject); [...]
procedure TForm1.BTNEditorClick(Sender: TObject); [...]
procedure TForm1.BTNRegeditClick(Sender: TObject); [...]
procedure TForm1.BTNCMDClick(Sender: TObject); [...]
procedure TForm1.BTNkalibrierenClick(Sender: TObject); [...]
procedure TForm1.BTNAnwendung_auswaehlenClick(Sender: TObject); [...]
procedure TForm1.URL4logistic(Sender: TObject); [...]
procedure TForm1.BTNshowtaskbarOnClick(Sender: TObject); [...]
procedure TForm1.BTNshowtaskbarOffClick(Sender: TObject); [...]
procedure TForm1.BTNShowDesktopOnClick(Sender: TObject); [...]
procedure TForm1.BTNShowDesktopOffClick(Sender: TObject); [...]
procedure TForm1.BTNShowStartButtonOnClick(Sender: TObject); [...]
procedure TForm1.BTNShowStartButtonOffClick(Sender: TObject); [...]
procedure TForm1.BTNRebootClick(Sender: TObject); [...]
procedure TForm1.BTNShutdownClick(Sender: TObject); [...]
procedure TForm1.BTNanwendungClick(Sender: TObject); [...]
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin KeyboardClose; PageControlKonfiguration.Free; Form1.Free; end;
procedure TForm1.BTNShutdownWithoutLogonOnClick(Sender: TObject); [...]
procedure TForm1.BTNShutdownWithoutLogonOffClick(Sender: TObject); [...]
end. |
Tilman - Mo 25.08.08 16:07
Weiß ja net was jetzt genau das problem ist, aber man sollte Komponenten nie in ihrer eigenen Ereignisbehandlung freigeben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin KeyboardClose; PageControlKonfiguration.Free; Form1.Free; end; |
zitat Delphi-Hilfe:
Zitat: |
Warnung: Sie dürfen eine Komponente nie in einer ihrer eigenen Ereignisbehandlungsroutinen oder in einer Ereignisbehandlungsroutine eines untergeordneten Objekts freigeben. Geben Sie beispielsweise auf keinen Fall eine Schaltfläche oder ihr übergeordnetes Formular in der OnClick-Ereignisbehandlungsroutine der Schaltfläche frei.
Um ein Formular freizugeben, ruften Sie seine Methode Release auf. Dadurch wird sichergestellt, dass das Formular erst aus dem Speicher entfernt wird, wenn die Ausführung seiner eigenen und der Ereignisbehandlungsroutinen seiner Komponenten beendet ist.
|
CoWa - Mo 25.08.08 16:16
Hab deinen Vorschlag beherzigt und Form1.free auskommentiert.
Problem: Wenn ich TForm1.BTNRebootClick ausführe erhalte ich einen Zugriffsfehler
CoWa - Mo 25.08.08 16:41
Nachdem ich Form1.Free entfernt habe bekomme ich wieder die "Com Server Warning" Fehlermeldung. (Siehe Anhang)
Boldar - Di 26.08.08 19:43
dann nimm halt form1.release!!!
CoWa - Do 28.08.08 14:45
Danke dir! :) Vielen dank. Deine Loesung funktioniert. Werde mir mal den Unterschied zwischen .free .close und .release durchlesen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!