Delphi Programming Tips

Welcome to my "Delphi Doodles" web page.
Here you will find some clever and useful tips to improve your Delphi Programming.
These were "lifted" from various sources. I take no credit for them.

Beginner's Tips



Make your computer beep.

messageBeep(0);

Display the mouse's hourglass (and then go back to an arrow).

try
   Screen.Cursor := crHourGlass;
   {do something here}
finally
   Screen.Cursor := crDefault;
end;
Application.ProcessMessages;

Scanning through a Data Table Table1.First; x := 0; while not(Table1.Eof) do begin {do what you have to do here} Table1.Next; end;

Setting focus on a specific field of a TDBGrid DBGrid1.SelectedField := Table1Field1; DBGrid1.SetFocus;

Navigator control use I have a form that uses several TDBGrids. It has only one navigator control. How do I write it so that I can use the navigator control so that it works with whatever grid is active? Use this line in the Enter event of each grid: TDBNavigator1.dataSource := (sender as TDBGrid).dataSource;

Dynamically update DBGrid row color Versions: Delphi 2, 3 The DBGrid is a great user interface tool for displaying data. This technique demonstrates how to dynamically change the color of text in a DBGrid. For example, we want our grid to display rows of country information. If a country's population is greater than 20 million, we'll display its row in blue colored text. We test the values and update the text color in the OnDrawColumnCell event of the grid. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin if Table1.FieldByName('Population').AsInteger > 20000000 then DBGrid1.Canvas.Font.Color := clBlue; DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; This is a simple but visually profound technique. In addition to just data content, you can display the meaning of the information; e.g. a lot of people, account overdrawn, parts have arrived.

Getting the network user name without using the BDE. A: This way uses the 32 bit API: function GetNetUserName: string; const NetUserNameLength: integer = 50; begin SetLength(result, NetUserNameLength); GetUserName(pChar(result), NetUserNameLength); SetLength(result, StrLen(pChar(result))); end; This way uses the registry: It reads the key groups under the network\persistent section into a TStringList. Then, we traverse the list until we find a UserName key and grab that value. If we don't find that name, we keep looking until we run out of entries in that list. If nothing is found, an empty string is returned. function GetNetUserName: string; var reg: TRegIniFile; RegKeys: TStringList; s: string; i: integer; begin reg := TRegIniFile.create('network\persistent'); try RegKeys := TStringList.create; try reg.ReadSections(RegKeys); i := 0; repeat // Make sure that there is a UserName key. s := reg.ReadString(RegKeys[i], 'UserName', ''); inc(i); until (s <> '') or (i = RegKeys.count); result := s; finally RegKeys.free; end; finally reg.free; end; end;


Putting the current time on the title bar of my form
Note: The placement of the time varies according to whether it is Win95 or below, as well as the form's size. If the form is too narrow, this may write the time over the top of the control buttons (maximize, minimize, etc). unit Unit1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TForm1 = class(TForm) Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var Form1: TForm1; dc: hDC; implementation {$R *.DFM} procedure TForm1.Timer1Timer(Sender: TObject); var TheTime: array[0..80] of char; begin StrPCopy(TheTime, TimeToStr(time)); TextOut(dc, width DIV 2, 5, TheTime, StrLen(TheTime)); end; procedure TForm1.FormCreate(Sender: TObject); begin dc := GetWindowDC(handle); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin ReleaseDC(handle, dc); {This *must* be manually released.} end; end.

Conserving resources with a TTabbedNotebook?
A: The TTabbedNotebook is created with only the page showing actually in memory. As tabs are selected, the pages to be shown are instantiated into memory. The trick is to release the last page from memory so that only one page at a time exists. There are two examples of doing this below. This version recycles controls by changing the parent property as the pages are turned: procedure TForm1.TabbedNotebook1Change(Sender: TObject; NewTab: Integer; var AllowChange: Boolean); var CurrentPage, NewPage: TWinControl; begin if sender is TTabbedNotebook then with TTabbedNotebook(sender) do begin CurrentPage := TWinControl(pages.objects[PageIndex]); LockWindowUpdate(handle); NewPage := TWinControl(pages.objects[NewTab]); while PresentPage.ControlCount > 0 do PresentPage.Controls[0].Parent := NewPage; LockWindowUpdate(0); end; end; This version is a bit more elegant and releases he window handle of the control while keeping all the other properties intact. (i.e. You don't have to worry about losing the information contained in that window just because the window went away.) procedure TForm1.TabbedNotebook1Change(Sender: TObject; NewTab: Integer; var AllowChange: Boolean); var CurrentPage: TWinControl; begin if sender is TTabbedNotebook then with TTabbedNotebook(sender) do begin CurrentPage := TWinControl(pages.objects[PageIndex]); LockWindowUpdate(handle); TWinControl(pages.objects[NewTab]).HandleNeeded; LockWindowUpdate(0); end; end;

File Copy Routine

File Copy Routine that keeps Attributes and File Date/Time the same function FileCopy(source,dest: String): Boolean; var fSrc,fDst,len: Integer; size: Longint; buffer: packed array [0..2047] of Byte; begin Result := False; { Assume that it WONT work } if source <> dest then begin fSrc := FileOpen(source,fmOpenRead); if fSrc >= 0 then begin size := FileSeek(fSrc,0,2); FileSeek(fSrc,0,0); fDst := FileCreate(dest); if fDst >= 0 then begin while size > 0 do begin len := FileRead(fSrc,buffer,sizeof(buffer)); FileWrite(fDst,buffer,len); size := size - len; end; FileSetDate(fDst,FileGetDate(fSrc)); FileClose(fDst); FileSetAttr(dest,FileGetAttr(source)); Result := True; end; FileClose(fSrc); end; end; end;

Scrolling your form with pgUP and pgDn. How can you do scrolling functions in a TForm component using keyboard commands? For example, scrolling up and down when a PgUp or PgDown is pressed. Is there some simple way to do this or does it have to be programmed by capturing the keystrokes and manually responding to them? Form scrolling is accomplished by modifying the VertScrollbar or HorzScrollbar Postion properties of the form. The following code demonstrates how to do this: procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); const PageDelta = 10; begin With VertScrollbar do if Key = VK_NEXT then Position := Position + PageDelta else if Key = VK_PRIOR then Position := Position - PageDelta; end;

TMediaPlayer - What CD Track am I on? Here's an easy way to do it: create a timer and put this code in the OnTimer event: var Trk, Min, Sec: Word; begin with MediaPlayer1 do begin Trk:= MCI_TMSF_TRACK(Position); Min:=MCI_TMSF_MINUTE(Position); Sec:=MCI_TMSF_SECOND(Position); Label1.Caption:=Format('%.2d',[Trk]); Label2.Caption:=Format('%.2d:%.2d',[Min,Sec]); end; end; Add MMSystem to the uses clause in Unit1 This will show current track and time.

Printing Directly to a Printer by Robert Vivrette - [email protected] Several readers have in the past inquired about how to print directly to a printer without going through the Windows printing engine. The key use for such a technique is when the user wants to send raw data (from a text file for example) directly to the printer without having to mess with fonts or formatting. Also, sometimes you may have directed some print output to a file rather than the printer. This technique allows you to send such a file directly to the printer. The technique is really quite simple. All you need to do is use AssignFile to open a file with the filename specified as 'LPT1' (or any other printer port). The operating system recognizes this as a special file type and directs all the output to that printer port. The Write & Writeln procedures are used to actually send the data. If you need to eject the page when you are done, just send a ASCII code of #12. Most printers recognize this as a formfeed code. var F : TextFile; begin AssignFile(F,'LPT1'); Rewrite(F); Writeln(F,'Hello'); Writeln(F,'There!'); Writeln(F,#12); CloseFile(F); end;

Printing Bitmaps
procedure PrintBitmap(Bitmap: TBitmap; X, Y: Integer); var Info: PBitmapInfo; InfoSize: Integer; Image: Pointer; ImageSize: Longint; begin with Bitmap do begin GetDIBSizes(Handle, InfoSize, ImageSize); Info := MemAlloc(InfoSize); try Image := MemAlloc(ImageSize); try GetDIB(Handle, Palette, Info^, Image^); with Info^.bmiHeader do StretchDIBits(Printer.Canvas.Handle, X, Y, Width, Height, 0, 0, biWidth, biHeight, Image, Info^, DIB_RGB_COLORS, SRCCOPY); finally FreeMem(Image, ImageSize); end; finally FreeMem(Info, InfoSize); end; end; end;

Copying a Table Record
Useful for copying a single record from one table to another provided the tables have the same structure. Procedure CopyRecord(const SourceTable, DestTable : TTable); var I : Word; begin DestTable.Append; For I := 0 to SourceTable.FieldCount - 1 do DestTable.Fields[I].Assign(SourceTable.Fields[I]); DestTable.Post; end;


(c) 1997 Flint A. Dwiggins