www.ewlab.de
Delphi 2006
Delphi 2005
Kylix
Delphi 6
Delphi 5
Delphi 4
Impressum
Korrekturen
D4: Korrekturen

Korrekturen zu "Delphi 4"

Diese Seite nennt die wichtigsten Korrekturen an den Beispielprogrammen des Delphi 4-Buchs. Wenn Sie einen Programmfehler kennen, der hier nicht berücksichtigt wird, schreiben Sie bitte an ewarken@ewlab.de.

Korrekturen nach Beispielprogrammen:

 TRuler-Komponente

 ThreadDemo1

 TreeDesigner

 CDPlayer

TRuler-Komponente

Die TRuler-Komponente verursacht eine Division durch Null, wenn der Platz zum Zeichnen der Beschriftung nicht mehr ausreicht. Zur Korrektur genügt es, zwei Zeilen in die Methode TRuler.Paint einzufügen (Datei complib\rulers.pas). Wenn Sie die rulers.pas nicht modifiziert haben, können Sie sich an den im Folgenden angegebenen Zeilennummern orientieren, ansonsten an den zitierten Inhalten vor bzw. nach der Einfügeposition:

procedure TRuler.Paint
...
  TextAbst:=Canvas.TextWidth('9999');
- einfügen als Zeile 138: -
  if TextAbst <= PaintWidth then begin
    TextSteps:=PaintWidth div TextAbst; { maximale Anzahl von Beschriftungen }
... - einfügen als Zeile 191: - end; end; // Ende von TRuler.Paint

ThreadDemo1

ThreadDemo1 hat einen Fehler in der Initialisation: In ThreadDemoForm.pas endet die Methode TThreadDemo1Form.FormCreate mit der folgenden Anweisung:

GlobalProcs.UseSynchronize := UseSynchronize.Checked;

Diese Anweisung sollte an den Anfang der Methode verschoben werden, damit GlobalProcs.UseSynchronize initialisiert ist, bevor die Threads, in denen diese Variable verwendet wird, gestartet werden. In der Praxis hat dieser Fehler bisher keine negativen Wirkungen gezeigt.

In seltenen Fällen ist es bisher unter Windows NT zu Problemen mit dem Programmablauf gekommen, die möglicherweise an einer Inkompatibilität zwischen der VCL von Delphi 4 und Windows NT liegen (wie etwa, daß das Fenster nach dem Programmstart gar nicht erscheint; unter Delphi 5 wurde dieser Fehler bisher noch nicht gemeldet). Eine Umgehung dieses Fehlers ist beispielsweise durch die folgenden Maßnahmen möglich:

  • Deaktivieren Sie die Verwendung der Synchronize-Methode, indem Sie den entsprechenden Schalter im Hauptformular schon zur Entwurfszeit abschalten
  • oder unterbinden den sofortigen Start des Threads Panel 3: VCL-synchronisierter Thread, indem Sie in der Unit DemoThread1 die folgende kleine Änderung vornehmen:
constructor TDemoThread.Create(PB : TPaintBox);
begin
  inherited Create(True); // << "True" statt "False", also Start im "suspend"-Modus
  ...

TreeDesigner

Eine Division durch Null wird durch einen Fehler in TRuler-Komponente hervorgerufen.

Eine Verbesserung zum Verkleinern maximierter MDI-Kindfenster finden Sie auf der Korrekturseite zum Delphi 5-Buch.

Im TreeDesigner 2.5 funktioniert die Größenänderung von Grafikelementen teilweise nicht richtig. Verantwortlich dafür ist die Methode TDocumentForm.RectFromDragMode in der Unit DocForm:

(* Die folgende neue Version der Methode ersetzt die alte Version komplett *)
function TDocumentForm.RectFromDragMode(x, y : integer) : TRect;
{ RectFromDragMode berechnet das Rechteck des Umrisses, der während
  des Ziehvorgangs gezeichnet werden soll. Das Rechteck ist vom
  DragMode, vom Startpunkt des Ziehvorgangs und von der aktuellen
  Mausposition (angegeben in den Parametern) abhängig: }
var
  R, NR : TRect;
  MoveX, MoveY : integer;
begin
  case DragMode of
    dmResize: begin
      MouseObject.GetOriginalRect(R);
      // Veränderung der linken Seite
      if ResizeMode in [rmL, rmLT, rmLB] then begin
        if R.Left < R.Right then R.Left:=x else R.Right:=x;
      end;
      // Veränderung der rechten Seite
      if ResizeMode in [rmR, rmRT, rmRB] then begin
        if R.Left < R.Right then R.Right:=x else R.Left:=x;
      end;
      // Veränderung der unteren Seite
      (* ResizeMode ist eine Konstante mit T im Namen, wenn die untere Seite verändert wird.
         Es könnte möglicherweise logischer sein, diese Namen mit rmB, rmRB und rmLB zu vertauschen *)
      if ResizeMode in [rmT, rmRT, rmLT] then begin
        if R.Top < R.Bottom then R.Top:=y else R.Bottom:=y;
      end;
      // Veränderung der oberen Seite
      (* Bemerkung zu den Namen rmB, rmRB und rmLB siehe vorhergehender Fall! *)
      if ResizeMode in [rmB, rmRB, rmLB] then begin
        if R.Top < R.Bottom then R.Bottom:=y else R.Top:=y;
      end;
      Result:=R;
    end;
    (* ab hier keine Änderungen mehr *)
    dmMark, dmCreate:
      Result:=Rect(DragStartX, DragStartY, x, y);
    dmMove, dmMoveTree: begin
      MouseObject.GetNormalizedRect(R);
      MoveX:=x-DragStartX; MoveY:=y-DragStartY;
      OffsetRect(R, MoveX, MoveY);
      Result:=R;
    end;
  end;
end;

CD-Player

In der Formulardatei des Progammieren-Dialogs ist eine CheckListBox-Komponente abhanden gekommen, die Sie manuell wieder hinzufügen müssen (Name: CheckLB, Position: siehe Buch, Seite 385).

Außerdem berücksichtigt der CD- berücksichtigt nicht die unter Delphi 4 eingetretene Änderung der VCL, daß das Laufwerk, von dem die CD abgespielt werden soll, schon vor dem Aktivieren der TMediaPlayer-Komponente im FileName-Property angegeben werden muß. Bis Delphi 3 hat TMediaPlayer das CD-Laufwerk selbständig ermittelt. Um unter Delphi 4 ein funktionstüchtiges Beispielprogramm zu erhalten, schalten Sie das Property MediaPlayer1.AutoOpen im Entwurfsmodus auf False und ändern die Unit CDPForm wie folgt:

function IsCDROM(Drive: char) : boolean;
// Siehe auch auf der amerikanischen Borland-Website:
// "FAQ2756D.txt   Does my CD-ROM Drive contain an Audio CD?"
var
  DrivePath : string;
  MaximumComponentLength : DWORD;
  FileSystemFlags : DWORD;
  VolumeName : string;
begin
  Result := False;
  DrivePath := Drive + ':\';
  if GetDriveType(PChar(DrivePath)) <> DRIVE_CDROM then exit;
  Result := True;
  SetLength(VolumeName, 64);
  GetVolumeInformation(PChar(DrivePath),
                       PChar(VolumeName),
                       Length(VolumeName),
                       nil,
                       MaximumComponentLength,
                       FileSystemFlags,
                       nil,
                       0);
end;
procedure TCDPMainForm.FormCreate(Sender: TObject);
var
  Drive: char;
  FoundCDROM: Boolean;
begin
  TitleList:=TStringList.Create;
  DisplayNormal:=True;
  ProgramPos:=-1;
  StepWidth:=10;
  MediaPlayer1.TimeFormat:=tfTMSF;
  FoundCDROM := False;
  Drive := 'A';
  repeat
    if IsCDROM(Drive) then begin
      FoundCDROM := True;
      MediaPlayer1.Filename:=Drive+':';
      try
        MediaPlayer1.Open;
        { Für den Fall, daß hier noch keine Audio-CD eingelegt ist, wird
          der Aufruf von Open sicherheitshalber wiederholt, wenn der
          Schalter "Neu einlesen" gedrückt wird (siehe Methode ReadNewClick). }
        ReadNewClick(nil);
      except
        // wahrscheinlich noch keine Audio-CD eingelegt - ignorieren
      end;
    end;
    inc(Drive);
  until (Drive = 'Z') or FoundCDROM;
  if not FoundCDROM then
    ShowMessage('Kein CD-ROM-Laufwerk gefunden.');
end;

Zwei weitere kleine Änderungen betreffen die Methoden Timer1Timer und ReadNewClick. In Timer1Timer:

procedure TCDPMainForm.Timer1Timer(Sender: TObject);
...
  with Mediaplayer1 do begin
  (** geänderte Zeile: **)
  if (Mode=mpStopped) or (Mode=mpPlaying) or (Mode=mpPaused) then begin
    if DisplayNormal then begin (** ab dieser Zeile unverändert **)

In ReadNewClick muß TMediaPlayer.Open aufgerufen werden, falls bisher keine CD eingelegt war und daher die Methode Open beim Start des Programms gescheitert ist:

procedure TCDPMainForm.ReadNewClick(Sender: TObject);
begin
  (* Neue Zeile *)
  MediaPlayer1.Open;
[www.ewlab.de] [Delphi 2006] [Delphi 2005] [Kylix] [Delphi 6] [Delphi 5] [Delphi 4] [Impressum]