Unit MiscDebugWindows; { Ideally the user will never see one of these. It displays text messages. It is very generic so that a lot of different code could use it. } Interface // TODO Need to make a switch to turn the debug stuff on and off. Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; Type TMiscDebugWindow = class(TForm) Memo1: TMemo; Timer1: TTimer; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private ReadyForWrite : Boolean; NewStuff : String; public Procedure AddMessage(M : String; Ex : Exception = Nil); end; // This will create the window if it does not already exist. Procedure SendMiscDebugMessage(Var W : TMiscDebugWindow; M : String; Owner : TComponent = Nil); Overload; // There is one global window for people who don't want a window of their // own. Procedure SendMiscDebugMessage(M : String); Overload; // This will format the exception into an appropriate message. This uses the // shared window from the previous procedure. Procedure SendMiscDebugMessage(Ex : Exception; Location : String); Overload; Var MiscDebugWindow: TMiscDebugWindow; Implementation {$R *.dfm} Procedure TMiscDebugWindow.FormCreate(Sender: TObject); Begin WindowState := wsMinimized End; Procedure TMiscDebugWindow.AddMessage(M : String; Ex : Exception = Nil); Begin If Not ReadyForWrite Then Begin ReadyForWrite := True; Timer1.Enabled := True; End; If NewStuff = '' Then NewStuff := M Else NewStuff := NewStuff + #13#10 + M; Visible := True End; Procedure TMiscDebugWindow.FormClose(Sender: TObject; Var Action: TCloseAction); Begin // We have to minimize the window here or it becomes annoying. If we get // one message, we will often get a stream of messages. If we don't // minimize the window, it is likely to pop up again exactly where it was // right after the user closes it. WindowState := wsMinimized; // We always hide the window to keep the memory management simple. Once // you've created a window you can assume that it exists until you delete // it. Otherwise you will have to watch for a user who might have closed // the window. //removed as this breaks new MDI //Action := caHide End; procedure TMiscDebugWindow.Timer1Timer(Sender: TObject); begin ReadyForWrite := False; Timer1.Enabled := False; Memo1.Lines.Add(NewStuff); NewStuff := '' end; Procedure SendMiscDebugMessage(Var W : TMiscDebugWindow; M : String; Owner : TComponent = Nil); Begin If Not Assigned(W) Then W := TMiscDebugWindow.Create(Owner); W.AddMessage(M) End; Var SharedDebugWindow : TMiscDebugWindow; Procedure SendMiscDebugMessage(M : String); Begin SendMiscDebugMessage(SharedDebugWindow, M) End; Procedure SendMiscDebugMessage(Ex : Exception; Location : String); Begin Try SendMiscDebugMessage('Class=' + Ex.ClassName + ', Message=' + Ex.Message + ', Location=' + Location) Except // This function will often be called in a try/except block because we // have an exception that we don't know what to do with so we are // ignoring it. If there was an exception in this code then we'd // destroy that logic. We'd throw an unexpected exception in the // exception handler. End End; end.