Pascal Newsletter #52
The full source code examples of this issue are available for download.
![]() |
![]() |
Pascal Newsletter #52 - 21-DECEMBER-2004 Contents 1. A Few Words From the Editors 2. How to Add a Program to the Explorer Send To Menu 3. Introductory Principles of Indexed Searching 4. Extracting Records in a Field into a TStringList 5. Returning Classes from a DLL 6. Simplified Collision Detection in Game Programming 7. Forums / Mailing Lists 8. Delphi on the Net - Components, Libraries and Utilities - Shareware / Commercial - Freeware - Borland Product Updates - Articles, Tips and Tricks - Tutorials and Training - News - Other / Misc Sites ________________________________________________________________________ 1. A Few Words From the Editors Welcome to the last issue of the Pascal Newsletter for 2004. We'd like to thank all the authors who contributed articles or prizes this year. We've got five articles in this issue to give you plenty of reading over the holiday period and we'd like to thank the authors who contributed them: Peter Johnson, Jim McKeeth, Stewart Moss, Max Kleiner, John Pears. We're pleased to award Stewart Moss, Max Kleiner and John Pears the prizes for this issue: * Stewart Moss - 'Extracting Records in a Field into a TStringList' InstallAWARE 3.0 Express Edition - by MimarSinan Int. ($69.95) InstallAWARE 3.0 for Windows Installer - by MimarSinan International Develop setups for Windows Installer without any knowledge of MSI! InstallAWARE automatically converts a conditionally flowing script into a logo certifiable, ICE-compliant MSI database at build time. The IDE features a visual UI which generates your setup script for you automatically and you can fully customize the script behavior. Special limited offer: 30% off all editions, Enterprise only $559.95! http://www.installaware.com/landingea.html * John Pears - 'Simplified Collision Detection in Game Programming' KnowedgeBASE Vortex 2.9 by Delphinium Software ($49.35) KnowledgeBASE Vortex features a highly searchable and expandable information tree viewed in outline or audited within a built-in wordprocessor. Includes a database for stored references. http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html * Max Kleiner - 'Returning Classes from a DLL' KylixDriver v1.1 - by ET Kimberliteware Ltd ($39 / $69 with source) KylixDriver is a RAD Kylix-oriented and integrated toolkit for PC hardware access. This toolkit can be efficiently used for writing Linux device drivers for ISA and PCI hardware. http://www.geocities.com/etkimberliteware/kylixdriver/index.html Special thanks to Delphinium Software for donating KnowledgeBASE Vortex as an ongoing prize for future issues. In the next issue we have three prizes up for grabs: InstallAWARE 3.0 Enterprise Edition, KnowedgeBASE Vortex and YAPI Professional. * YAPI Professional - by Owen Mooney ($95) Offers the easiest and yet powerful printing from Delphi. It provides: WYSIWYG setup, print preview, Non database, Database, text, Grids, tabs, bitmaps, TCanvas operation, precise positioning or free flow positioning - all using simple "writeln" statements. http://free.hostdepartment.com/o/owenmooney/ We're also proud to offer readers a special discount on InstallAWARE 3, thanks to the nice people at at MimarSinan International. InstallAWARE 3 was developed completely in Delphi and helps you author MSI setups with zero knowledge of Windows Installer. Rather than just providing a visual UI (like Wise or InstallShield), InstallAWARE has its own RAD scripting language which is automatically converted to a logo-certifiable MSI database at build time. Unique features include: Partial Web Deploy; Genuine Scripting for Windows Installer; Powerful Dialog Editor with Unique Controls (such as Flash and HTML containers); Advanced 7ZIP Compression (.NET runtime is 11MB instead of 23MB!). For a limited time, readers can get 30% off any edition of InstallAWARE 3 by following the links in this issue. Next year we're planning to publish seven issues of the newsletter - in January, March, May, July, September, November and Christmas / New Year. Now, on with the code... Regards, Dave Murray and Ernesto De Spirito pascal-newsletter-owner@yahoogroups.com ________________________________________________________________________ Help & Manual 3.50 by EC Software - Shareware ($ 299) - Help & Manual is a WYSIWYG help authoring tool that will aid you in creating standard WinHelp files (.HLP), Adobe PDF files, HTML pages and the new HTML HELP (.CHM) files introduced in Windows 98, as well as other file formats and printed documentation, everything from a single source. This is a must- have for any software developer. http://www.helpandmanual.com/hmpage.htm ________________________________________________________________________ 2. How to Add a Program to the Explorer Send To Menu By Peter Johnson, Copyright (c) 2003 <delphidabbler at tiscali dot co dot uk> http://www.delphidabbler.com/ Why Do It --------- If you are writing a general purpose file-related program it can be useful to add it to the Windows Explorer "Send To" menu. For example I place Windows Notepad on the "Send To" menu so I can easily view any file in the text editor. How It's Done ------------- There are two stages achieving our goal: 1. Ensuring our program can receive files sent from the "Send To" menu. 2. Creating an entry for our program in the "Send To" menu. Although you can create a special handler for the "Send To" menu, we will take the simple approach of simply storing a shortcut to our program in the menu. Receiving Files From the "Send To" Menu --------------------------------------- This is very simple. If the user selects one or more files, right clicks and selects Send To | Our program, Windows will simply start our program and pass the names of the selected files on the command line. So, to read the files sent from the "Send To" menu, we simply need to check our command line parameters. We can do this in our application's FormCreate event handler as follows: procedure TForm1.FormCreate(Sender: TObject); var I: Integer; begin for I := 1 to ParamCount do ProcessFile(ParamStr(I)); end; Where ProcessFile processes a given file in an application defined way. (In the demo program that accompanies this article we simply display the file names in a memo control). That's all there is to handling the files. Now let's look at how we create the "Send To" menu entry. Creating the "Send To" Menu Item -------------------------------- Windows stores the contents of a user's "Send To" menu in a special folder. We will need to create a shortcut to our program in that folder. We must first find the path to the "Send To" folder. Each user has their own copy of this folder. We find its location by using the SHGetSpecialFolderLocation and SHGetPathFromIDList API calls (defined in the ShlObj unit) as follows: function GetSendToFolder: string; var pidl: PItemIDList; PPath: array[0..MAX_PATH] of AnsiChar; begin Result := ''; if SHGetSpecialFolderLocation(0, CSIDL_SENDTO, pidl) = NOERROR then begin try if SHGetPathFromIDList(pidl, PPath) then Result := PPath; finally CoTaskMemFree(pidl); end; end; end; We first use SHGetSpecialFolderLocation to get a PIDL representing the required folder. We pass CSIDL_SENDTO to the function to get the PIDL for the current user's "Send To" folder. If we succeed in getting the PIDL we then get the path to the folder by passing the PIDL to SHGetPathFromIDList which stores the required path in a PChar buffer we supply. We convert the PChar to a string and return this from the function. Windows allocated memory for the PIDL using its task allocator. It is our responsibility to free the PIDL, using the CoTaskMemFree function (defined in the ActiveX unit). Having found the path to the user's "Send To" folder we can now create a shortcut to our application in the folder. We may choose to do this in a set up program or by making this an option in our application. Whatever our choice, the next section shows how to create a shell link. Creating a Shell Link --------------------- The following function can create any shell link -- not only those for use in the shell link folder. function CreateShellLink(const LinkFileName, AssocFileName, Desc, WorkDir, Args, IconFileName: string; const IconIdx: Integer): Boolean; var SL: IShellLink; // shell link object PF: IPersistFile; // persistant file interface to shell link object begin // Assume failure Result := False; // Ensure COM is initialised CoInitialize(nil); try // Create shell link object if Succeeded( CoCreateInstance( CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL ) ) then begin // Store required properties of shell link SL.SetPath(PChar(AssocFileName)); SL.SetDescription(PChar(Desc)); SL.SetWorkingDirectory(PChar(WorkDir)); SL.SetArguments(PChar(Args)); if (IconFileName <> '') and (IconIdx >= 0) then SL.SetIconLocation(PChar(IconFileName), IconIdx); // Create persistant file interface to shell link to save link file PF := SL as IPersistFile; Result := Succeeded( PF.Save(PWideChar(WideString(LinkFileName)), True) ); end; finally // Finalize COM CoUninitialize; end; end; The function has numerous parameters. They are: const , , , , : string; const : Integer 1. LinkFileName: the full path to the shortcut file -- in our example we use the name of the "Send To" folder that was returned by GetSendToFolder, followed by the name of the shortcut file. Note that the "Send To" menu displays the name of this file, stripped of it's extension, so give the file a descriptive name. 2. AssocFileName: the name and of the file referenced by the shortcut -- here we provide the full path to the program to be started from the "Send To" menu. ParamStr(0) stores this file name. 3. Desc: a description of the shortcut -- this is not displayed in the "Send To" menu so we pass ''. 4. WorkDir: the program's working directory -- can supply '' if not required. 5. Args: any command line that is to be passed to the program -- we do not use this parameter in this example. Remember that the "Send To" menu also passes file names on the command line. 6. IconFileName: specifies the file containing the shortcut's icon -- in our example don't specify this file and so the icon is assumed to be in the program file. 7. IconIdx: the index of the icon in IconFileName or -1 to cause the program's default icon to be used -- we specify -1. From the above we can see we need to call CreateShellLink and follows: ... CreateShellLink( GetSendToFolder + '\' + 'My SendTo Item.lnk', ParamStr(0), 'My SendTo Sample Program', ExtractFileDir(ParamStr(0)), '', '', -1 ); ... Summary ------- We have now covered the basics of adding an item to the "Send To" menu and in handling files "sent" to our program from the menu. The code presented can be used as a basis for implementing "Send To" menu support in your programs. A demo application is also included with this issue's source code zip. It has been tested with Delphi 4 and Delphi 7. __________________ Peter Johnson is a hobbyist programmer living in West Wales (UK) who maintains the DelphiDabbler website (http://www.delphidabbler.com/) where his articles and freeware Delphi applications & components are published. The code for this article is also available at: http://www.delphidabbler.com/download.php?file=article-12-demo.zip ________________________________________________________________________ Vote for the Pascal Newsletter in The Borland Top 100! http://top100borland.com/in.php?who=20 ________________________________________________________________________ 3. Introductory Principles of Indexed Searching By Jim McKeeth <jim at mckeeth dot org> Introduction ------------ There are really two main ways to search a large collection of text documents. The simplest method would be to load each document and scan through it for the search terms, this would be referred to as a full text scan. The second, much faster method is to create an index and then search the index. An index is a list of terms found in a document or set of documents. Each word only appears once per document so it is much shorter then the original document. Creating An Index ----------------- Finding The Words ----------------- In order to create an index you must first parse the document. Parsing, is the process of picking out the individual tokens (terms or words) in a piece of text. A parser is a type of state machine. There are many existing parsing routines available. "The Tomes of Delphi Algorithms and Data Structures" by Julian Bucknall contains many very good parsers. An example: http://www.delphi3000.com/articles/article_1265.asp A simple parser would scan through a string of text, starting at the beginning, looking at each character. If it is a letter or number then it is part of a word, if it is white space or punctuation then it is a separator. Each word is added to a list (i.e. TStringList) in the order it is found in the document. Typically each word is converted to the same case (upper or lower). It is really important to consider what you are indexing and how your index will be used when creating your index and parsing. For example if you are parsing HTML then you want to exclude most tags (with the obvious exception of META tags, which are handled specially). Other times you might only want to index summery information about each document. Indexing The Words ------------------ Now that we have a parsed token list we need to index it. The simplest index is just a list of each word found in a document, and a reference to the document. This reference may be a URL, a document name or any other unique identifier (a GUID or a foreign key to another table describing the document). A more complex index may include the number of times the word is found in the document or a ranking for where it is in the document (in the title, keyword section, first paragraph, middle, last, etc.) This additional information stored with each word is part of what differentiates one search engine's performance from another. Many times certain words are left out. These are called stop words. Stop words are common words, words that will not be searched on, or words that will not enhance the meaning of a search. An example of stop words includes "THE, A, AN, AND, IF, BUT", words with numbers in them, or anything else you want to filter out. Selecting stop words is another point of separation of performance. Some web search engines used to leave out words like "HTML" or "WEB" because they were so common while other search engines would include every word. Other search engines start with a dictionary list and only index words found in that dictionary list. This leads to trouble when you are indexing names, technical terms or anything else not found in your original dictionary. One time I was creating a search engine for a collection newsgroup articles. I discovered that there was UUEncoded (similar to MIME or Base64) binaries in the articles. This resulted in my parser finding words that were hundreds of characters long and total gibberish. I decided to omit any word longer then 50 characters or shorter then 4. Making the choices about what to include and what to omit is an important decision, and will vary based on what content you are indexing. So here is an example table structure for your index: Table: WordList --------------- Document: Number (foreign key to Documents table) Word : String[20] (if our longest word is 20 characters) Count : Number (how many times the word is found) The primary key would be a compound of Document and Word since each word is listed once per document. Table: Documents ---------------- Document : Number(primary key index) Title : string (title of document) Location : string (URL or full filename and path) Optionally you could include the entire document as a blob in this table. You could also have other tables that lists terms (from the meta section of the document) or include authors. Again this design choice depends on the type of documents you are indexing and the purpose of your search engine. Searching Your Index -------------------- Once all the indexes are stored in a database you need to be able to search the index for a document. A simple SQL statement to search for a document that contains a single word could look like this: SELECT * FROM WordList WHERE Word = :v_search_term ORDER BY Count DESC This returns all documents containing your single search term and they are ordered by the number of times the word is found. If you want to use SQL then to search on multiple terms involves an join for each term. Instead you could retrieve a list for each term and then merge them manually. This is where you would support AND, OR or NOT key words. If you want to allow phrase searching then you could search for each word in the phrase and then search those documents for the phrase. The same technique could be used for the NEAR key word. There are other more advanced techniques to do this that are much quicker, but they are beyond the scope of this document. Once the hits are found and ranked then display the title of each document, possibly a summary or the context of the hits, and provide a way for your user to reach the document. Variations ---------- One thing Google does a little differently is they look at how pages are linked. This works really well with the hyper linked nature of the web. For example if you search for Borland most pages that mention Borland link to www.borland.com. This is assumed to indicate that www.borland.com is a very important site about Borland. Google also limits the number of hits you get on each domain. Many search engines also rank pages higher if the search term appears in the URL or title of the page. They also look at the description and keywords meta tags for ranking. Some search engines will actually ignore a word if it appears too often in a page. This weeds out sites that try to artificially inflate their rankings. Phonetics or Soundex is another technique that can be used. This could be done with an additional table similar to the word table, but instead store the soundex value for the words instead of the actual word. Third Party Search Tools ------------------------ dtSearch http://www.dtsearch.com/ -------- dtSearch provides a full range of text search products. These products target everyone: from the end user to the media publisher and finally the developer. Their dtSearch Text Retrieval Engine is the core of all their products and they provide an API with Delphi examples. This product is just about creating a full text index of documents and searching it. They use their own data format. Using their API you can create a Delphi application to index just about any document (PDF, Office, ZIP, etc. and Text too!) and then search that index to find the matching documents. They recently added support for Linux and .NET but I haven't tested these with Linux or Delphi for .NET yet. Depending on what type of project you are working on, one of their other product lines might be a good match. Their dtSearch Publish, for example, lets you create a CD / DVD of searchable content quickly and easily. While their dtSearch Web is idea for building a web search engine. Rubicon http://www.fulltextsearch.com/ ------- Tamarack Associates' provides their flagship product Rubicon to Delphi and C++Builder developers who want indexed searching without building a system from scratch. Beyond the basics we cover here, they also offer many advanced features and speed improvements. If you visit their web site you can download a demo version of their search tools or test their newsgroup search in Borland and Microsoft's newsgroups. Not only does Rubicon allow searching of documents (It comes with a parser to handle text, HTML, and RTF), but it will also allow you to search your database for data. It supports logical expression (and, or, not, near and like), as well as support for full phrases. It is all pure Delphi source, and really offers the developer a very high level of control over the process. Rubicon's FastPhrase technology builds a much larger table that allows it to perform phrase searches without performing a full text scan of the target document. This is done by not only storing each word, but also storing a concatenation of each word and it's two adjacent words, for a total of up to there entries per word. Rubicon boasts very comprehensive database compatibility. Supported databases include the BDE and dbExpress as well as ADO, Advantage, Apollo, Direct Oracle Access, DBISAM, FlashFiler, Halcyon, Interbase Express, Interbase Objects, ODBC Express and Topaz. Other databases are supported through building your own packages. When installing Rubicon (either demo or full version) be sure to follow the directions to install it correctly and so it will support your selected database. Summary ------- Based on my comparisons between dtSearch and Rubicon, they both perform about the same in the search speed department. dtSearch's advantage is in their additional product lines and simpler interface, but you suffer from less configurability. Rubicon gives you access to every detail of your search project by providing you with the complete Delphi source and your choice of databases instead of dtSearch's closed database and DLL. Database Search Features ------------------------ Many databases provide features to allow you to index and search documents stored within the database. Oracle offers an additional add-in to index documents. MySQL by default allows you to search stored text documents just like you would any other field. DBISAM (a native Delphi BDE replacement with no deployment) now has text indexing and searching as well. Conclusion ---------- Searching a shorter and well organized index is much quicker then searching an entire document. Creating and searching an index takes a lot more planning and effort up front, but quickly pays off if the text is searched very often. Typically the larger and more complex the index, the more effective the search. If your index gets too large or complex then the search speed will degrade. There are off the shelf searching tools available to end users and developers alike. dtSearch and Rubicon are both extremely fast and useful, but don't let that stop you from designing your own, especially if you have a specialized need. See also: http://www.dtsearch.com/dtsoftware.html#Art_of_The_Text_Query ________________________________________________________________________ InstallAWARE 3.0 for Windows Installer by MimarSinan International Special time limited offer: 30% off Enterprise Edition, only $559.95! InstallAWARE is a next generation setup authoring tool with unique features such as partial web deployment, Flash and HTML progress billboards, ten striking setup themes, fully customizable installation dialogs, and a setup script that automatically gets converted to a Windows Installer file. >> http://www.installaware.com/landingea.html << ________________________________________________________________________ 4. Extracting Records in a Field into a TStringList By Stewart Moss <stewart at new-heights.co.za> http://www.new-heights.co.za/ Introduction ------------ Often the programmer needs a quick and dirty method to extract a set of records from a specific field in a dataset in a convenient way. Examples of this in my own programming are when I needed to populate a TListBox or TComboBox (on a modal form) with values that the user can select for reporting or other purposes. This simple class is a safe and convenient way to do this. The current record in the dataset is restored, and the dataset's active state (ie open or closed). A demo application is also included with this issue's source code zip. Implementation -------------- The code simply gets a TField object from a specified field name (property called "FieldName") belonging to the dataset (property called "Dataset") and iterates through the records returning each value in the field, from start to finish. The TField class is handy because it allows us to handle any field type based on any dataset :) Only datatypes which support the .AsString method (ie not blobs) are returned. A boolean property of the class (called "emptyNulls") will allow you to return blank rows if found. This is useful if you need to return the "offset" in the dataset of the required record (ie matching DataSet.RecNo) or if blank rows are meaningful. The output is in a read only property called Strings of type TStringList. This property can be used to directly populate a TListBox or even Strings.SaveToFile(). The output is based on system formatting variables (for dates etc) so beware! The Refresh method is fired then the Strings property is read and the list needs to be refreshed. This happens when you change the dataset or the fieldname for the first time, you can also call this manually. The output can be padded with leading and trailing and leading strings. This is useful if you need to pad the text for formatting. However this padding needs to be removed from the return of the TListBox or TComboBox (for use in lookup queries etc). Honestly I don't use this this padding feature in my own code. The class has a method called "quickSearch", this allows you to perform a lookup based on any return value. This is just a wrapper of the TDataset.Locate() on the current dataset. For example you could present all CustomerNames in a drop down list, and quickSearch() will allow you to locate the CustomerID of the selected CustomerName. The lookup is returned as a String. Example of Usage ---------------- This populates the TListBox called SrcList on TfrmSelectData with the names of the active stock as returned from the TQuery named qryPortfolio. Then performs a lookup to determine the StockID of the stock name. procedure TFormMain.thingy; var StockID, StockName : string; DatasetExtract : TDatasetExtract; begin DatasetExtract := TDatasetExtract.Create; try // any field DatasetExtract.FieldName := 'StockName'; // any dataset DatasetExtract.DataSet := qryPortFolio; // create the form with TfrmSelectData.Create(Self) do begin // add a copy of the DatabaseExtract TStringlist to the TListBox // Getting the strings could generate an exception. SrcList.Items.AddStrings(DatasetExtract.Strings); // show the form ShowModal; // if he pressed ok if ModalResult = mrOK then begin // Return the stock name from the selected index in the list StockName := SrcList.Items[SrcList.selectedindex]; // Lookup the StockID from qryPortfolio query using the class StockID := DatasetExtract.Search('StockName', StockName, 'StockID',[]); showmessage('The StockID of '+StockName+' is '+StockID); end; free; end; // with finally DatasetExtract.free; end; end; Class Code ---------- {----------------------------------------------------------------------- Unit Name: unitDatasetExtract2 Modification Date: 18 December 2004 Creation Date: 04 June 02 00:39:21 Documentation Date: 04 June 02 00:39:21 Release Date: 15 Jan 2003 Version: 2.0 Author: Stewart Moss Compiler version: Delphi 5 and Delphi 6 tested Purpose: To Extract a specific field from a dataset in a TStringList. Useful for populating TListBoxes that you dont want to be data aware... (Released originally on Delphi3000.com) Description: At the moment it only support TStringLists. It will convert most TField.FieldType into a string Notes: Dependancies: History: 15 Jan 2003: Posted at wwww.delphi3000.com. Article number 3512. 1122 visits by Dec 2004 Copyright 2002, 2003, 2004 by Stewart Moss All rights reserved. You must not modify this Unit Header. -----------------------------------------------------------------------} unit unitDatasetExtract2; interface uses Classes, db{$IFDEF VER140}, Variants{$ENDIF}; type TDatasetExtract = class private fEmptyNulls: boolean; recPos: integer; fFieldname, fappend, fprepend: string; fDataset: TDataset; fStrings: TStringList; refreshed: boolean; function FieldToString(Field: TField): string; function Get_Strings: TStringList; procedure Set_Dataset(const Value: TDataset); procedure Set_Fieldname(const Value: string); public constructor create; destructor destroy; override; procedure Refresh; function Search(searchField, searchValue, ReturnField: string; Locateoptions: TLocateOptions): string; published // You have the option of appending and prepending any information // to the begining of each record. // Useful for creating delimited records easily (ie you can just add // the StringList items together) (maybe not really that useful :P ) property append: string read fappend write fappend; property prepend: string read fprepend write fprepend; // Whether or not nulls must be translated into blank values, // or ignored property EmptyNulls: boolean read fEmptyNulls write fEmptyNulls default true; // The field name to return in the string list property FieldName: string read fFieldname write Set_Fieldname; // The dataset of the field property Dataset: TDataset read fDataset write Set_Dataset; // This is the TStringList output of the class. Reading this string // triggers the action of the class. property Strings: TStringList read Get_Strings; end; implementation uses Sysutils; // allow exception objects { TDatasetExtract } constructor TDatasetExtract.create; begin fDataset := nil; fStrings := TStringList.create; EmptyNulls := true; // allow null rows by default refreshed := false; // we do not have data end; destructor TDatasetExtract.destroy; begin fStrings.free; inherited; end; procedure TDatasetExtract.Refresh; {----------------------------------------------------------------------- Procedure: TDatasetExtract.Refresh Starts at the beginning of the record set and appends the required field in each consecutive record to the string list using the TField. ----------------------------------------------------------------------} var Field : TField; isactive : boolean; begin with fDataset do begin try // turn off any data-aware components related to current dataset disablecontrols; // save Dataset open state isactive := fDataset.Active; if not isactive then fDataset.open; // Save our current place in the dataset recPos := RecNo; // go to the start First; while not eof do begin // Get the TField object for field FieldName at // the current position (we don't care what type) Field := FieldByName(fFieldname); // Ok is it null? if not varisnull(Field.asvariant) then // use our "safer" .AsString fStrings.add(fprepend + FieldToString(Field) + fappend) else if EmptyNulls then // we are allowed to insert nulls fStrings.add(fprepend + fappend); next; end; // while not eof finally // Restore our current place in the dataset RecNo := recPos; // if the dataset was closed then close it if not isactive then fDataset.close; // turn on the data-aware components related to current dataset enablecontrols; end; // finally end; // with fDataset end; function TDatasetExtract.FieldToString(Field: TField): string; {----------------------------------------------------------------------- Procedure: TDatasetExtract.FieldToString Arguments: Field: TField Result: string This actually reads the field from the database and swallows any EDatabaseErrors. ----------------------------------------------------------------------} begin try result := Field.AsString; except on e: EDatabaseError do begin // nothing end else // re-raise the exception if it is something else raise; end; end; function TDatasetExtract.Get_Strings: TStringList; begin result := fStrings; // always return what you have (even if exception) if refreshed then // if we have clean data exit; // then we are done fStrings.clear; if (fDataset = nil) or (fFieldname = '') then // uber cool error message raise exception.create(self.ClassName + ': Two manditory fields not supplied'); Refresh; end; function TDatasetExtract.Search(searchField, searchValue, ReturnField: string; Locateoptions: TLocateOptions): string; {----------------------------------------------------------------------- Procedure: TDatasetExtract.quickSearch Arguments: searchField, searchValue, ReturnField : string; Locateoptions: TLocateOptions Result: string Searches for a field value in a specified field name and returns the specified field returns '' is nothing is found. eg Ask for a customer id of 10 and return the customer name ----------------------------------------------------------------------} var isactive : boolean; begin with fDataset do begin // turn off any data-aware components related to the current dataset disablecontrols; // save Dataset open state isactive := fDataset.Active; if not isactive then fDataset.open; try result := ''; First; if not locate(searchField, searchValue, Locateoptions) then exit; // use our "safer" .AsString method result := FieldToString(FieldByName(ReturnField)); finally // our current place obeys TDataset.Locate() // if the dataset was closed then close it if not isactive then fDataset.close; // turn on any data-aware components related to the current dataset enablecontrols; end; end; end; procedure TDatasetExtract.Set_Dataset(const Value: TDataset); begin fDataset := Value; refreshed := false; // we are dirty again end; procedure TDatasetExtract.Set_Fieldname(const Value: string); begin fFieldname := Value; refreshed := false; // we are dirty again end; end. ________________________________________________________________________ Vote for the Pascal Newsletter in The Delphi Top 200! http://top200.jazarsoft.com/delphi/rank.php3?id=latium ________________________________________________________________________ 5. Returning Classes from a DLL By Max Kleiner <max@kleiner.com> Kleiner Kommunikation Reference: http://max.kleiner.com/ Component Download: http://max.kleiner.com/download/dllplus.zip Question/Problem/Abstract: -------------------------- Export an object-reference from a DLL is one approach to get real OO-access to a DLL. The DLL must create and return the object, so the client gets the methods without encapsulating. Let's see how this framework, called DLL+, works... Answer: ------- There is also an example uploaded with UML-Diagrams (*.tif) from ModelMaker. We always work with MM since we had to redesign a big project. First, we have to built an abstract class in a separate unit (see below the same with a real interface). You might consider this unit like an interface: unit income1; interface type IIncome = class public function GetIncome(const aNetto: Currency): Currency; virtual; abstract; procedure SetRate(const aPercent, aYear: integer); virtual; abstract; function queryDLLInterface(var queryList: TStringList): TStringList; virtual; abstract; end; Second we built the DLL in a new unit (*.dpr) with the corresponding class, which has to implement the methods from the interface: type TIncomeReal = class(IIncome) private FRate: Real; public constructor Create; function GetIncome(const aNetto: Currency): Currency; override; procedure SetRate(const aPercent, aYear: integer); override; ... And now comes the export, cause objects in DLL+ are created by calling a global Constructor function, you can see that returning objects from the function that creates them is acceptable by the client: {-------------------------------------------------------------} function CreateIncome: TIncomeReal; stdcall; begin result:= TIncomeReal.Create; end; exports CreateIncome resident; begin {fake} end. {-------------------------------------------------------------} At last we take a look at the client. In managing objects the client consider who owns the object and is responsible for freeing it up: Uses income1; private IncomeRef: IIncome; //member ... function CreateIncome:IIncome; stdcall; external('income.dll'); ... procedure TfrmIncome.FormCreate(Sender: TObject); begin IncomeRef:=createIncome; end; So the access is easy, stable and improves maintenance of the DLL. It should be mandatory to implement a function called queryDLLInterface, in order to reproduce the interface and all the parameters in case of lost (see example). procedure TfrmIncome.BitBtnOKClick(Sender: TObject); begin incomeRef.SetRate(strToInt(edtZins.text), strToInt(edtJahre.text)); cIncome:= incomeRef.GetIncome(StrToFloat(edtBetrag.Text)); edtBetrag.text:= Format('%m',[cIncome]); end; Calling an Interface -------------------- Now the client calls an InterfaceReference: private incomeIntRef: IIncomeInt; procedure TfrmIncome.BitBtnOKClick(Sender: TObject); begin incomeIntRef:=createIncome; try with incomeIntRef do begin if QueryInterface(IIncomeInt, incomeIntRef) = S_OK then begin SetRate(strToInt(edtZins.text), strToInt(edtJahre.text)); cIncome:=strTofloat(edtBetrag.text); The Unit Income1 is enlarged with the interface: IIncomeInt = interface (IUnknown) ['{DBB42A04-E60F-41EC-870A-314D68B6913C}'] function GetIncome(const aNetto: Currency): Currency; stdcall; function GetRate: Real; function queryDLLInterface(var queryList: TStringList): TStringList; stdcall; procedure SetRate(const aPercent, aYear: integer); stdcall; property Rate: Real read GetRate; end; The DLL now exports a real Interface-Pointer: TIncomeRealIntf = class (TInterfacedObject, IIncomeInt) private FRate: Real; function Power(X: Real; Y: Integer): Real; protected function GetRate: Real; public constructor Create; destructor destroy; override; function GetIncome(const aNetto: Currency): Currency; stdcall; function queryDLLInterface(var queryList: TStringList): TStringList; stdcall; procedure SetRate(const aPercent, aYear: integer); stdcall; property Rate: Real read GetRate; end; function CreateIncome: IIncomeInt; stdcall; begin result:= TIncomeRealIntf.Create; end; When n-classes implements one interface push a parameter to the export routine in the DLL: function CreateIncome(intfID: byte): IIncomeInt; stdcall; begin case intfID of 1: result:= TIncomeRealIntf.Create; 2: result:= TIncomeRealSuper.Create; 3: result:= TIncomeRealSuper2.Create; end; end; exports CreateIncome; Client-calling looks like this: incomeIntRef := createIncome(3); ________________________________________________________________________ KnowedgeBASE Vortex 2.9 by Delphinium Software ($49.35 US) KnowledgeBASE Vortex features a highly searchable and expandable information tree viewed in outline or audited within a built-in wordprocessor. Includes a database for stored references. http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html ________________________________________________________________________ 6. Simplified Collision Detection in Game Programming By John Pears <j.pears@coventry.ac.uk> The, so called, 'simple collision detection algorithms' only detect collisions between two rectangles yet the most simple of them seem to be over complicated. Each sprite has x and y coordinates (usually the centre of the sprite) and a rectangle used for placing the image. Sometimes, a separate 'bounding rectangle' is used for collision detection. Each time the sprite's x,y is moved, the positions of the rectangle(s) have to recalculated. The collision detection then tests left, top, right and bottom of BOTH sprites rectangles to see if a collision occurred. All of this has to be done for each sprite on each step of the game. How about only moving the x,y (centre) of the sprite and "fixing" the offsets to the left and top? Consider the following data structure: type TSpriteRec = record Centre : tpoint; OffSet : tpoint; // never changes unless change of image.picture Image : TImage; end; var Invader : array[1..A_NUMBER] of tSpriteRec; Rocket : array[1..ANOTHER_NUMBER] of tSpriteRec; Placing the sprite becomes: Image.Left = ( Centre.x - OffSet.x ); Image.Top = ( Centre.y - OffSet.y ); No more code, its there, job done, the offsets never change. We can now write a simple function to detect collision: Function Collided(Spr1, Spr2 : TSpriteRec) : Boolean; begin result := (abs(Spr1.Centre.x-Spr2.Centre.x) < (Spr1.OffSet.x+Spr2.OffSet.x)) and (abs(Spr1.Centre.y-Spr2.Centre.y) < (Spr1.OffSet.y+Spr2.OffSet.y)); end; And, our main code becomes: if Collided (Rocket[10], Invader[77]) then begin // some code end; The demo application included in this issue's source code zip is a simple 'Space Invaders' type game. It was written with Delphi 6 and has no DirectX or DelphiX. It is just raw Delphi moving TImages around. The code is not identical to the above examples but the principle is. In the demo try changing the following constants in U_Sprites.pas: INVADER_COLS = 16; INVADER_ROWS = 6; ________________________________________________________________________ Vote for the Pascal Newsletter in The Delphi Resource Center! http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E ________________________________________________________________________ 7. Forums / Mailing Lists To join any of our forums, the best way is to subscribe from the web, since then you'll be able to access the website features (message archive, files section, etc). A Yahoo! ID is required for that, and you can get yours free by registering as a Yahoo! user, but you can also subscribe by email (you'll only have email access). * Delphi-En: A unique forum for intermediate-level Delphi programmers. A large group with a helpful community of members. If you are a beginner please stay as a listener and learn from others' questions and answers. Home Page: http://groups.yahoo.com/group/delphi-en/ Subscription: http://groups.yahoo.com/group/delphi-en/join delphi-en-subscribe@yahoogroups.com * Delphi-All: A Delphi group open to programmers of all levels. Home Page: http://groups.yahoo.com/group/delphi-all/ Subscription: http://groups.yahoo.com/group/delphi-all/join delphi-all-subscribe@yahoogroups.com * Kylix: Kylix programming. Home Page: http://groups.yahoo.com/group/KylixGroup/ Subscription: http://groups.yahoo.com/group/KylixGroup/join KylixGroup-subscribe@yahoogroups.com * Components: This is a forum for searching / recommending software components (VCL and CLX components, ActiveX objects, DLL libraries, .Net, etc.), as well as utilities, tutorials, information, etc. Home Page: http://groups.yahoo.com/group/components/ Subscription: http://groups.yahoo.com/group/components/join components-subscribe@yahoogroups.com * Software Developers: A place for subjects related to software development and the industry. For developers to share their experiences as an academic, professional or hobbyist. It is not a programming forum, messages here are supposed to be more general or language independent. Home Page: http://groups.yahoo.com/group/software-developers/ Subscription: http://groups.yahoo.com/group/software-developers/join software-developers-subscribe@yahoogroups.com ________________________________________________________________________ Delphi-PRAXiS · One of the fastest growing German Delphi-forums, with unique services like our "Delphi-PRAXiS Expert" (add-on which allows access to our libraries directly from within the IDE). Our database contains more than 50,000 articles. >>> http://www.delphipraxis.net <<< ________________________________________________________________________ 8. Delphi on the Net By Dave Murray <irongut at vodafone dot net> Components, Libraries and Utilities =================================== Shareware / Commercial ---------------------- * InstallAWARE 3.0 for Windows Installer - by MimarSinan International Develop setups for Windows Installer without any knowledge of MSI! InstallAWARE automatically converts a conditionally flowing script into a logo certifiable, ICE-compliant MSI database at build time. The IDE features a visual UI which generates your setup script for you automatically and you can fully customize the script behavior. Special limited offer: 30% off all editions, Enterprise only $559.95! http://www.installaware.com/landingea.html * KnowedgeBASE Vortex 2.9 by Delphinium Software ($49.35) KnowledgeBASE Vortex features a highly searchable and expandable information tree viewed in outline or audited within a built-in wordprocessor. Includes a database for stored references. http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html * YAPI Professional - by Owen Mooney ($95) Offers the easiest and yet powerful printing from Delphi. It provides: WYSIWYG setup, print preview, Non database, Database, text, Grids, tabs, bitmaps, TCanvas operation, precise positioning or free flow positioning - all using simple "writeln" statements. http://free.hostdepartment.com/o/owenmooney/ Freeware -------- * CSV Parser v1.0 - by Patrick Beekmans (with source) Parse any CSV-file with this component. You have the ability to choose the desired separator. This component has three events: OnNewColumnHeader, OnNewRow and OnNewValue. http://www.torry.net/vcl/vcltools/text/PBParsers.zip * GExperts v1.21 - by GExperts Inc. (with source) GExperts is a set of open source tools that increase productivity by adding features to the IDE. Includes: Editor Experts to find matching delimiters, insert unit headers, etc; IDE enhancements that add a Windows menu and show hidden menu items; Palette enhancements that add multi-line tabs or add tabs to the context menu; and much more. Now supports Delphi 5/6/7/8/2005 and C++Builder 6. http://www.gexperts.org/ * Indy v10.0.51 - by The Indy Pit Crew (with source) Open source suite of more than 120 protocols and Internet standards. Each protocol is robust with rich support, the need to add additional support to existing protocols is rare. Indy is easy to use because it uses blocking sockets; everything happens in a sequence, just like accessing a file. Now supports .Net. http://www.indyproject.org/Sockets.iwp * PGP Components for Delphi v4.0.1 - Michael in der Wiesche (w. source) Provides a Delphi (2-7) direct interface to PGP 6.5.x, 7.x or 8.x. New in Version 4.0.1: Checking and restarting of the PGPsdkService have been fixed, modified and enhanced; Error handling in TPGPDecode's data analysis has been slightly adjusted for special cases. http://idw-doc.homepage.t-online.de/PGPcomp.htm * ProDelphi v17.3 - by Helmuth J. H. Adolph Source code profiler for Delphi (runtime measurement). Features include: Cyclic storage of measurement results for long period measurement; Open the source in the Delphi editor by clicking a procedure in the viewer; Conditional compilation; Integrated into the Delphi IDE; Measures runtimes in DLL's; Delphi 2005 Win32 supported. http://www.prodelphi.de/ * ProDelphi.Net v3.0 - by Helmuth J. H. Adolph Source code profiler for Delphi 8 and Delphi 2005. It has the same features as ProDelphi except measuring functions written with the inline assembler (not supported for .Net platform). http://www.prodelphi.de/ * TscFontCombobox v1.1 - by Stefan Cruysberghs (with source) An advanced combobox which shows the available Windows fonts. A lot of features for preview, used fonts, show font types (truetype, printer, symbol), etc are provided. This component provides all features of the Microsoft and Corel font combobox. www.torry.net/news.php?id=26&SID=d05e863b8b4107c854fa651e2bbfdeaa * Vector Graphics ActiveX v1.6.0 - by Stas Semenov A graphics component for creating technical drawings, illustrations and presentation, training material and business reports, charts and diagrams and more. Based on Layer-Class-Shape architecture that repeatedly reduces the size of the stored data, to increase speed of loading and displaying documents, and also to provide excellent speed of execution with documents containing around 1,000,000 shapes. http://www.script-debugger.com/ * XP Graph v2.1 - by JLx Soft A Delphi Chart component equal like that one in Windows' task manager with bar and history, plus additional extensions. http://comps.jlxsoft.com/ Borland Product Updates ----------------------- * Delphi 2005: The Ultimate Delphi The complete development solution for Windows. With all of the Windows languages and SDKs you need in one environment for modern Windows rapid application development (RAD), Delphi 2005 takes the power of Delphi to the next level. With Delphi, C#, Microsoft .NET Framework and Win32 support for GUI, Web, database, modeling, and ALM in one hyperproductive RAD environment, Delphi 2005 makes Windows development tasks faster, better, and easier. http://www.borland.com/delphi/ Articles, Tips and Tricks ========================= * BDNradio: Delphi 2005 Live Chat on Interop with Chris Bensen In this audio replay, Chris discusses his work on ActiveX, COM, .NET interop, VLI and the New Component wizard. http://community.borland.com/article/0,1410,32858,00.html * BDNRadio: Log from Chat with Corbin Dunn on Delphi 2005 IDE Features Read the chat room log for questions answered by Corbin on Delphi 2005 IDE features, and listen to the replay. http://community.borland.com/article/0,1410,32850,00.html * BDNRadio: Delphi 2005 IDE Chat with Allen Bauer This is a log for the live audio chat from November 24th 2004 on Delphi 2005 with Allen Bauer, a Borland Principal Engineer, and Delphi IDE architect. Allen discusses his work on Delphi 2005. http://community.borland.com/article/0,1410,32843,00.html * Delphi 2005 Fixes for QualityCentral Bug Reports There are currently 263 QualityCentral bug reports closed with the release of Delphi 2005. http://community.borland.com/article/0,1410,32837,00.html * Namespaces in Delphi 2005 To make Delphi code friendlier towards other .NET languages Borland has changed the way Delphi 2005 produces namespaces. This article discusses the changes that have been made and how they affect you. http://community.borland.com/article/0,1410,32765,00.html * Advanced Markup Language Generation for IntraWeb Describes how to use an undocumented feature in IntraWeb to create complex controls that require multiple tags. http://community.borland.com/article/0,1410,32758,00.html * BDNradio: Chat Room Log of Live Chat with Danny Thorpe on Delphi 2005 This is the chat log for the live audio chat from November 19th 2004 on Delphi 2005 with Danny Thorpe, a Borland Chief Scientist and architect of the Delphi compilers. Danny discusses changes and enhancements to the Delphi Win32 and Microsoft.NET compilers, the run time framework and .NET support in general. http://community.borland.com/article/0,1410,32789,00.html * Using XMLDoc For API Documentation And HelpInsight With Delphi 2005 How to use Borland's XMLDoc tool to quickly and easily document your software and generate HelpInsight for your components. http://community.borland.com/article/0,1410,32770,00.html * What's New in Delphi 2005 - by Bob Swart A Technical White Paper on all that's new in Delphi 2005. http://community.borland.com/article/0,1410,32778,00.html * Building a custom data provider for .Text A case study on the porting of .Text from SQL Server to InterBase using Delphi for .NET. http://community.borland.com/article/0,1410,32419,00.html * Borland Conference 2004 Blogs An impressive compilation of blog entries that were created during BorCon 2004. It's not as good as being there, but it's close. http://community.borland.com/article/0,1410,32752,00.html * How to Check if a Document in a TWebBrowser is Located on a Local (or Network) Drive - by Zarko Gajic If you need to know the location of a document displayed in a TWebBrowser component, you need to get the Protocol property of the IHTMLLocation. Here's a function that returns true if a document in a WebBrowser is stored locally. http://delphi.about.com/od/adptips2004/a/bltip1204_5.htm * Using the TDBGrid Component - by Zarko Gajic Contrary to most other Delphi data-aware controls the DBGrid component has many nice features and is more powerful than you would have thought. There are many ways to customise the output of a DBGrid... http://delphi.about.com/od/usedbvcl/a/tdbgrid.htm * Retrieving All Image Links from an HTML Document - by mrbaseball34 Here's how to obtain all image links from an HTML document using Indy. http://delphi.about.com/od/adptips2004/a/bltip1204_3.htm * Making Delphi 2005 Independent from .NET - by Alvaro Garcia Pascual Despite what Borland says, Delphi 2005 doesn't require .NET. If you are a Delphi Win32 developer and don't like that Delphi 2005 comes polluted with .NET stuff, read this article to learn how to remove .Net from Delphi 2005. http://delphi.about.com/od/delphifornet/a/delphi2005win32.htm * A First Look at Delphi 2005 - by Zarko Gajic The time has come to take a sneak peak into a new Delphi version: Delphi 2005. Delphi 2005 is the ultimate weapon for developers: Delphi, C#, Win32 and .NET in one RAD environment. http://delphi.about.com/od/productreviews/ss/delphi2005first.htm * How to write a Ping utility using ICMP.dll - by Serge Perevoznyk Raw Sockets are subject to security checks and are accessible only to members of the administrator's group. Icmp.dll provides functionality that allows developers to write Internet ping applications on Windows systems without Winsock 2 support and without security problems. http://www.delphi-central.com/tutorials/icmp-ping.aspx * How To Find an Item in a Tree Control Via its Label - Serge Perevoznyk The "tree view" control does not have a built-in method for searching the entire tree or for selecting an item given its label. This article provides code that returns the location of any item in a tree when given a specific label to search for. http://www.delphi-central.com/tutorials/FindTreeViewNode.aspx Tutorials and Training ====================== * Installable Delphi 2005 Examples Download an installation for dozens of tested Delphi 2005 examples for use directly from the IDE. These examples include the C# and Delphi languages and both the Win32 and .NET platforms with text that introduces and explains them. http://community.borland.com/article/0,1410,32857,00.html * BDNtv: C++Builder in Delphi In this quick preview, Troy Kitch shows integration of C++Builder features in Delphi 2005. Flash http://bdntv.borland.com/cppbuilder/CPPinDelphi8x6.html * BDNtv: Unit testing in Delphi 2005 This BDNtv episode shows the unit testing integration for DUnit for a Delphi/Win32 application in Delphi 2005. Unit testing for C#, Delphi for .NET, and Delphi for Win32 with both NUnit and DUnit are supported in Delphi 2005. Flash http://dotnet.borland.com/bdntv/delphi/d2005unittesting8x6.html * GOF Behavioural Patterns with C#: Part 1 - by Barry Mossman This is the third article in a series upon the GOF Design patterns from a C# and .Net Framework perspective. It is covers some of the Behavioral Patterns: Chain of Responsibility, Command, Interpreter. http://community.borland.com/article/0,1410,32710,00.html * GOF Behavioural Patterns with C#: Part 2 - by Barry Mossman This is the fourth article in a series upon the GOF Design patterns from a C# and .Net Framework perspective. It is a continuation of the Behavioral Patterns this time looking at Iterator, Mediator, Observer and Memento (Momento) patterns. http://community.borland.com/article/0,1410,32795,00.html * Deriving a Model From an Existing Database with ECO II in Delphi 2005 Henrik Jondell demonstrates how easy it is to create model-powered applications for your existing databases with ECO II. Flash http://dotnet.borland.com/bdntv/delphi/eco2modelderivation.html * An Introduction to COM Programming with Delphi (1/6) - by Curtis Socha A brief historical rundown on COM's glorious past. Abstract methods vs. Interfaces. Classes and Interfaces: An interesting paradox. http://delphi.about.com/library/weekly/aa112304a.htm * An Introduction to COM Programming with Delphi (2/6) - by Curtis Socha What is an Interface? How to implement an Interface? Describing the TInterfacedObject. http://delphi.about.com/library/weekly/aa113004a.htm * An Introduction to COM Programming with Delphi (3/6) - by Curtis Socha What is the implements directive? What is the Method Resolution Clauses? Pseudo-Multiple Interface Inheritance. Interface properties and other fine tales of horror. http://delphi.about.com/library/weekly/aa120704a.htm * An Introduction to COM Programming with Delphi (4/6) - by Curtis Socha A Com Object walk-a-bout. A Class Factory tour. Our first true COM Object program. Homework Assignment. http://delphi.about.com/library/weekly/aa121404a.htm * An Introduction to COM Programming with Delphi (5/6) - by Curtis Socha Marshaling Data. Oh, the glory of leadership! Variant Reference Page. Using Variants and Variant Arrays. http://delphi.about.com/library/weekly/aa122104a.htm * Programming a Memory Game in Delphi: Part 1 - by Delphi Central In this tutorial, we will see how the TDrawGrid component can be used to help us develop a "Memory" game. Firstly we will describe what is involved with the Memory game. http://www.delphi-central.com/tutorials/memory_game.aspx * Programming a Memory Game in Delphi: Part 2 - by Delphi Central In part 1 we explained how to create the form and drawgrid at design time. Now we will move onto writing the actual code. http://www.delphi-central.com/tutorials/memory_game_2.aspx * Programming a Memory Game in Delphi: Part 3 - by Delphi Central In part 1 we explained how to create the form and drawgrid at design time, in part 2 we started writing the actual code. In the third part of the tutorial we will draw the grid that the game is played on. http://www.delphi-central.com/tutorials/memory_game_3.aspx News ==== * Delphi 2005 Architect Review Delphi has grown up since it launched nearly ten years ago. The latest version provides support for developing Win32 and .NET applications as well as supporting the C# language. There are many enhancements to almost all areas with the main goal of increasing developer productivity. http://www.builderau.com.au/program/0,39024614,39170720,00.htm * Global 2000 Companies Select Borland to Elevate Software Quality An unprecedented number of high-profile customers spanning a wide spectrum of industries and regions selected CaliberRM and StarTeam in 2004 as their preferred requirements management and software configuration and change management solutions. Companies that selected CaliberRM or StarTeam this year include: British Telecom, Comcast, EDS, Gap, HP, Jaguar Cars, Siemens AG, Symantec and Verizon Wireless. http://home.businesswire.com/portal/site/google/index.jsp? ndmViewId=news_view&newsId=20041206005289 * BDNradio Interviews with Borland's R&D staff for Delphi 2005 Don't miss these live interviews with Borland R&D engineers. http://community.borland.com/article/0,1410,32786,00.html * Software Delivery Optimisation Enables Disciplined Approach At the Borland Conference 2004, Dale Fuller, President and CEO, presented their vision and product strategy for transforming software development from an unpredictable art form into a more manageable and repeatable business process. http://www.itweb.co.za/sections/business/2004/0411150801.asp * Borland's ALM Products Receive Numerous Accolades in 2004 Borland today announced 2004 as a banner year for its products, with receiving numerous industry accolades and awards from around the globe. Industry recognition of their innovative solutions provides the company with significant momentum leading into 2005 and underscores their ongoing focus on technical excellence and customer value. http://home.businesswire.com/portal/site/google/index.jsp? ndmViewId=news_view&newsId=20041110005673&newsLang=en * Borland to Provide UML Support to MS Visual Studio 2005 Team System Borland joined Microsoft and other industry leaders in announcing support and future plans for Software Factories, a new industry approach to improve software development. As part of Borland's support for Software Factories, the company plans to deliver a domain-specific modeling solution providing UML capabilities within the Microsoft Visual Studio 2005 Team System. http://www.tmcnet.com/usubmit/2004/Oct/1087428.htm * Borland Focuses on UML Modeling Borland is breaking up Together ControlCenter for UML modeling into separate products for developing, designing, and architecting applications. The move is intended to align Together with the SDO strategy of providing a disciplined approach to development. http://www.infoworld.com/article/04/10/25/HNborcontrolcenter_1.html * IBM and Borland Upgrade Developer Tools IBM unveiled new Rational developer tools and Borland rolled out the new version of its Delphi Windows development tool. Both are maneuvering to infuse their platforms with business process automation commonly used in other areas of enterprise operations. http://www.computerweekly.com/articles/article.asp?liArticleID=134236 * Native Win32 and .Net Framework Support for New Delphi Delphi, the grand-daddy of visual programming environments, has been updated. Delphi 2005 works with both Win32 and .Net frameworks, and also supports Microsoft's C# as well as the Delphi language itself. http://www.pcpro.co.uk/news/64469/ native-win32-and-net-framework-support-for-new-delphi.html Other / Misc Sites ================== * The Daily WTF: Curious Perversions In Information Technology The Daily WTF presents scary code examples. If you are looking for a good laugh visit the site, I just hope your code is not there! :) http://thedailywtf.com/ ________________________________________________________________________ Irongut's Delphi Pages Dedicated to programming with Borland Delphi and Kylix. We have articles on programming, Borland and Delphi news, source code and components to use in your applications and more. >> http://www.paranoia.clara.net/ << ________________________________________________________________________ YOU CAN HELP US We need your help to keep this newsletter going and growing. You can help by referring the newsletter to your colleagues: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Or you can help by voting for us in some or all of these rankings to give more visibility to our web site and thus increase the number of subscriptions to this newsletter: http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium It's just a few seconds for you that REALLY mean a lot to us. Don't forget we also need articles and there are prizes available for contributions. All articles will be considered but we are particularly interested in articles about Kylix because there is so little available online to help Kylix developers. Send articles to: <pascal-newsletter-owner@yahoogroups.com> We are also looking for shareware authors who would like to offer their components or applications as prizes for articles in the newsletter. In return you will be promoted in the newsletter and on the Latium Software and Irongut's Delphi Pages websites. For more info contact: Dave Murray <irongut at vodafone dot net> ________________________________________________________________________ If you haven't received the full source code examples for this issue, you can get them from http://www.latiumsoftware.com/download/p0052.zip ________________________________________________________________________ This newsletter is provided "AS IS" without warranty of any kind. Its use implies the acceptance of our licensing terms and disclaimer of warranty you can read at http://www.latiumsoftware.com/en/legal.php where you will also find a note about legal trademarks. Articles are copyright of their respective authors and they are reproduced here with their permission. You can redistribute this newsletter as long as you do it in full (including copyright notices), without changes, and gratis. ________________________________________________________________________ Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Group Home: http://groups.yahoo.com/group/pascal-newsletter/ Subscribe: pascal-newsletter-subscribe@yahoogroups.com Unsubscribe: pascal-newsletter-unsubscribe@yahoogroups.com Problems with your subscription? pascal-newsletter-owner@yahoogroups.com ________________________________________________________________________ Latium Software: http://www.latiumsoftware.com/en/index.php Irongut's Delphi Pages: http://www.paranoia.clara.net/ Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved. ________________________________________________________________________ |
The full source code examples of this issue are available for download.
![]() |
Errors? Omissions? Comments? Please contact us!






