Delphi4/5

Hier handelt es sich um Sachen aus dem letzten Jahrtausend ;).  Programmiert wurden die Beispiele mit Borland Delphi 2/4 und Inprise Delphi 5. Ich verwende immernoch Delphi 5 und obwohl es so alt ist kann man die Programme problemlos auch noch auf Windows 10 laufen lassen.

 

Delphi mit Sqlite

Sqlite verwendet SQL Befehle um auf eine "lokale" Datenbank zu zugreifen. Dies ist etwa vergleichbar mit dem Zugriff auf eine DBase-Datenbank. Allerdings kann man bei Sqlite direkt per SQL zugreifen und der wohl größte Vorteil ist, dass man die BDE nicht mitliefern muss um es zu nutzen.
Sqlite wird auch mit php5 mitgeliefert und man kann davon ausgehen, dass Bugs, soweit vorhanden, somit schnell erkannt und beseitigt werden.

Sqlite findest du unter: http://sqlite.org

Für Delphi gibt es auch schon eine Komponentensammlung, die mit Sqlite arbeitet (SQLITE open source components) . Diese basiert auf TDataset und somit sind alle "Datensteuerung"s-Komponenten verwendbar.

Die Komponentensammlung findest du unter http://www.aducom.com/sqlite/

Achtung: die in der aktuellen Version 2005.02.A ist eine sqlite3.dll beigelegt, die nicht funktioniert. Einfach die Dll direkt von Sqlite verwenden, dann geht es ;)


Exe schrumpfen

Delphi erzeugt relativ große Exe-Dateien. Wenn du diese ohne großen Aufwand schrumpfen möchtest solltest du dir UPX (http://upx.sourceforge.net/) anschauen. Der Download deiner Software wird kleiner, was deine Kunden freut ;)


Paradox-Dateien im Netzwerk

Wer  auf Paradox-Dateien in Netzwerk zugreifen will, sollte nicht gleich verzweifeln, wenn die Meldung kommt:  Die Datei sei gesperrt oder der Zugriff nicht möglich. Ich habe lange daran gebissen und dann die Lösung gefunden.

Beim Form Create tragt Ihr einfach die Zeile Session.NetFileDir='X:\MeinNetz'; 
ein und das war's. Achtung, vorher darf noch keine DB-Komponente auf die Datenbanken zugreifen!!! Sonst nutzt das alles nix, wenn ein 2ter Benutzer was machen will. Achso außerdem muss bei allen Benutzern das gleiche eingetragen sein - also Mappings überall gleich anlegen! 
Noch etwas, den Eintrag kann man auch in der BDE-Konfig. machen aber naja, dann muss man die auch noch verwalten...


 

Coolbar Hintergrund und 256 Farben

Wenn man Hintergrundbitmaps in der Coolbar verwendet verhalten sich die Toolbars, die auf der Toolbar sitzen etwas seltsam wenn man die Farbtiefe von 256 Farben einstellt. Um das ganze zu umgehen, kann man Hintergrundbitmaps mit 16 Farben verwenden, was allerdings nicht sehr schön aussieht. Wenn ich davon ausgehe, dass die Mehrzahl der Windows Benutzer heute mehr als 256 Farben haben, bin ich zu der Entscheidung gekommen diesen Benutzern einfach das Hintergrund vorzuenthalten. Also muß ich beim Formcreate die Farbetiefe ermitteln und die Bitmap aus dem Speicher entfernen. Delphi stellt leider keine eigene Function zur Verfügung um die Farbtiefe zu ermitteln aber keine Angst die folgende Function liefert die Farbtiefe:

Function GetColorDepth:byte;
   {Results:
     4=> 16 Farben
     8=> 256 Farben
   16=> 24KB Farben
   24=> True Color
   }
begin
  Result:=GetDeviceCaps(GetDC(
  GetActiveWindow),BITSPIXEL);
end;

Im FormCreate füge ich also folgende Zeile ein:

If  GetColorDepth<16 then Coolbar1.bitmap:=nil;

Dies funktioniert natürlich auch, wenn man andere components verwendet, die z.B. den Formhintergrund füllen. Oder lädt zur Laufzeit unterschiedliche Bitmaps für die unterschiedlichen Farbtiefen.


Programme starten mit Delphi

Delphi

Ich kenne nun einige Methoden um aus Delphi heraus andere Anwendungen zu starten. Die einfachste ist wohl Winexec. Winexec stammt aber noch aus der 16bit Zeit und deshalb nur mit Vorbehalt zu empfehlen. Die größte Schwierigkeit unter Win32 bzw. seit Delphi 2 besteht darin die eigene Anwendung solange anzuhalten, wie das andere Programm ausgeführt wird. Sicherlich braucht man das nicht immer, aber diese Routine beherrscht es :-)

function fileExec(const aCmdLine: String; aHide, aWait: Boolean): Boolean;
var
   StartupInfo : TStartupInfo;
   ProcessInfo : TProcessInformation;
begin
   {setup the startup information for the application }
    FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
   with StartupInfo do
    begin
     cb:= SizeOf(TStartupInfo);
     dwFlags:= STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
     if aHide
      then wShowWindow:= SW_HIDE
      else wShowWindow:= SW_SHOWNORMAL;
    end;

    Result := CreateProcess(nil,PChar(aCmdLine), nil, nil, False,
    NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo);
    if aWait then
      if Result then
      begin
        WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
        WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
      end;
end;

Ich muß hinzufügen, dass diese Routine nicht von mir selbst ist. Mit freundlicher Erlaubnis des Author Stefan Böther kann man die angehängten XProcs hier downloaden ;)

Anhang Größe
xprocs.zip 46.99 KB

Treeview mit Datenbank Zugriff

Daten in einer Baumdarstellung darzustellen, ist eine feine Sache, wenn man weiß wie. Die TTreeview-Component ist nicht besonders benutzerfreundlich, und so schrecken viele Programmierer davor zurück. Doch die Vorteile dieser wirklich übersichtlichen und benutzerfreundlichen Darstellungsweise alla Windows-Explorer ist nicht von der Hand zuweisen.

Ich habe für die Feburarausgabe des Delphianer ein kleines Projekt erstellt, welches die Funktionsweise von TTreeView an einem einfachen Beispiel zeigt. Der Quelltext enthält Beschreibungen zu den einzelnen Proceduren und Functions. also einfach downloaden und ausprobieren.

Anhang Größe
feb99.zip 6.7 KB

 


Delphi goes MS-Word

Im letzten Excel-Beispiel habe ich gezeigt, wie einfach der Zugriff auf Excel ist und genauso einfach kann man auch auf MS-Word zugreifen und Briefe mit der Geisterhand schreiben. Auch hier werde ich nur den grundsätzlichen Zugriff erklären und wie man sich über Makroaufzeichnung den nötigen Quelltext für Delphi erarbeiten kann.

Zuerst habe ich mir folgendes Macro aufgezeichnet:

Sub Makro1()
Documents.Add
Selection.TypeText Text:= "Hallo Leute, dies ist ein Zugriff über Delphi :-)"
Selection.TypeParagraph
Selection.TypeParagraph
Selection.Font.Bold = wdToggle
Selection.Font.Size = 12
Selection.Font.Name = "Arial"
Selection.TypeText Text:="Toll oder?!"
End Sub

Mit diesem Macro erstelle ich mir meinen Delphiquelltext:

1. Als erstes muß ich die benötigte Unit in die uses clausel aufnehmen:

uses OLEAuto //in Delphi 2
uses  ComObj //in Delphi 3 und 4

 

2. Ich deklariere die Variable MSWord für den Zugriff auf Word

var MSWord:variant;

3. Nun muß ich noch eine Verbindung mit Word herstellen und ggf. abbrechen, wenn ein Fehler auftritt.

try
  Msword := CreateOleObject('Word.Application');
except
  ShowMessage('WORD konnte nicht gestartet werden !');
  Exit;
end;

4. Wenn ich die Verbindung erfolgreich herstellen konnte, kann ich loslegen zu schreiben:

Macrosource Delphisource Beschreibung
Documents.Add MsWord.Documents.Add; Neue Datei,
Selection.TypeText Text:= "Hallo Leute, dies ist ein Zugriff über Delphi :-)" MsWord.Selection.TypeText(Text:='Hallo Leute, dies ist ein Zugriff über Delphi :-)'); normalen Text einfügen
Selection.TypeParagraph MsWord.Selection.TypeParagraph Leerzeile
Selection.Font.Bold = wdToggle MsWord.Selection.Font.Bold := true; Fett
Selection.Font.Size = 12 MsWord.Selection.Font.Size := 12; Fontsize=12
Selection.Font.Name = "Arial" MsWord.Selection.Font.Name := 'Arial'; Arial-Font
Selection.TypeText Text:="Toll oder?!" MsWord.Selection.TypeText(Text:='Toll oder?!'); nun den formatierten Text

4. Wenn ich die Verbindung erfolgreich herstellen konnte, kann ich loslegen zu schreiben:

Msword.visible:=true;

Fertig! Viel Spaß beim "Ghostwriting" mit Delphi in Word.

 


Stringbearbeitung

Der Umgang mit Zeichenketten ist eine wichtige Aufgabe. Delphi bringt einige Funktionen mit die zwar sehr flexibel, aber im täglichen Umgang sehr zeitintensiv sind.

Beispiel:
Ich möchte einige Informationen in einer einzigen Zeichenkette unterbringen und mit einem Zeichen separieren. Das zusammensetzen einer solchen Information ist eigentlich ganz einfach. Nehmen wir an, ich möchte mir eine Adresse mit 6 Feldern in einer Zeichenkette ablegen und mit dem Zeichen | trennen. Ich habe mehrere Adressen, deshalb lege ich alles in einer Stringliste ab.

Felder : NAME, STRASSE, PLZ, ORT, TEL, FAX, EMAIL
AdrLst:=TStringlist.create;
AdrLst.Add('Hans Mustermann|Musterweg 9|12345|Musterstadt|(012345) 7788990|(012345) 7788991|hmuster@och.com')
AdrLst.Add('Franz Mustermann|Musterweg 9|12345|Musterstadt|(012345) 7788996|(012345) 7788999|fmuster@och.com')

u.s.w.

Jetzt könntest Du frage, warum mache ich das ganze nicht als Record und speichere das als typisierte Datei ab. Ganz einfach, um mir den Aufwand mit dem Zugriff auf typisierte Dateien zu sparen und ich nicht so viele Datensätze habe, speichere ich alles in eine INI-Datei ab und hole die Daten bei Bedarf aus der INI-Datei in den Speicher (TStringlist).

Ich möchte nun die einzelnen Felder in Editfelder einlesen und bei Bedarf wieder speichern. Dazu muss ich mir noch merken auf welchem Datensatz ich stehe, welches Feld geändert wurde, umsortieren u.s.w. - das spare ich mir aber nun, denn ich wollte nur ein Beispiel dafür bringen, wozu ich Zeichenketten teilen muss. Obwohl ich im Laufe der Zeit eine Reihe von guten Stringbehandlungsroutinen als Freeware gefunden habe, habe ich mir selbst eine function gebastelt, die für diesen Fall geeignet ist:

function ValuestrNr(instr:string;seperator:char;nr:byte):string;
  var tmpcnt:byte;
        tmpout:string;
begin
   tmpcnt:=0;tmpout:='';

    while (pos(seperator,instr)>0) and (tmpcnt<nr) do
     begin
      inc(tmpcnt);
      if tmpcnt=nr then tmpout:=copy(instr,1,pos(seperator,instr)-1);
      delete(instr,1,pos(seperator,instr));
    end;
    if (length (instr)>0) and (tmpcnt+1=nr) then tmpout:=instr;
    ValuestrNr:=tmpout;
end;

Dies ist nur eine function, um einen separierten Teilstring aus einer Zeichenkette zu extrahieren. Eine komplette Sammlung von Stringbehandlungsroutinen sind z.B. in den beliebten RX-Tools (erhältlich auf der Torry's Delphi Page) enthalten. Schaut euch dort die Unit StrUtils an!