42
Pascal BLAISE PASCAL ENGLISH VERSION ALL ABOUT DELPHI AND KYLIX, PASCAL AND RELATED LANGUAGES 2 June 2008 Publisher: Foundation for Supporting the Pascal Programming Language (Stichting Ondersteuning Programeertaal Pascal) in collaboration with the Dutch Pascal User Group (Pascal Gebruikers Groep) © Stichting Ondersteuning Programeertaal Pascal Cover price Europe: € 10.00 / UK £ 7.00 / US $ 15.00 Effective Pascal For-Loops / Hacks1-Write access to read-only property Resizing Bitmaps Delphi 2007 VCL Component Building - II ClientDataset filtering Intraweb and AJAX Delphi for PHP .2 new version Solving unknown variables Obfuscator? Restricting Edits to numbers / Euro symbol generation with the Alt key Monitor aspects Binary Heap David Dirkse Making right-justified Edits Henk Schreij Martin De Bont Bob Swart Herman Peeren Peter Bijlsma Rob van den Bogert Henk Schreij Hallvard Vassbotn Bob Swart Jeremy North Julian Bucknall

Blaise Pascal 2 Uk Print Able Download

Embed Size (px)

DESCRIPTION

Blaise Pascal 2 Uk Print Able Download

Citation preview

Page 1: Blaise Pascal 2 Uk Print Able Download

Pascal

BLAISE PASCALENGLISH VERSION

ALL ABOUT DELPHI AND KYLIX, PASCAL AND RELATED LANGUAGES

2

June 2008

Publisher: Foundation for Supporting the Pascal Programming Language(Stichting Ondersteuning Programeertaal Pascal)in collaboration with the Dutch Pascal User Group (Pascal Gebruikers Groep)© Stichting Ondersteuning Programeertaal PascalCover price Europe: € 10.00 / UK £ 7.00 / US $ 15.00

Effective Pascal For-Loops / Hacks1-Write access to read-only propertyResizing Bitmaps

Delphi 2007 VCL Component Building - II ClientDataset filteringIntraweb and AJAX Delphi for PHP .2 new version

Solving unknown variables Obfuscator?Restricting Edits to numbers / Euro symbol generation with the Alt key

Monitor aspects Binary Heap

David Dirkse Making right-justified Edits Henk Schreij

Martin De Bont Bob Swart Herman Peeren

Peter Bijlsma Rob van den Bogert Henk Schreij

Hallvard Vassbotn

Bob Swart

Jeremy North Julian Bucknall

Page 2: Blaise Pascal 2 Uk Print Able Download

June 2008 BLAISE PASCAL 2 Page 2 / 1816

All material published in Blaise Pascal is copyright © SOPP Stichting Ondersteuning Programeertaal Pascal unless otherwise noted and may not be copied, distributed or republished without written permission. Authors agree that code associated with their articles will be made available to subscribers after publication by placing it on the website of the PGG for download, and that articles and code will be placed on distributable data storage media. Use of program listings by subscribers for research and study purposes is allowed, but not for commercial purposes. Commercial use of program listings and code is prohibited without the written permission of the author.

Volume 2, ISSN 1876-0589BLAISE PASCAL 2CONTENTS

Copyright notice

Editor in chief

News and Press Releases

Authors

Editors

Translations

Copyright Trademarks

Caveat

Subscriptions

ABN AMRO Bank Account no. 44 19 60 863

IBAN: NL82 ABNA 0441960863BIC ABNANL2A VAT no.: 81 42 54 147(Stichting Programmeertaal Pascal)

Subscription department

Detlef D. Overbeek, NetherlandsTel.: +31 (0)30 68.76.981 / Mobile: +31 (0)6 21.23.62.68

N Jeremy North,O Tim Opsteeg,

V Hallvard VassBotn.

A.W. (Bert) Jonker, M. L. E. J.M. (Miguel) van de Laar

M. L. E. J.M. (Miguel) van de Laar, Kenneth Cox (Official Translator)

4 issues per year excl. postage. Postage fore Europe € 3,-- World € 5,50

ubscription € 25.-- UK 22.-- $ 40.–(including code, programs and download magazine)

3: Basic Subscription: € 10.-- UK .-- $ 15.–(excluding code, programs and non printable/non editable download magazine)

or by written order, or by sending an email to

Subscriptions can start at any date. All issues published in the calendar year of the subscription will be sent as well.

the subscription department receives

email only to [email protected]

www.blaisepascal.eu

[email protected]

[email protected]

B Martin de Bont, Julian Bucknall, C Marco Cantu, D David Dirkse, Frans Doove,

P Herman Peeren, S Henk Schreij, Rik Smit, Bob Swart,

Rob van den Bogert, W. (Wim) van Ingen Schenau,M.J. (Marco) Roessen.

See the notice at the bottom of this page.All trademarks used are acknowledged as

the property of their respective owners.Whilst we endeavour to ensure that what is

published in the magazine is correct, we cannot accept responsibility for any errors or omissions. If you notice something which may be incorrect, please contact the Editor and we will publish a correction where relevant.

1: Printed version: subscription € 40.-- UK 28.-- $ 60.–(including code, programs and printed magazine,

2: Non printed s

Subscriptions can be taken out online at

plus postage.Subscriptions are parallel to the calender year. Subscriptions will be prolonged without notice unless

notice of cancellation by letter or email before 1 November. Receipt of payment will be sent by email. Invoices will be sent with the February issue.Subscription can be paid by sending the payment to:

Edelstenenbaan 21 3402 XA IJsselstein, The NetherlandsTel.: + 31 (0) 30 68.76.981/Mobile: + 31 (0) 6 21.23.62.68

Peter Bijlsma,

Corrector

£

£

£ 9

€ 10.00 / UK £ 7.00 / US $ 15.00

Foundation for Supporting the Pascal Programming Language (Stichting Ondersteuning Programeertaal Pascal)

Cover price in Europe:

ALL ABOUT DELPHI AND KYLIX PASCAL AND RELATED LANGUAGES

Articles

ColumnsBooks by Frans Doove pag 6

Components 4 Developers pag 40DeepSea Obfuscator pag 38

Effective Pascal For-Loops

Hacks1-Write access to read-only property

Making right-justified Edits

Delphi 2007 VCL Component Building - II

Solving unknown variables in a set of linear equations

Restricting Edits to numbers

Euro symbol generation with the Alt key

Monitor aspects

Hallvard Vassbotn

Hallvard Vassbotn

Bob Swart

Bob Swart

Jeremy North

Julian Bucknall

pag 9

pag 11Resizing Bitmaps David Dirkse pag 12

Henk Schreij pag 14

pag 16ClientDataset filteringMartin De Bont pag 20Intraweb 9.x and AJAX

pag 25

Herman Peeren pag 3

Peter Bijlsma pag 28

Rob van den Bogert pag 30

Henk Schreij pag 32

Henk Schreij pag 38

pag 33Binary Heap

pag 21

Advertisers

Delphi 4 PHP versie 2

Obfuscator?

The illustrations on the cover are from the book Pascal, mathematician of God.The first calculator ever, invented by Pascal with some technical details.The statistic figures were delivered by Julian Bucknall

Page 3: Blaise Pascal 2 Uk Print Able Download

Page 3 / 1817

Foreword...Already the second issue and there are more to come.It was a hefty quarter for Delphi people. A new magazine, a new company for CodeGear, a new horizon on the sky for Delphi and their other products. Hope forinspiring new developments. “Embarcadero” has a promising sound.

We found out that we now have the start of a new subscriber group: the paperless people. About 2000 free downloads of the first issue, over night.Lots of readers let us know how pleased they are with our initiative to revive a ”Pascal Magazine”.

And we are very pleased that many well known authorsagreed to write for us. That is a very good thing. One of the most asked questions was: will you still do articles for starters and hobby Pascallers?

Of course we will. New techniques are very interesting, but older ones like the article of Julian about the Binary Heap are so fundamental, that even beginners should try to understand that matter. It really makes you a better“beginner” because after it you will understand some more of the fundamentals. Even though now a days it is not done to talk about pointers and all that stuff.Back to the roots. It is heard everywhere. And still inspiring. And I hope for Delphi as well. Now there needs to be stable times, a time to built the future again.

Detlef Overbeek

Downloads of code, applications etc. are available on our website: www.blaisepascal.eu

June 2008 BLAISE PASCAL 2

Delphi for PHP 2.0 by Herman Peeren

In the beginning of May the second edition of Delphi for PHP was launched. Some striking new features:

Templated Forms: you can now drag and drop HTMLelements as well as VCL-components on a form. You can also import HTML-pages, made with another web- design tool, like Dreamweaver.

· Visual guidelines, as we know them from the Delphi IDE, for easier alignment.

· Improvements in the code view, like: code completion, syntax checking, code folding, change tracking and sync edit. With all this, Delphi for PHP is also a good editor for non-visual PHP-files.

· Besides ADOdb for access to many different databases, new components were added for native database connections like for Oracle, Microsoft SQL Server and PostgreSQL. Database access can be visually

accomplished by dragging tables on a form. Personally I don't like the explosion of native db-classes; I would have preferred a wrap in one set of database access components, being able to easily switch between the several kinds with a parameter.

· Improved documentation and more than 20 new samples

There are more enhancements. For an overview of all new features:

·

www.codegear.com/products/delphi/php/whats-new/

Templated formsThis is not the same as the use of templates, like Smarty-templates, for designing a webpage. Which is still a very useful way of using Delphi for PHP-components in a webpage. The new Templated Form Designer is an extension of the (also new) HTML Designer. The HTML Designer provides visual capabilities to edit HTML files plus the ability to drag and drop HTML elements such as HTML Input Fields, HTML Drop Down and HTML button controls from the Tool Palette on a form. The Templated Form Designer adds the ability to work with PHP components in such an HTML-form. When working on a templated form, PHP components can be dropped inside the HTML form, and behave like any other HTML element.

Templated Forms enable PHP developers to develop applications using “tagging” similar to ASP.NET or Cold Fusion. For instance, you can now create a templated form and add tags like the following:

<button:php id="Button1" style="z-index: 1000; width: 75px; height:25px"></button:php>

into your HTML pages. Those HTML pages can be edited in a visual designer or in a text editor. This mode of development enables the decoupling of the PHP code from the HTML code, so that developers can pass off their HTML files to external designers who can provide the styling of the HTML pages while working around the PHP tags in the HTML.

PHP-components can thus be added to a page by using a kind of php-“namespace”… but follwing after the tag-name in stead of leading before it. Maybe someone had read a book about XML-basics upside-down.

for PHP 2

Page 4: Blaise Pascal 2 Uk Print Able Download

Page 4 / 1818

For instance, there is a scrollbar-component, but it is (still) not possible to simply add a scrollbar to any container-component, without quite some coding what is to be scrolled and how. In ActionScript (used in Adobe's Flash and Flex) you can simply drag a scrollbar-component to anything that can contain other things. Drag-drop-ready. You could rewrite all components in Delphi for PHP stemming from the control-component by taking a scrollingControl-component as base, but then you'll have to rewrite a whole tree of components; that is the inflexibility of inheritance as basis for the VCL.

June 2008 BLAISE PASCAL 2

Never have I seen something like that, very original, but in my humble opinion: good for nothing. The idea is that a page can be designed outside of Delphi for PHP. A page produced with a templated form in Delphi for PHP can indeed be further designed with another program, like Dreamwever.

But the other way around doesn't work with Delphi for PHP ! You can import an HTML-page into Delphi for PHP, sure, but it ignores everything other than plain HTML (including their own tags like “button:php”). For instance, with Notepad I've put in an html-body:

yet

<button:php id="Button1" style="z-index: 1000; width: 75px; height:25px"></button:php><input name="button4" type="button" /><newtag>this some nonexistent tag of my own</newtag>

Guess what Delphi for PHP made out of it… this:

<input type="button" name="button4" /> <newtag>&nbsp;</newtag>&nbsp;&nbsp;this some nonexistent tag of my own

So: ignoring the button:php-tag and making a mess out of an unknown tag… Not very handy. When using the templated form, you cannot directly position the PHP-components anymore: you must first put “position: absolute;” in the component's style-code in the template-window. One of those child-diseases… An improvement to version 1.0 is that you can use percentages in Delph4PHP, but only when making use of a templated form.

Something else:I've experimented a bit with importing HTML-pages that were made up outside Delphi for PHP. Of course: with all styling in a separate CSS-stylesheet. That seems to go well, but as soon as you reposition something in Delphi for PHP, an inline style is used and thereby the stylesheet is ignored. Maybe the bad habits of Visual Studio shouldn't be copied….All in all, I think, that the use of Smarty-templates in Delphi for PHP is still favorable above the use of the new templated forms. It'll have to mature first.

My personal experienceI like the idea: PHP is widely used, but there was no visual IDE (Integrated Development Environment) for PHP. Besides, there are a lot of open source frameworks that are used for PHP- and JavaScript-development, which could be nicely integrated. A VCL (Visual Component Library) was made, mainly based on the way the Delphi VCL is organized (with some features that were inspired by the .NET-FCL). All of this was build into a Delphi-like IDE et voilà: Delphi for PHP.

Figure 1: Templated form designer

Figure 2: Visual designer guidelines

Figure3: Code insight and code completion

Delphi for PHP 2.0

An improvement to the VCL for PHP in comparison with the VCL for Delphi is, that there are no separate components for data-aware use. So, no TEdit plus a TDBEdit etcetera. An Edit-component in Delphi for PHP has a DataSource and a DataField property. And so have many other components. Unfortunately the VCL for PHP is, just as the classical VCL for Delphi, mainly based on inheritance of classes in stead of using interfaces for a more flexible object oriented design. An “interface” that can be “implemented” is standard object oriented PHP5, but it is not used in the VCL. Some components are still not complete.

for PHP 2

Page 5: Blaise Pascal 2 Uk Print Able Download

Page 5 / 1819

To in advertise

email

mob. + 31.6.21.23.62.68

or see our price list

[email protected]

http://www.blaisepascal.eu/index.php

?actie=advertprices/priceinform

June 2008 BLAISE PASCAL 2

Figure 4: Code folding and new code tracking

By the way: I added a vertical scrollbar to a panel (say: panel1) by simply adding #panel1_outer {overflow-y:auto;} to my stylesheet. There is always a way to do something, but these kinds of hacks don't give the most beautiful code and it is certainly not the way visual application development is intended.

A problem with the use of several different open source frameworks in one IDE is that some of them don't cooperate very well. For instance: you can use some very nice tabbed panes (from the qooxdoo-framework), you can use a dbRepeater-component for displaying some database-data, but in version 1.0 you could not use those two components together… The data-rows would be displayed much to far to the left. This is fixed now in version 2.0 (great!). So, although it is very nice to use all that beautiful open source code that already exists on this planet, the VCL4PHP-builders have a lot of work to integrate the different frameworks to a whole. In that way, it was an advantage of the .NET framework that it was build from scratch.

Figure 5: Drag and drop a table from a databse on a form

Version 2.0 is certainly a big improvement.Unfortunately, but understandable, it is not completely backwards compatible with version 1.0: some projects that were made with the previous version don't work in the new version. For instance: if a panel-component was put on a page in version 1.0, and that unit is opened in version 2.0, than it is impossible to set the visible-property to false. Having used the panel-visibility-property several times in a Delphi for PHP-project under version 1.0, I still have to use version 1.0 to edit my old sources… But well, that's the disadvantage of an early user.

I made a “back-end” of a CMS (Content Management System) in Delphi for PHP 1.0. It was okay for quickly making up screens for inserting and editing data, and it would have been better with version 2.0. But it is not very flexible; also because all the HTML-rendering is done in the different components themselves. Delphi for PHP was intended for making web-applications. That is certainly something else than designing websites. But: it is also something else than making desktop-applications. Web-applications are often integrated in websites (e.g. shopping cart) and are thereby viewed by different browsers on different screens etc. The lessons of today's web-design to separate design from content by using CSS should be better taken into account by Delphi for PHP.

I think Delphi for PHP can become a useful tool, but we are not yet there. Of course, if your styling doesn't have to be flexible and you quickly want to make a web-application, then Delphi for PHP is a good choice. Fortunately Delphi for PHP 2.0 is also a good editor for non-visual PHP-files, so I'll certainly use it as my standard PHP-editor.

Conclusion

Herman Peerenis addicted to computer-programming since 1977 and has worked in many different fields. His passion is the combination of creativity and technique. At the moment he is mainly focussing on web-applications and -design. He will write some articles about Object Oriented Programming and Design Patterns in Blaise Pascal Magazine.

Helpful suggestionsBlaise Pascal

for using your issue of

3 Recommended versionMouseover hints appear in some locacations.The page numbers on the contents page are clickable.All URLs are clickable and direct you to the site.

èèè

2005 Win32 2005 .NET

About using this PDF fileOne of the most attractive features of Adobe Acrobat PDF files is that you can incorporate hyperlinks in them. We do this wherever appropriate. The articles listed on page 2 can be accessed by clicking the title or the page number. This takes you directly to start of the article you want to read. All URLs listed in code and mentioned in adverts are also clickable.

Delphi for PHP 2.0 for PHP 2

BLAISE PASCAL MAGAZINE

Page 6: Blaise Pascal 2 Uk Print Able Download

Page 6 / 1820 June 2008 BLAISE PASCAL 2

Books by Frans Doove

I continue to find it extremely remarkable and incomprehensible that user's guides are no longer published for new versions of Delphi – not by the software producer and not by other publishers. In my opinion, a good user's guide, in addition to its educational aspects, has a not inconsiderable promotional aspect. You would think that people in this field would take a cue from Microsoft, which even offers free magazines – including in Dutch.I also think that the lack of user's guides makes things unnecessarily difficult for beginners in particular and for all users in general. Another aspect is that the lack of user's guides and textbooks makes hobby programming more difficult and perhaps even practically impossible. Maybe software developers and publishers have come to regard hobbyist programmers as an extinct race? Many programmers, at least in the past, started out as hobbyists and later became professionals.

I fear that there is too little realisation that software packages, such as Delphi, are in fact rather difficult for beginners, including novice programmers. This ultimately involves at least two aspects: learning to use the development environment and mastering the programming language – although we must not overlook the underlying theory, such as object-oriented programming.

One of the difficulties in writing a user's guide – as well as a magazine article – is the risk that the description of how the programming environment works, in preparation for solving programming problems, remains a 'mental exercise' for too long and is too far removed from actual programming. Maybe this is why there are now so few good books on programming that are oriented toward beginners. Solving programming problems without adequate knowledge of the programming environment is like walking in the dark. However, knowledge of the programming environment alone does solve any programming problems. And searching the Web, of course, is even less useful.

2008, English, 104 pages, paper, A4 format. No ISBN number; self-published. Order via Lulu ( ). Recommended price: € 23 including shipping. Payment by credit card.

Bob Swart:Delphi 7 for Win 32 Development Essentials

www.lulu.com

For many years, Cantù had an e-book on his website with the title Essential Pascal, which could be downloaded free of charge. Now a revised and updated version of the text has been published by Lulu. I have a previous version of the book from 2003. The present version lacks the screenshots of the previous version, and there is no longer any colour in the text. I understand that this has to do with how it is published (and the publishing costs).

The book consists of twelve chapters dedicated to Pascal as a programming language in Delphi. Naturally, the fact that the book can also be used with Free Pascal (and thus with Lazarus) and Chrome is mentioned. The book describes the conventional Pascal constructions, but not the object-oriented extensions. The intention is to publish a new version of the book with each new version of Delphi, but not to include any OOP extensions.The source code of the examples is still available free of charge from the author's website.The topics discussed in the twelve chapters are: Chapt. 1: A brief history of the Pascal language. Chapt. 2: Coding in Pascal. Chapt. 3: Types, variables and constants. Chapt. 4: User-defined data types. Chapt. 5: Statements. Chapt. 6: Procedures and functions. Chapt. 7: Handling strings. Chapt. 8: Memory. Chapt. 9: Windows programming. Chapt. 10: Variants. Chapt. 11: Programs and units. Chapt. 12: Files in the Pascal language.

Reading this book is a pleasure. It is a good introduction to the Pascal language, but without any mention of Delphi. In a certain sense, this is not logical, since Delphi also provides opportunities to try out the described code, so beginners can concentrate on becoming proficient in Pascal without having to learn how to use Delphi at the same time.

However, most of the sample code in the discussions of the various topics is only program components instead of complete programs. This means that you need another book to learn how to use Delphi as programming environment. Of course, the book can also be used as a reference book for aspects of the language, but I think that what the author had in mind was beginners who want to use the Pascal language and programmers who come to it from another language. Naturally, there are also other environments for working with Pascal, although Lazarus users (for example) will experience the same problems as Delphi users.

In my opinion this book is not primarily intended for beginners, but instead specifically for relatively experienced programmers who use or plan to use Delphi 7 with Windows 32. In five chapters, the author discusses five specific features of this version. Each chapter deals with a specific function of Delphi 7, in part by solving programming exercises. I find this combined approach very worthwhile. It is a suitable answer to the previously described problem.Chapter 1 is relative general and discusses (among other things) templates, designers, Vista support, Code Editor and refactoring.Chapter 2 introduces the changes and extensions to the language, with many examples.

Chapter 3 describes the Together engine in considerable detail (30 pages), with extensive code examples.Chapter 4 discusses unit testing, again with extensive application examples.The final chapter discusses examples of globalisation and localisation.

The discussions of the topics are clear and include many illustrative examples, as we are accustomed to see with this author.However, the reader must have a certain amount of prior knowledge and – an important consideration – must have the described Delphi version on his or her computer.Warmly recommended!

2008, English, self-published, no ISBN number; order via Lulu ( ). Recommended price: € 20 plus shipping. Payment by credit card.beginners.

Cantù: Essential Pascal

www.lulu.com

Page 7: Blaise Pascal 2 Uk Print Able Download

Page 7 / 1821June 2008 BLAISE PASCAL 2

The news that CodeGear had been purchased by a software company that specialises in databases came in while I was preparing this text. Aside from the commercial aspects, this seems fairly logical to me. In the last while, I increasingly have the impression that Delhi programming is heading more and more in the direction of using computers for databases. A long time ago already, the French called the computer an 'ordinateur'. Maybe they were especially farsighted?In all honesty, I find this development regrettable if it is true. However, when I read the text on the Web about the origin of the 'world's largest platform-independent software provider of database and application tools', I fear that my suspicions are not entirely unfounded. On the one hand, the increasing use of computers as 'application devices' is positive and understandable, but it reduces the use of computers as tools for developing software. This despite the impression I have that there is still a lot of room for computers in and in aid of fields such as education (and probably the Dutch tax office as well). And of course, for more inventiveness in programming!

This nicely published book is written by two Dutch authors and published in English by an American publisher. It consists of twelve chapters arranged in four parts.

Part 1 (chapters 1–4) is dedicated to the underlying mathematics of databases and database design. It provides an introduction to logic (Chapt. 1), an introduction to set theory (Chapters 2 & 3), and an introduction to relations and functions (Chapt. 4).The purpose of these introductory chapters is to provide a foundation for database design. The topics discussed in these four chapters are in fact the most essential fundamental concepts in this area. These topics are always discussed in introductory courses in informatics, as well as in introductions to logic and discrete mathematics. The explanations are excellent: clear and comprehensible, with many problems and exercises. The ideas here are actually not overly difficult; they are the usual basic concepts.The text includes many examples and overviews.

The explanations are clear, and the examples are illustrative. All significant features of the language are described. I don't know what target group the author had in mind. The explanations and examples are accessible to beginners as well as experienced programmers. However, beginners will have to learn how to use the programming environment, and with relatively large programs where an understanding of OOP is necessary they will have to consult other references. I'm not sure that beginners will know what FORTRAN, COBOL and Wordstar were (p. 12), unless they're rather old beginners. I still happen to know.

Recommended for beginners and as a reference for everyone.

Each chapter ends with a summary and a number of exercises. The answers to some of the exercises are given in Appendix E. Chapter 2, an introduction to set theory, is structured similarly and the topic is discussed clearly. Chapter 3 discusses logic in more detail. The topics that are discussed include algebraic properties and concepts such as commutative, associative, distributive, etc.

Part 2, 'The Application' (chapters 5–10), devotes 130 pages to a discussion of applications. The topics include database design and the structures of possible manipulations. The terms and concepts are explained in the discussion with figures and listings. The explanations are clear and complete.

Part 3, 'The Implementation' (chapters 11 & 12; 70 pp) begins with a discussion of the database design and then describes the implementation in Oracle. Chapter 12 is short (3½ pages) and provides a summary of the objectives of the book. It presents a sort of rationale for the introductory mathematical chapters and their application to the design of databases. This chapter should actually be located at the front of the book as a sort of preface.

Part 4 consists of Appendices A–E (55 pp). Appendix A gives a formal definition of an example database. Appendix B provides an overview of the symbols. Appendix C contains a bibliography. Here it struck me that many books dating back ten years or more are listed as background references. Appendix D provides an overview of multi-valued logic, and Appendix E provides answers to some of the exercises (without explanations).It is difficult to judge whether this book is intended for students in educational programmes and/or for self-study. The authors (one of whom is now deceased) point out that anyone who does not have a basic understanding of the logic discussed in the book will find the book quite difficult. It is not clear whether this is based on experience with teaching this subject. The mathematics, which are discussed clearly, are fairly basic and in my opinion not enormously difficult, although the authors suggest otherwise. The database theory is decidedly more complex and more difficult.

Aside from the question of whether this book is suitable for self-study, the authors say on page 23 that the target audience is IT professionals: developers, designers and architects.A good book, but probably most suitable for a specific target group, in part due to the use of the Oracle platform.

Lex de Haan and Toon Koppelaars: Applied Mathematics for Database Professionals2007, Apress, English, hardbound, 376 pp, ISBN 13:978-1-59059-745-3, no CD. The accompanying code is available on the publisher's website. Recommended price: € 45.

Daniel Solis: Illustrated C# 20082008. Apress, English, paper, 694 pp, ISBN 13:978-1-59059-954, no CD; recommended price: $ 45

A while ago we devoted some attention to C# in Blaise. At that time, Microsoft made it possible to distribute a CD with Visual Studio and C#, in order to not only advertise the capabilities of Visual Studio and .NET but also promote writing software for them in a modern programming language. As a result, many Delphi users seriously wondered whether they were witnessing the gradual demise of Delphi, perhaps abetted by the policies of Borland and its successor.

Books

Page 8: Blaise Pascal 2 Uk Print Able Download

And they wondered whether C# was perhaps its modern successor.Fortunately, the Delphi scene has calmed down somewhat since then, although new speculations have arisen suddenly from time to time. It's clear that there is still considerable interest in Delphi and Pascal, throughout the world.

Of course, it's a good idea to keep a close eye on the problems and developments. Here I can mention two items which indicate that the problems have not been eliminated.The first item is that Microsoft distributed a CD with Visual Studio and Microsoft Visual C# via the May 2008 issue of the Dutch PC Magazine.The second item gives me even more cause for concern. On the website of a large, specialised bookseller, which provides mail-order service as well as shop sales, I once checked to see how many books were available on Pascal and Delphi and on C# at that time. There were 23 books specifically devoted to C# 2008. There were a total of 10 on Delphi. Of these, leaving aside the level, there were three on Delhi 5, two on Delphi 6, three on Delphi 7, two on Delphi 8, and one on Delphi 2005.I fear this shows that somewhat more advertising for Delphi, now that the interest in (and use of?) C# is so large, is not unwarranted.

Solis's extensive book on C# 2008 is intended to appeal to beginners and moderately advanced programmers. It is a large book. The table of contents occupies 40 pages, the text fills 656 pages, and there is a 37-page index. Extensive tables of contents and indexes are always important for getting to know the structure of a book, so the book rates well in this regard. It gives the reader a good overview and insight into what it has to offer. And finally, there are 25 chapters.

My first exploratory browsing through the book gave me the impression of an old-fashioned reliable textbook for learning to program in C#. The question is whether this first impression is correct.

The author based his approach on the idea that many readers think visually. This means that figures, tables and charts are useful for assimilating the material. This translates into a combination of text and illustrations. In addition to the countless code examples, the discussed topics are illustrated by many charts and tables. It is impossible to mention all the topics that are discussed. After a general introduction to the C# language and .NET, as well as a general introduction to programming in C#, there is a discussion of variables, classes and methods, inheritance, expressions, operators, and statements. This is followed by exceptions, structs and arrays, events, interfaces, conversions, generics, and LINQ.

This list is naturally not complete, but it gives an impression of the broad range of topics. In this regard it is a rich book, with many clear explanations and a large number of examples and illustrations.

One thing I miss are chapter summaries, although the chapters are relatively short (around 18 pages on average). What I miss the most are programming exercises so readers can practice on their own and apply the discussed material to check their comprehension. Maybe this is because relatively few complete programs are generated in the book. Or because there is rather little discussion of .NET. I noticed this especially because the author is said to have experience in teaching programming courses. However, the author may have intentionally chosen to concentrate on programming in C# and omit any further digressions or discussion of applications. With 600 pages, there is naturally plenty of learning material.

In summary: a good book that offers lots of study material. The explanations are clear. For some applications, including fairly essential ones, you will need to study another book. The term 'illustrated' in the title reflects the large number of tables, charts and code examples in the book. There are no screen shots. .NET is only discussed on a few pages in the first chapter. There is also no mention of which programming environment can or must be used.

Page 8 / 1822 June 2008 BLAISE PASCAL 2

Books

Readers Please send your questions and comments to:

email [email protected] to: Edelstenenbaan 21

3402 XA IJsselstein, The NetherlandsTel.: + 31 (0) 30 68.76.981

Mobile: + 31 (0) 6 21.23.62.68

How to become a subscriber

*

subcribe

*for the first year € 25.00

First of all you need to decide whether you want:

1 the printed version ,

2 the no paper (download) version, printing enabled and code included.

3 the basic download version,

without code, downloads and printing disabled. The second issue is not free but costs € 10,00.

Any first issue can be downloaded at any time.(If it is your first download.)

Special limited-time offer:

to the “printed version” or “no paper”

download version

You can pay with PayPal or by credit card (Take Two) or by bank. Look for subscription details on page 2

code included, fully printable version,lectronic version download included;including tax, postage (4 issues = 20,00 euro’s, total € 45,00)You can have your electronic version immediatly whilst the printed issue is on its way.

(you don't have to pay postage, just pay € 25,00).

without

excluded

Page 9: Blaise Pascal 2 Uk Print Able Download

Efficient Pascal – For-loops

As one of the pillars of modern programming has stated; “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” C. A. R. Hoare ( )

But we should not confuse premature optimization with using an efficient programming style – a style where you consistently use coding patterns that are clear, easy to read, but that still produce reasonably efficient code. Subtle changes in coding style can produce significant improvements in code size, memory usage and performance. In your day to day coding you should employ an efficient coding style. Only in specific, proven performance critical points in the code, you should go to the extra effort of optimizing the code further, making sure to perform measurements before and after the improvements.

In this article we will look more closely at loops and how to write efficient code using them. Pascal has a rich set of loop statements; for-do, while-do, repeat-until and in more recent Delphis, for-in. In addition direct and indirect recursion and even the shunned goto-statement can be used to perform repetitive tasks.

One trait of an efficient programmer is the ability to select the most appropriate loop for a given situation. While it is possible to use any of them for a given task, code complexity can often be reduced by using the loop-statement that best fit the requirements. For instance, I've seen programmers almost exclusively using repeat-until loops, even when looping over the contents of a list, like this:

http://en.wikipedia.org/wiki/C._A._R._Hoare

Choosing the right kind of loop

For such a simple and common operation as looping over the contents of a list, this code is way to complex. It is hard to write initially, getting the border cases and conditions right, it is hard to maintain and debug and it generates sub-optimal code. There are several problems with this code. Because the condition of a repeat-until loop is only checked at the end of the loop, after the first iteration, we have to have an extra condition at the top for the special case of an empty list. In addition, the loop index variable i is initialized, incremented and checked in three separate points in the code. The chances of getting one of these statements wrong is high, and, worse, the reader and maintainer of the code has to read, understand and verify these four statements every time the code is read or modified. Performance and code-size wise, the code is inferior because of the duplication of the List.Count check and the fact that the until-expression is evaluated for every iteration of the loop (this can be more significant when the run-time cost of the expression is higher than in this case).This kind of loop, counting from 0 to a known count is a perfect fit for the for-do loop.

Notice that the collection being looped over here is an instance of TList. In Win32, TList holds a list of pointers. Most programmers would probably write the assignment to Item like this:Item TMyObject List i This is fine and produces identical code to the line above, but strictly speaking the hard type-cast is not needed since untyped pointers are assignment compatible with all other pointers and object references. So the line above can be written:Item List i

This change does not affect the generated code, but I think it produces slightly less cluttered and easier to read code. Of course, you need to ensure that the list actually only contains object references that is (or inherits from) TMyObject. For the safety minded, you could to assign or cast to TObject first then perform a run-time checking as-cast.Item TObject List i TMyObject; One alternative is to only keep the checks in assert-enabled debug builds, like this: Item List i Assert TObject Item TMyObject ; Another issue is that evaluating List[i] is the same as accessing the default property of TList, Items:

:= ( [ ]);

:= [ ];

:= ( [ ])

:= [ ];( ( ) )

as

is

Notice that Get first checks that the index is in a valid range between 0 and Count-1. Inside the for-loop (provided we have coded it correctly), this test is superfluous, because we know that the index is always between 0 and Count-1. This is admittedly a minuscule performance overhead (even including the call and return instructions), but inside multiple, long running and potentially nested loops, this can add up. It also generates slightly larger code. Is there any way around this extra call and checking?

It turns out there is. Helpfully, the TList class declares a public read-only property called List that gives access to a pointer to the internal array of pointers.

List PPointerList FList

The clue here is that by accessing the items of the TList directly through the List property, we avoid the overhead of calling Get and checking the indx. This is part of my everyday coding style:

property read : ;

Hallvard Vassbotn

procedurevar

beginif thenbegin

repeat

untilend

end

DoOperations List TList

i integer Item TMyObject

List Count i Item List i Item Operation i i i List Count

( );

; ;

.

;

[ ];. ;

;. ;

; ;

:

: :

>

:=

:=

:= + >=

0

0

1

procedure var begin

for to dobegin

endend

DoOperations2 List TListi integer Item TMyObject;

i List.Count-1 Item List i Item Operation

( : );;

[ ];. ;

;;

: :

:=

:=

0

// Compiles ok

Items Index Integer Pointer Get Put default

Item List.Items i

Deze toegang gaat via de TList.Get methode

TList Get Index Integer Pointer;

Index Index FCount Error SListIndexError Index Result FList Index

;

property read write

functionbegin

if or then

end

[ ]:; ;

[ ];

. ( )

( ) ( )( , );

];

:

…:=

: :

< >=@:= ^[

// Same as List[i]

0

procedurevar begin

for to dobegin

endend

DoOperations2 List TList

i List.Count Item List.List i Item.Operation

( : );

-

[ ];;

;;

i integer Item TMyObject: ; : ;

:=

:=

0 1

Notice that if you compile with range-checking on, there will still be a check to see that the index is in the range 0..MaxListSize-1, but this is performed using a fast single instruction. You could disable this range-checking just for that statement:{$R-} Item List.List {$R+}:= [ ];i // Direct array access

It has a number of advantages over the repeat-until loop above. It combines the initialization, increment and check into a single statement. It also only evaluates the from- and to-expressions only once before the loop.

But it is starting to get ugly. In my opinion, we come to the point of what constitutes an efficient coding style for for-loops over a TList instance. Going further moves into the field of (potential premature) optimizations. But it may be interesting none-the-less to see what can be achieved.

There are many levels of an implementation that can be optimized. At the outermost level, optimizing at architecture level may involve using a fast in-memory database instead of a slower disk-based database. Next, optimizing by picking the most suitable algorithm

Optimizations of a for-loop

Page 9 / 1823June 2008 BLAISE PASCAL 2

3 2005 Win32 200 Win327

Page 10: Blaise Pascal 2 Uk Print Able Download

and data structures can have a profound effect, such as replacing a naïve bubble-sort with a faster quick-sort algorithm. Finally, you can perform optimizations on the function and statement level. Often it does not make sense to perform micro-optimizations before the higher levels of the design have been optimized.With that warning in mind, let's see what kinds of micro-optimizations we can perform on a single for-loop that loops over the contents of a TList. Note that in most loops there will be additional optimizations that can be done, moving all calculations and work that does not change during the loop, outside the loop. We're ignoring that part here, focusing on the loop itself and accessing the TList contents.

Most micro-optimizations relies on knowing the code-generation patterns of the compiler and knowing what language rules inhibit the compiler from generating the most optimal code. For instance, accessing non-local variables, fields and properties inside the loop forces the compiler to call functions or to load values from memory locations. Caching frequently accessed and non-changing variables in local variables allows the compiler to keep them in fast registers instead.For instance, one trick is to cache the value of the TList List property (the raw pointer to the allocated pointer array for the collection) in a local variable, like this:

Only use local variables inside the loop

Actual generated code may differ slightly between versions, but DoOperations2 above (without range checking) yields this assembly code in Delphi 2007 for the two statements inside the loop..mov eax edimov eax eax esicall TMyObject Operation

The slightly optimized version using a local LList variable gives this assembly code:mov eax, esi+ebxcall TMyObject Operation

It is one instruction shorter and has one less memory access. The reason the compiler cannot perform this optimization automatically, is that it cannot guarantee that the value of the List property does not change. Note that in order to use this optimization, we as programmers must make sure that this is safe. For instance, if the code inside the loop (directly or indirectly) changes the contents of the List, the optimization is not safe.

,[ +$ ],[ + * ]

.

[ * ].

044

4

Let the loop run downwardsAnother small detail is that the loop termination check code can be made simpler if the index variable can be checked against 0 instead of some other value. The reason for this is that the Intel processors have simplified combined instruction for checking against 0 and jumping if it is equal (or is not equal). For a for-loop this normally means that we need the loop to go towards 1 instead of 0. The reason for this is that the loop index decrement and check happens at the end of the loop. When the last valid index is 0, it will be 0 after the final decrement.

procedure

var

begin

for to dobegin

endend

DoOperations4 List TList

I integer Item TMyObject LList PPointerList

LList List List i List Count

Item LList i Item Operation

( : );

;;

;

. ; . -

[ ];. ;

;;

// Efficient code // Only use local variables inside loops

0

// Direct array access

:::

:=:=

:=

1

{$R-} {$R+}

procedure

var

begin

for to dobegin

endend

DoOperations4b List TList

I integer Item TMyObject LList PPointerList

LList List.List I 0 List Count Assert(LList List List)

{$R-} Item LList i Item Operation

( : );

: ; : ;: ;

;.

. ;[ ];

. ;;

;

// Efficient code // Let loops count down to 0 (assuming the logic is unaffected)

1

// Direct array access

:=:= -

=:= {$R+}

procedure

var

begin

for downto dobegin

endend

DoOperations6 List TList

LList PPointerList

LList List List i List Count

Item LList i ; Item Operation ;

;

( );

;

. ;

.

[ ]. ;

:

: ; : ;:

:=:=

:= -

// Efficient code // Let loops count down to 0 (assuming the logic is unaffected)

1 // Direct array access

i integer Item TMyObject

{$R-} {$R+}

1

Efficient Pascal – For-loops

The reason is that the internal list array could be reallocated when the collection grows or shrinks and this would make our local cached value invalid. So be careful about not breaking this assumption when performing this optimization. One possible improvement here would be to use an Assert to make sure the cached value has not changed inside the loop:

Again, looking at the loop logic for updating the index variable and the jumping back to the start of the loop, here is what D7 generates for DoOperations2 above:

mov ebx edidec ebxtest ebx ebxjl finc ebxxor esi esi

inc esidec ebxjnz c

Notice that the compiler is still counting down and using the fast JNZ instruction, but it has to update two variables; the actual index variable (here kept in ESI) that counts up from 0 and another internal loop-control variable (in EBX) that counts down to 0. The corresponding code for DoOperations6 looks like this:

mov ebx eaxcmp ebxjl e

dec ebxtest ebx ebxjnz e

// Loop prologue 08 // Get Count

// Calc Count-1//

1 // Skip loop if negative// EBX = Count again// ESI = i = 0

// <-- Loop body goes here// Loop update index/loop variable and jump back to the loop body

// Inc(i)// Dec(EBX)

1 // Jump to the loop body if EBX <> 0

// Loop prologue 08 // i := Count

01 // Compare Count with 10 // Skip loop if Count is less than 1 (i.e. 0)

// <-- Loop body goes here// Loop update index variable and jump back to the loop body

// Dec(i)//

0 // Jump to the loop body if EBX <> 0

,[ +$ ]

,+$

,

-$

,[ +$ ],$

+$

,-$

Here we see that the compiler only has to update a single variable (EBX) instead of two. In addition to smaller, faster code, this gives the compiler another free register to play with and use for other purposes. The Intel architecture is really hampered with too few registers (it is a little better in 64-bit mode), so any register we can free up in performance critical code will help the compiler generate more efficient code. Note that we often cannot change the direction of the loop, because it would change the logical outcome or generate the wrong external side-effects. Don't use Word or Cardinal for the index variableA common mistake when using a for-loop is to declare the loop index variable as an unsigned variable like Word or Cardinal. This can cause a subtle bug to linger in the code. You may test and see that it works fine with a list that has one or more elements. The problem arises when the list is empty. Then the expression Count-1 evaluates to -1 and the attempt to assign a negative value to an unsigned variable will result in a range check error. The bad solution to this problem is to check if Count > 0 before the loop. The best solution is to always use integer for the index variable.

The for-loop is the bread-and-butter of everyday programming, so we sure ensure that we use it correctly and produce readable and efficient code. In later installments we may be looking at other kinds of loops and efficient coding patterns.

Conclusion

The Assert statement would have no code generated for it when you compile the release (or performance test) version with no asserts enabled (in compiler options).

Page 10 / 1824 June 2008 BLAISE PASCAL 2

3 2005 Win32 200 Win327

Page 11: Blaise Pascal 2 Uk Print Able Download

Page 11 / 1825June 2008 BLAISE PASCAL 2

First we get a pointer to the run-time type information (RTTI) of the property we are interested in using the helper function GetPropInfo from the TypInfo unit. In this call we provide our newly declared TScreenEx class, because we know it has the desired PixelsPerInch property published. By using information gleaned from the TypInfo unit about the encoding of the GetProc field, we are enable to get the offset of the backing field for the property.

GetProc is encoded differently for field, normal methods and virtual methods. For fields the most significant byte is always $FF and the remaining three bytes contains the offset of the field from the start of the instance. Then we use the instance variable Screen and add the calculated offset, using a couple of well-placed type casts in the process. Now we have a pointer to the private FPixelsPerInch field inside the Screen instance, and we can change the value simply by de-referencing the pointer and assigning to it.

While this second version of the code is less cryptic than the one-liner we started with, it basically hard-codes the general hack of modifying a read-only property from the specific task of modifying the Screen.PixelsPerInceh property. Let's refactor a bit and tear the two different concerns apart, giving us a reusable RTTI hack routine.

The aptly named SetReadOnlyIntegerProperty takes four parameters;

Parameter DescriptionInstance The object with the read-only property you want to

changeRTTIClass The hack-class with the re-declared published propertyPropName The name of the read-only propertyValue The integer value you want to change the property to

Note that this is specific to integer properties, if you need to change properties of other types you need to write corresponding routines, replacing Integer and PInteger with appropriate types.With this handy helper routine in our belt, it is a piece of cake to re-implement our SetPixelsPerInch routine.

So now you have a tool for the special occasion where you really need to modify a read-only property of a class that you don't have the luxury of modifying the source code for. Use it sparingly! )

Hallvard Vassbotnhas been a professional programmer since 1985 and he is now the Head of Client Development at Infront AS (www.infront.no). You can read Hallvard's blog at hallvards.blogspot.com.

procedureconst string

var

begin

if andand

and thenbegin

and

endend

SetReadOnlyIntegerProperty Instance TObjectRTTIClass TClass PropName Value integer

Offset integer Field PInteger

PropertyRTTI GetPropInfo RTTIClass,PropName Assigned PropertyRTTI PropertyRTTI PropType Kind tkInteger

Integer(PropertyRTTI.GetProc FF

Offset Integer PropertyRTTI GetProc FFFFFF Field PInteger Integer Instance Offset Field Value

( ; ; ; );

; ;

( );( )

( . . )

(( ) ) $ )

( . ) $ ;( ( ) );

; ;

;

: : : :

: ;: :

:=

^^ =

$ =

:=:= +

^ :=

PropertyRTTI PPropInfo

FF

// the property exist// it is an integer property

000000// the reader is a field

000000

00

procedurebegin

end

SetPixelsPerInch Value integer

SetReadOnlyIntegerProperty Screen,TScreenExValue

( : );

( ,' ', );

;PixelsPerInch

Hack #1: Write access to a read-only property

Some time ago I was faced with the task of making our main application behave better systems with different screen resolutions (or rather pixel density, as in pixels per inch). This is the classic Large Font/Small Font problem and getting forms and dialogs to scale properly to show readable fonts and text on all displays. There are several things to keep in mind, some of them are covered here - there are more complications due to MDI windows and Form inheritance. To make my testing easier (and possibly to let the end-user override the default scaling behavior) I decided to let the current screen density (as determined by Screen.PixelsPerInch) be controlled from a setting in the Registry. The built-in Delphi form scaling works reasonably well, and relies on the fact that the form's design-time PixelsPerInch value is different form the run-time Screen.PixelsPerInch value. Now, PixelsPerInch is a read-only, public property of the singleton TScreen class. It is initialized in the TScreen constructor to the number of vertical pixels per inch as returned by the current graphics driver:

For my testing purposes, I wanted to set the value of the PixelsPerInch property without going to the hassle of actually changing my system setup, but to do that I would somehow have to modify the value of the read-only property. Impossible, right? Well, in software, nothing is really impossible. Software is soft, so we can change it . Changing the declaration of TScreen to make the property writeable would work, but as has pointed out, making changes in the interface section of RTL and VCL units can have cascading effects, that are often undesirable. Besides, that would not really qualify as a bona-fide hack - it would have been too easy. Nah, lets do something a little more fun ;-P. PixelsPerInch is only a public property, so there is no RTTI for it. Let's declare a descendent class, that promotes the property to published:

Allen Bauer

Now, since TScreen indirectly inherits from TPersistent, and TPersistent was compiled in the $M+ mode, published properties in our TScreenEx class will have RTTI generated for them. But PixelsPerInch is still a read-only property - and there is no way our TScreenEx can make it writeable, because the backing field FPixelsPerInch is private, not protected, and so is off-limits for us. The cunning thing about the RTTI generated for the TScreenEx.PixelsPerInch property, is that it includes enough information about where to find the backing field in the object instance. Open TypInfo.pas and locate the TPropInfo record that describes the RTTI for each property. Included is the GetProc pointer. For backing fields, this contains the offset off the field in the object instance (sans some flag bits). After decoding this offset and adding it to the base address of the object instance, we now can get a pointer to the backing field and thus modify it - voila write-access! Here is the short version:

That is indeed a cryptic one-liner! Let's expand in into something slightly more readable.

typeclass

publishedpropertyend

TScreenEx TScreen PixelsPerInch

= ( )

;;

DC GetDC FPixelsPerInch GetDeviceCaps DC LOGPIXELSY

:= ( );:= ( , );

0

procedurebegin

and end

SetPixelsPerInch Value integer PInteger Integer Screen

Integer GetPropInfo TScreenEx GetPrc FFFFFF Value

;

( : );( ( )

+ ( ( ( ,‘ '). )$ ))^:= ;

PixelsPerInch00

procedure var

begin

and

end

SetPixelsPerInch Value integer

PropertyRTTI PPropInfo Offset integer PixelsPerInch PInteger

PropertyRTTI GetPropInfo TScreenEx Offset Integer PropertyRTTI GetProc

$00FFFFFF; PixelsPerInch PInteger Integer(Screen Offset PixelsPerInch^ Value

;

( : );

: ;: ; : ;

:= ( , ‘ ');:= ( . )

:= ( )+ );:= ;

PixelsPerInch

3 2005 Win32 200 Win327

Page 12: Blaise Pascal 2 Uk Print Able Download

Page 12 / 1826 June 2008 BLAISE PASCAL 2

Resizing Bitmaps

This article describes how a bitmap can be resized.For this purpose, we use a source bitmap (called sbm) to be resized to a destination bitmap (called dbm).

A Bitmap is a flexible component to store and manipulate pictures.A Bitmap is device independent: it is only a table in memory and must be copied to a paintbox to show its contents to the user.

A digital picture is made of rows and columns of dots, called pixels.

See figure 1, where a pixel is represented by a square. The color of a pixel is defined by a number. So, a picture is a (2) dimensional table of numbers.Several formats exist for this numbers. In this article, we use the 32 bit pixelformat. See figure 2.The number has 3 fields of 8 bits each, representing the intensity of primary colors red, green and blue.Also shown is the Windows internal color format.

If the multiplication factor is f , then :

Also we define :

dbm.width sbm.width f dbm.height sbm.height f.

f1 1 f f2 f f

:= *:= *

= / = *

How it worksPixels of dbm are addressed 1 by 1 from left-top to right-bottom.Each pixel of dbm is projected over sbm.This projection will (partially) cover one or more pixels of sbm.Each (partially) covered pixel of sbm will proportionally contribute to the final color of the destination pixel.See figure 3, where an bitmap is reduced to

To illustrate the process, part of sbm is enlarged, see figure 4.The projection of the addressed dbm pixel is painted in red.In this figure we notice:

8 8 5 5 so f 5 8 0 625.

sy1 f1 y sy2 sy1 f1 sx1 f1 x sx2 sx1 f1

x* , = / = ,

= *= + = *= +

The are “single” type real variables. To calculate the color of the destination pixel , the colors of sbm pixels

must be added together, proportional to the area that is occupied on sbm.

sx1 sy2x y

i j i 1 j i 2 j i,j 1 i 2 j 3

....[ , ]

[ , ], [ + , ], [ + , ],[ + ]...............[ + , + ]

This area is the product where: is the horizontal edge and is the vertical edge of the rectangle

defining the overlap. Notice, that is the total size of the dbm pixel projected on sbm.(a pixel is given dimensions )

For each pixel in sbm , we calculate and .With , variable is the weight factor for the color of pixel[i,j].So, , this color contributes for 20% to the final color of pixel[x,y] in .

dx dydx dy

f1 f1

1 1

[i,j] dx dyf2 = f * f AP = dx * dy * f2

if AP = 0.2 dbm

*

*

*

Initially, the value of the dbm pixelcolor is set to 0.For each i and j we summarize:

This should be repeated 3 times of course, for red, green and blue.

color color pixelcolor i j AP. = + [ , ] *

Adressing pixels in a bitmapTwo ways exist to address pixels in a bitmap:

1: with property of the bitmap's canvas: copies the color

of column 3, row 2 of the picture into variable color

Note, that in this case color has the internal windows format, regardless the format of the data in the bitmap.

This way of working with pixels is very slow, because Windows is called.

pixels color sbm canvas pixels 3 2

[..,..]:= . . [ , ]

Figure 1.

Figure 3.

Figure 4.

Figure 2.

by David Dirkse 3 2005 Win32 200 Win327

Page 13: Blaise Pascal 2 Uk Print Able Download

Page 13 / 1827

2: using the property of the bitmapif we define : TWA 0 2500 LongInt PWA TWA py PWA

py is a pointer to the first element of a (long) array of LongInteger values. py dbm scanline y followed by py x color

copies color to row column .

Note, that color should have the (internal) bitmap format, as Windowsis not called and no conversion takes place. The speed is much, much higher than in case 1, so this way is recommended.

scanline[..]

y x

type array of

var

= [ .. ]= ^:

:= . [ ]

^[ ] :=

,

Calculating dx en dy

thenif then

Manipulating colors

andandand

About the program

Limitations

Initially and are set to , the dimensions of a pixel.

So, if a complete pixel is overlapped, these values are correct.

In cases when pixel boundaries of sbm are crossed or partial pixels are covered, there are two possibilities: left or right (high or low) orientation of the rectangle For dx: Right if sx1 i dx dx sx1 i Left sx2 i , dx dx i – sx2

A similar explanation holds for dy.

is the pointer to the first element of row in .

Color pj i

copies of to variable color.

Note, that color now has the exact format of the data in the bitmap as mentioned before.Unpacking the primary colors into (byte) variables en for blue, green and red :

sB color $ff sG (color shr 8) $ff sR (color shr 16) $ff

Now, we can make calculations with and before packing and copying them to the destination pixel.Please look at the code listing for details.

The language is Delphi, version 7. Procedure “resize” is actually doing the work. Width and height of dbm are calculated according to the sbm dimensions and factor f.Some buttons are added to test the algorithm: : a picture (format *.bpm) can be loaded into sbm from a file. : draws a raster with ellipses in sbm

Two paintboxes, sbox en dbox, show bitmaps sbm en dbm on the screen.Procedure “edge” draws an edge around a paintbox. The edge is actually painted on the canvas of form1, the parent of the paintbox. This is only for esthetical reasons. Please refer to the listing for more details.

The program works fine in case of size reduction. When pictures are enlarged, the results are sometimes coarse. Interpolation would probably yield a smoother result, especially in the case of photographs.Technical drawings and graphics are a different case, because they contain information on an otherwise meaningless background. So, in this case background colors need special treatment (omission). However, this may be the topic of another article.

dx dy 1

dx dy.

1 1

pj j sbm

pixel[i,j] sbm

sB sG sR

sB sG sR

picture drawing

*

: > , := – ( - ): < + := – ( + );

:= ^[ ]

,

:=:=:=

,

Resizing Bitmaps

June 2008 BLAISE PASCAL 2

David DirkseBorn 1945 in Amsterdam, David joined Control Data Corporation in 1968, after a study in electrical engineering. As a hardware engineer, he was responsible for installation and maintenance of mainframes at scientific data centers in the Netherlands.At the decline of CDC around 1990, he started a study of mathematics and became a math teacher. His hobby is programming, in particular educational software, math algorithms and puzzle solving.http://home.hccnet.nl/david.dirkse

3 2005 Win32 200 Win327

There is also a Dutch edition of

If you are interested in the Dutch version please send an email to

and we will assist

you.

First of all you need to decide whether you want:

1 the printed version ,

2 the no paper (download) version, printing enabled and code included.

3 the basic download version,

without code, downloads and printing disabled. The second issue is not free but costs € 10,00.

Any first issue can be downloaded at any time.(If it is your first download.)

Special limited-time offer:

to the “printed version” or “no paper”

download version

You can pay with PayPal or by credit card (Take Two) or by bank. Look for subscription details on page 2

Blaise Pascal Magazine

How to become a subscriber

*

subcribe

*for the first year € 25.00

[email protected]

code included, fully printable version,lectronic version download included;including tax, postage (4 issues = 20,00 euro’s, total € 45,00)You can have your electronic version immediatly whilst the printed issue is on its way.

(you don't have to pay postage, just pay € 25,00).

without

excluded

Page 14: Blaise Pascal 2 Uk Print Able Download

Page 14 / 1828 June 2008 BLAISE PASCAL 2

Edits are always left-justified in Delphi, which isn't so nice with numbers. In Windows, it's possible to make Edits left-justified, centred or right-justified – at least since Windows 98. However, this property is not included in Delphi. Of course, you can create your own component and add this property to it, but it is also possible to add new properties without having to install a component. You can place the code for this in a separate library unit and then use it in any desired Form. To do this, you must include the library unit at the beginning of the program in your 'uses' section. You also have to use the FormCreate event to set the alignment of the Edit(s) to taRightJustify.

There's also a very simple way to make an entry field right-justified. You can use a Memo to imitate an Edit by setting its height to '21' (the standard Edit height), setting WantReturns and WordWrap to 'False', and setting Alignment to 'taRightJustify'. Then empty Lines, and you have a nice pseudo-Edit. I already described this in Blaise 75.

Another approach is to set the BiDiMode property to 'bdRightToLeft'. This property is intended to be used with non-European languages (Arabic, Japanese, etc.) that are written and read from right to left. I don't recommend this approach, because it works on some computers but not on others, depending on which version of Windows is installed.

If you want to use a real Edit instead of a Memo, you have to take a different approach. At first glance it doesn't appear easy – if you look in Windows Help for Delphi, you will see:“There are three styles that cause Windows to align the text in an edit control, ES_LEFT, ES_CENTER, and ES_RIGHT. These styles apply only to multiline edit controls.”Here 'only multiline controls' means that it works with a Memo but not with an Edit. However, this is no longer true, as you can see from the MSDN library, which you can find on the Web at

.This library is so large that you can easily get lost in it, so I have illustrated the path to the Edit styles in Figure 1 (with hundreds of items omitted).

The simple way

Windows MSDN (SDK)

http://msdn2.microsoft.com/en-us/library

This means that you cannot use right justification in Windows 95 or earlier, but you can use it in later versions. Note the second sentence, which says that the Edit style must be declared in the Create and cannot be modified afterward. This means that you must declare the alignment in the FormCreate of the Form containing the Edits.

You can place the code where you declare the alignment, in the unit that contains the Edits. Do this only for testing, since copying the same code to every unit becomes tiresome if you use lots of units. For this reason, it is better to put the code in a separate unit that you can link into the forms that contain the Edits. Now I'll show you how to do this.

Start Delphi, create a new VCL application, and place a couple of Edits on Form1.The library unit does not have to display, so it can be a formless unit. To generate this, select File / New / Unit as shown in Figure 2 (example from Delphi 2007; other versions are slightly different).

Using a library unit

Figure 2. Adding a formless unit for the library unit

You will see an empty framework with the following code:

Unit2;

Here you have to insert the code for assigning right-justified alignment to an Edit. To do this, type the following code in the framework and save it (e.g. as 'EdtBib'):

unitinterfaceimplementationend.

unitinterfaceuses

typeclass

private

protectedprocedure const virtualprocedure var override

publishedproperty read write

end

implementation

procedure var begin

inheritedcase of

oror

endend

procedure constbegin

end

EdtBib

Windows Classes Controls StdCtrls

TAlignEdit TEdit FAlignment TAlignment SetAlignment Value TAlignment CreateParams Params TCreateParams Alignment TAlignment FAlignment

SetAlignment

TAlignEdit CreateParams Params TCreateParams

FAlignment taCenter Params.Style Params.Style ES_CENTER taRightJustify Params Style Params Style ES_RIGHT

TAlignEdit SetAlignment Value TAlignment

FAlignment Value RecreateWndend

;

, , , ;

= ( )

: ;

( : ); ;( : ); ;

:;

;

. ( : );

;

: := ;: . := . ;

;;

. ( : );

:= ;;

;

.

Making right-justified Edits by Henk Schreij

Figure 1. Finding the ES_RIGHT Edit style in the MSDN library

The Edit Control Styles page says:“Windows 98/ME, Windows 2000/XP/Vista: Aligns text in a single-line or multiline edit control. After the control has been created, these styles cannot be modified.”

A “uses” with StdCtrls (the unit in which the Edit is declared) is placed at the beginning of the code. The Windows, Classes and Controls units are also necessary because functions and constants that are used in the subsequent code are declared in these units.

3 2005 Win32 200 Win327

Page 15: Blaise Pascal 2 Uk Print Able Download

Page 15 / 1829June 2008 BLAISE PASCAL 2

If you have ever created a component, the rest of the code should look familiar. Otherwise, just be sure to copy everything exactly. The most important here is the 'Alignment' property. In CreateParams, inherited is used to take over the existing parameters. After this, an “or” is used to add taCenter with the ES_CENTER style (previously seen in the Windows MSDN). The same is done with taRightJustify. These styles tell Windows whether the text should be centred or right-justified.SetAlignment causes the FAlignment field to receive the selected value and invokes redrawing of the Edit with RecreateWnd. This pretty much covers the library unit.

To right-justify a second Edit, set the alignment to 'taRightJustify' in the OnCreate of Form1. The full code (append at 1, 2 and 3) is:

unitinterfaceuses

type class

class

procedure private public end;

var

implementation

procedure

end

end

EdtRechtsU1

Windows Messages SysUtils Variants Classes Graphics Controls Forms Dialogs StdCtrls EdtBib

TEdit TAlignEdit TForm1 TForm Edit1 TEdit Edit2 TEdit FormCreate Sender TObject

Form1 TForm1

TForm1 FormCreate Sender TObjectbegin Edit2 Alignment taRightJustify

;

, , , ,, , , ,, , ;

= ( ); = ( ): ;: ;

( : );

: ;

. ( : );

. := ;;

.

{<--(1)-}

{<--(2)-}

{Private declarations }

{Public declarations }

{$R *.dfm}

{<--(3)-}

At the first arrow (1) you see that the EdtBib unit (with the AlignEdit) is included in the “uses”. At (2) with type, you see that the Edit originates from AlignEdit, so you can use the alignment declared in FormCreate (3).

The Form at design time and run time is shown in Figure 3:

Figure 3. A right-justified Edit at design time and run time

Improving the code

class

A further improvement is possible, which allows you to omit the type declaration at (2). To achieve this, you must put the following code in the library unit, to have an Edit originated from an Edit:

TEdit StdCtrls Edit

You also have to 'revise' the code for the Edit in the library unit at three places, as shown in the following code:

directly

= ( . )

unitinterfaceuses

typeclass

private

protectedprocedure const virtualprocedure var override

publishedproperty read write

end

implementation

procedure varbegin inherited case of

oror

endend

procedure (constbegin

end

end

unitinterfaceuses

typeclass

procedure private public

var

implementation

procedurebegin

end

end

EdtBib

Windows Classes Controls StdCtrls

TEdit StdCtrls TEdit FAlignment TAlignment SetAlignment Value TAlignment CreateParams Params TCreateParams Alignment TAlignment FAlignment

SetAlignment

TEdit CreateParams Params: TCreateParams

FAlignment taCenter Params Style Params Style ES_CENTER taRightJustify Params Style Params Style ES_RIGHT

TEdit SetAlignment Value TAlignment

FAlignment Value RecreateWnd

The declaration of the alignment in Form1 then becomes:

EdtRechtsU1

Windows Messages SysUtils Variants Classes Graphics Controls Forms Dialogs StdCtrls EdtBib

TForm1 (TForm) Edit1 TEdit Edit2 TEdit FormCreate Sender TObject

end;

Form1 TForm1

TForm1 FormCreate Sender TObject

Edit2 Alignment taRightJustify

;

, , , ;

= ( . )

: ;

( : ); ;( : ); ;

: ;

;

. ( );

;

: . := . ;: . := . ;

;;

. : );

:= ;;

;

.

;

, , , ,, , , ,, , ;

=: ;: ;

( : );

: ;

. ( : );

. := ;;

.

{<--(I)-}

{<--(II)-}

{<--(III)-}

{<--(a)-}

{Private declarations }

{Public declarations }

{$R *.dfm}

{<--(b)-}

There is one disadvantage with this approach: it is essential to place the EdtBib in your uses section after StdCtrls (a). Otherwise you will receive an error message with Edit2 (b) saying that the alignment was not recognised. This is why some programmers prefer the previously described solution with AlignEdit.

Right-justification of an Edit in order to display numbers is not implemented in Delphi. As this is actually possible with Windows 98 and later. A library unit is presented containing code where the alignment can be declared. Coding this library unit is not a lot of work if you do it only once, and it is very easy to use.The approach described here shows that you can in fact add properties to an existing component without creating a new component. You can use this approach in other situations as well.

Conclusion

Making right-justified Edits 3 2005 Win32 200 Win327

Page 16: Blaise Pascal 2 Uk Print Able Download

Page 16 / 1830 June 2008 BLAISE PASCAL 2

Delphi 2007 VCL Component Building - II by Bob Swart

Last time, we made a custom TShadingLabel component, and demonstrated how it looks and behaves on a form. However, in the Object Inspector, we noticed that the new properties Offset and LabelStyle are only shown in the Miscellaneous category, but not in any of the other categories.

That will be solved in this article, and we'll also cover the use of packages and how to create the custom component bitmap file.

Delphi offers the ability of grouping properties and events together in special categories. The Object Inspector can actually arrange the properties in two ways: by category or by name.The latter is the view we've been used to since Delphi 1, and lists all properties in an alphabetic order. Including many of the properties and events that you'd seldom use. As of Delphi 5, we can also instruct the Object Inspector to display the properties in a list of categories. As soon as you do this, the list of properties is replaced by a list of property and event categories. It really helps to open up only a single relevant category and work with the properties and events in that category, than to have to look through the entire list of (sometimes more than hundred) properties and events.

As a component developer, we can not only add properties to categories, but also add new categories. The Register procedure, so far only calling RegisterComponents, is also the place to register your new custom properties in categories. We can use the overloaded procedure RegisterPropertyInCategory from the DesignIntf unit (in the DesignIDE package) to register a property in a category.

There are actually four overloaded versions of RegisterPropertyInCategory. The first variation lets you identify the property by the property's name. The following line of code registers a property related to visual display of the component, identifying the property by its name Offset.

RegisterPropertyInCategory

The second variation is much like the first, except that it limits the category to only those properties of the given name that appear on components of a given type.The following line of code registers into the Visual category again a property named Offset of a component of the custom class TShadingLabel.

RegisterPropertyInCategory TShadingLabel

This is actually a safer approach, since a property called Offset might be used by other components, in which case the Visual category is not automatically the best one.

Property Categories

RegisterPropertyInCategory

(' ', ' ');

(' ', , ' ');

Visual Offset

VisualOffset

RegisterPropertyInCategoryTypeInfo TLabelStyle

Although it's probably safe to assume that any use of the TLabelStyle in a property will affect the visualisation of the component, and should hence be placed in the Visual category, a safer approach is the final variation, which uses both the property's type and its name to identify the property. The following line of code registers a property based on a combination of its TLabelStyle type and its LabelStyle name.

RegisterPropertyInCategory TypeInfo TLabelStyle

As a result, the Register procedure contained in the eBob42.Register unit for the TEuro, TMultiLineButton, TRightEdit and TShadingLabel should be modified as follows to ensure that the Offset property in the TShadingLabel component, and the LabelStyle property of type TLabelStyle are both shown in the Visual category in the Object Inspector (note that I've also added the RegisterPropertyInCategory call that will put the MutiLine property of the TMultiLineButton component in the Visual category of the Object Inspector).

(' ', ( ));

(' ',( ), ' ');

Visual

VisualLabelStyle

procedurebegin

end

RegisterComponents TEuro RegisterComponents TMultiLineButton RegisterPropertyInCategory

TMultiLineButton RegisterComponents TRightEdit RegisterComponents TShadingLabel RegisterPropertyInCategory

TShadingLabel RegisterPropertyInCategory

TypeInfo(TLabelStyle);

Register;

(' ', [ ]);(' ', [ ]);

(' ',, ' ');(' ', [ ]);(' ', [ ]);

(' ',, ' ');

(’ ',, ' ');

eBob42eBob42

VisualMultiLineeBob42eBob42

VisualOffset

VisualLabelStyle

The third variation identifies the property using its type rather than its name. The following line of code registers a property based on its TLabelStype type.

Figure 1.

Figure 2.

200 Win327

Page 17: Blaise Pascal 2 Uk Print Able Download

Page 17 / 1831June 2008 BLAISE PASCAL 2

DesignIntf unit and DesignIDE packageLike I also mentioned when we implemented the TMultiLineButton component, the call to the RegisterPropertyInCategory method doesn't compile just yet. We have to add the DesignIntf unit to the uses clause of the eBob42.Register.pas unit.

However, if we do that, then the compiler will complain that it cannot find the DesignIntf.dcu file.

The DesignIntf unit cannot be found on your disk, but is part of the DesignIDE.dcp package (found in the

directory for Delphi 2005 or directory for Delphi 2006 or

for Delphi 2007). In order to resolve the compiler error, we must add the DesignIDE.dcp package to the Requires list of the eBob42 package.

Right-click on the Requires node in the Project Manager, and select Add Reference which results in a dialog where you can locate the DesignIDE.dcp package (depending on your version of Delphi):

C:\Program Files\Borland\BDS\3.0\lib BDS\4.0\lib RAD Studio\5.0\lib

unitinterface

procedure Register

implementationuses

eBob42 Register

;

Classes Controls StdCtrls eBob42 Euro eBob42 MultiLineButton eBob42 RightEdit eBob42 ShadingLabel DesignIntf

. ;

, , ,. ,. ,. ,. ,

;

This will add the DesignIDE.dcp package to the Requires node of the eBob42 package, and will allow the compiler to find the DesignIntf unit.

Although the compiler error is now gone, the solution of adding the DesignIDE package to the Requires list and the DesignIntf unit to the uses clause still mixes design-time and runtime behaviour of the VCL components in one package, which is not a good idea.

If you right-click on the eBob42 package in the Project Manager and select Options, you'll get the Project Options for the eBob42.bpl package, which includes the fact that the package is set to be design-time as well as run-time:

At this time, we've isolated the design-time related code as much as possible in the eBob42.Register.pas unit, but it would be a better idea to split the eBob42 package in a runtime and design-time specific part.

Packages

Design-Time Package

There are three kinds of packages: runtime packages, design-time packages, and hybrid packages that can be used both at runtime and design-time (like our current eBob42 package). The latter should be used with care.

And there are two kinds of package output files: .bpl and .dcp files. The .bpl file is the compiled package that can loaded at runtime (or design-time), while the .dcp file is a collection of all .dcu files that were required to build the package. You need the .dcp file to allow developers to link against your runtime package, unless you want to distrbute all individual .dcu files.

A runtime package is used for code that implements the components – like TEuro, TMultiLineButton, TRightEdit and TShadingLabel. A design-time package is used for design-time support, registering the components, registering properties into categories, etc..Right now, our eBob42 package contains a mix of runtime and design-time code. We should fix that by creating a second package called eBob42.Design which uses the eBob42 package, but only contains the design-time support. The original eBob42 package can then be turned into a runtime only package.

The reason why we haven't had to concern ourselves with this up until this point is the fact that by default a Delphi package is both a runtime and a design-time package, as we saw when we looked at the Project Options dialog for the eBob42 package. This may be handy when starting to develop components, but not good when you want to deploy them (since it would mean using design-time supporting code at runtime, which is really not needed at all).

So, let's try to clear up the issue by adding another package to the project group. Go to the Project Manager again, right-click on the ProjectGroup node, and do Add New Project to give you the Object Repository. In the Delphi Projects category, double-click on the Package icon:

Delphi 2007 VCL Component Building - II

Figure 3.

Figure 4.

Figure 5.

200 Win327

Page 18: Blaise Pascal 2 Uk Print Able Download

Page 18 / 1832

This will add a new package project to the ProjectGroup, with a default name of Package1. Rename this package project to

, placing it in the same directory as the original eBob42 package.

In order to let the eBob42 packagecompile with the DesignIntf unit inthe uses clause (to support propertycategories), we had to add the DesignIDE package to the Requireslist. Because the eBob42 packagewill become the runtime package, we need to remove the DesignIDE package from the Requires list again, and instead add it to the Requires list of the eBob42.Design package.

We should also add the eBob42 package to the Requires list of the eBob42.Design package, since the design-time package must use the runtime package (which contains the components that will be registered by the design-time package). Note that the Requires list contains the .dcp files.

The .bpl and .dcp files for custom packages like eBob42 can be found in the Borland Studio Projects\Bpl directory under My Documents.

We must also mark the eBob42.Design package as a design-time only package. Make sure it's the active project in the Project Manager, and do Project | Options to get the Project Options dialog for eBob42.Design. Check the “Designtime only” usage option, and feel free to enter a Description for the design-time package as well. Close the dialog when you're done.

eBob42.Design.bdsproj

Apart from the designide.dcp and eBob42.dcp packages, the design-time package eBob42.Design should get the eBob42.Register unit to contain the component and property category registration code.

If you compile the eBob42 runtime package again, you will get a notification message from the Delphi IDE, telling you that the package eBob42 is no longer installed (as design-time package), since it's not a design time package anymore.After that, you also will get a notification message that the registered VCL components are also no longer registered.

They will be re-registered as soon as we install the eBob42.Design package again, of course.

The Project Manager should show the eBob42.bpl runtime and the eBob42.Design.bpl design-time packages with their contents.

Project Manager

Obviously, we have to install the eBob42.Design.bpl package in order to add the four VCL components and their design-time support to the Delphi IDE again.We can right-click on eBob42.Design and select Install as a quick way to do so. This will give us a messagebox to inform us of the fact that TEuro, TMultiLineButton, TRightEdit and TShadingLabel have been installed again.

Once the VCL components are installed again, we can place a TMultiLineButton ot TShadingLabel component on a VCL form to verify that the properties are now correctly categorised (for example the MultiLine, Offset or LabelStyle properties).For the LabelStyle property, we'll see the Visual category being used, and no longer the Miscellaneous category. Also note the fact that the lsLowered value is not in boldfact but in normal font, to indicate that this is the original (default) value of the property.

There are a few miscellaneous component building techniques that need to be covered here (see the on-line help for more details).

Miscellaneous

Runtime PackageReturning to the eBob42 package, we have to remove the eBob42.Register unit from the Contains list. This will ensure that no components are registered in this runtime only package, so it only contains runtime code. As last step, we have to mark the package as runtime only, using the Project Options dialog again.

Delphi 2007 VCL Component Building - II

Figure 7.

Figure 6.

Figure 7.

Figure 8.

200 Win327

Page 19: Blaise Pascal 2 Uk Print Able Download

Page 19 / 1833June 2008 BLAISE PASCAL 2

First of all, we can use ComponentState to allow different behaviour of the component at design time and runtime, by checking if csDesigning is in the ComponentState set.

The Loaded method is called after all properties are streamed in, to cater for the fact that properties will come in some (perhaps inappropriate) order. Consider a TTable - maybe the TableName property is read in, then the Active property. If the DatabaseName property hasn't been read in, then the SetActive property will blow up with an exception. However since it is still be read in (another ComponentState set element), the table is not opened till Loaded. This is just an example tp illustrate the point (while the actual TTable implementation may differ, the use of the Loaded method will be helpful in similar situations).

Notification and FreeNotification allow a component to set a component reference to nil when that component gets destroyed, rather than leaving a dangling pointer. Consider a TDataSource's DataSet property. The underlying field would remain non-nil when the DataSet is destroyed if it weren't for Notification. Notification is automatically called for components owned by the same owner as the destroyed item. FreeNotification allows other things which aren't owned by the same owner (ie aren't on the same form or data module) to also work (linking across forms)

Now that we've designed and implemented new components, we may want to give each one of them a unique palette bitmap. Every component needs a bitmap to represent itself on the Tool Palette. If a component does not have a bitmap specified, Delphi uses the bitmap of the ancestor (back to TComponent itself, if necessary).

Remember that two of our new VCL component classes (TMultiLineButton and TShadingLabel) contain existing component bitmaps inherited from their ancestor class, while the other two component classes (TEuro and TRightEdit) are using the default component bitmap from the TComponent base class. While the TShadingLabel and TMultiLineButton have the same bitmap as their parent, TLabel and TButton, these bitmaps don't represent the new feature of these two new components. And TEuro and TRightEdit only show the default bitmap.

A palette bitmap for a component is easy to create: all we need to do is to make a Windows (compiled) resource file with a 24x24 bitmap. You can use any resource editor you want, including the Image Editor available in the Tools menu of the Delphi 2005 IDE (but which is no longer part of the Tools menu in Delphi 2006 or 2007 – if you do not have a copy of imagedit.exe from Delphi 2005, you will have to find another resource editor instead).

Do Tools | Image Editor from the Delphi 2005 IDE to start the Image Editor. Then, do File | New – Component Resource File (.dcr), which will result in an Untitled1.dcr project. We then need to add a new bitmap, using Resource | New – Bitmap, and specify a 24x24 pixel and 16 colour bitmap:

Palette Bitmaps

This will result in a little Treeview for the Untitled1.dcr file, with Contents, Bitmap and Bitmap1 as leaf node.You need to use a name similar to the unit that contains the Register procedure, which is eBob42.Register.pas, so the .dcr file should be saved in eBob42.Register.dcr in order to allow Delphi to automatically use the bitmaps inside.You need to rename Bitmap1 and give it the same name as one of

Note that the colour in the lower left corner pixel is usually considered the invisible colour.When you're finished, save the eBob42.Register.dcr file. In order to enforce the compiler to pick it up, you can remove the eBob42.Register.pas unit from the eBob42.Design package, and re-add it in order to add both the eBob42.Register.dcr and eBob42.Register.pas files to the Contains node.Warning: this will not update the component bitmap files right away. You have to restart Delphi 2005 (and sometimes even log out and back into Windows). After that, the new component bitmap are shown correctly in the Tool Palette.

When everything has been done right, then the TEuro, TMultiLineButton, TRightEdit and TShadingLabel custom components can appear with their own custom bitmaps in the Tool Palette (note in the screenshot on the next page, only the TEuro and TRightEdit use custom bitmaps, the TMultiLineButton and TShadingLabel still use their inherited bitmap).

SummaryIn this article, I've covered property categories, run-time and design-time packages, and demonstrated how to create the custom component bitmap file. We've now completed the coverage of a simple component, but there are more IDE support capabilities, including property and component editors that will be covered next time.For more information about Delphi Custom Component Development, check out my 175-page courseware manual “Delphi Win32 / .NET Component Development” available from Lulu.com for 30 Euro (printed) or 24 Euro (download), see

for more details.

http://stores.lulu.com/drbob42

Delphi 2007 VCL Component Building - II

the components that are registered in eBob42.Register.pas. For the TRightEdit component that's TRIGHTEDIT, and for the TEuro component that's TEURO, etc.. It's recommended to place all component bitmaps in one .dcr file), as long as they are all 24x24 in size using 16-colors.

Figure 9.

Figure 11.

Figure 10.

200 Win327

Page 20: Blaise Pascal 2 Uk Print Able Download

Page 20 /1834 June 2008 BLAISE PASCAL 2

ClientDataSet Filtering by Martin de Bont

Working with client datasets often requires some sort of filtering. This time I'm going to create a generic class to do just that on the fly. For this purpose I'm going to create a few classes (TFilterList and TFilterItem) together with a small program to demonstrate how it works. This demo is a .Net program.

In this program I make use of a text file holding the names of the countries in the world with their associate capital cities, number of inhabitants and the region in the world where the countries reside in. I admit it is not the most challenging data but it will do for now. This file is small, not up-to-date and is named WorldCountries.csv This file will be imported after pressing a button.Before I begin jotting down the code I will give you a preview of the final result of my 'hard' work.

TFilterItemTFilterItem Key Value QuickExpr Boolean

Create(AKey ValueQuickExpression Boolean)

TFilterItem Create AKey AValue ; QuickExpression Boolean

Create Key Akey Value AValue QuickExpr QuickExpression

=: ;: ;: ;

: ; : ; : ;

;

. ( , :: );

;:= ;:= ; := ;

;

classStringString

public constructor String String

endimplementation

constructor String

begin inherited

end

{ TFilterItem }

The first two parameters of the constructor will hold a key and its value, the last parameter needs some extra explaining. There are two places where a filter expression can come from. It is either a value coming from a data grid cell, or it is value coming from a dialog box.If it is coming from a dialog box then QuickExpr is True, False otherwise. The purpose of QuickExpr is telling the TFilterList class how to display the filter expression (TFilterList.Text). Nothing more.

TFilterList

TFilterList TObjectList FDataSet TDataSet FFilterCallBack TFilterCallBack SetDataSet Value TDataSet SetFilterCallBack Value TFilterCallBack

Create ActivateFilter Add AItem TFilterItem ; RemoveFilter RemoveLastExpression GetItem i Integer TFilterItem GetItem s TFilterItem Remove AKey ) Integer Text DataSet TDataSet FDataSet SetDataSet FilterCallBack TFilterCallBack

FFilterCallBack SetFilterCallBack ;

= ( )

: ;: ;

( : );( : );

;;

( : );;

;( : ): ; ;( : ): ; ;

( : : ; ;:

: ;:

;

classprivate

procedure const procedure const

public constructor

procedure procedure reintroduceprocedure procedure function overloadfunction String overloadfunction String reintroducefunction Stringproperty read writeproperty read

writeend

As you can see this class contains a few more fields and methods and two properties. For less experienced programmers let me first explain the 'overload' and 'reintroduce' keywords written behind some of these methods. The keyword 'overload' means that you are using methods (functions / procedures) with the same name but with different number and/or type of parameters. The keyword 'reintroduce' means that you are using a method that is already existing in the parent class you're inheriting from that you want to overwrite with code of your own (for consistency reasons).Using properties is a way to call methods by assigning values to that property just the way you assing values to variables. If you assign a value to a property the program will actually fire a procedure connected to this property. There are two methods belonging to a

property. The Get (read) and the Set (write) method. Leaving out one of these will make the property either read-only or write-only.I expect you to let Delphi do as much work as possible. After you have keyed in the class definition, press <Shift><Control>C and Delphi will write all the stubs for you. Now you only have to write the additional code yourself.Reading through the code of which I assume you downloaded a second a go, will explains itself mostly. The property FilterCallBack is of type TFilterCallBack which is defined as:TFilterCallBack = procedure(msg: string) of object;You can assign any method to this property as long as this method has the correct number and type of parameters. In the demo-program you will see the following code snippet:

The two classes will be put in one unit (ucFilter) purely for my convenience. Good programming practice is creating a unit for every single class, then again good programmers are lazy and do as litle as possible. Having that said does not mean that I'm a good programmer. Just a lazy one. The demo will be put in unit (ufMain).

I will start with the two classes.The TFilterList class is basically a list with objects and is descending from TObjectList. In this case it will hold objects of type TfilterItem, which is a simple class with only 3 fields and one constructor.

Figure 1 : In this case I selected all countries in Africawith less than 500,000 inhabitants

Figure 2.

2005 Win32 200 Win327

Page 21: Blaise Pascal 2 Uk Print Able Download

Page 21 / 1835June 2008 BLAISE PASCAL 2

Binary heapsQuickly finding the largest item in a collection of items

When you mention heap people automatically think of memory allocation. A binary heap is not that kind of heap. It's a quite remarkable and simple data structure that has great power. It is a container of objects into which you can add objects and from which you can easily and quickly pull out the largest object, and do both operations very quickly.

It seems that a binary heap is one of the best kept secrets in computer science. Oh sure, people have heard of stacks and queues, binary trees, hash tables, and will argue about the merits of a red-black tree versus an AVL tree, but when you mention heap people automatically think of memory allocation and deallocation and where objects come from, fully formed.

A binary heap is not that kind of heap. It's a quite remarkable and simple data structure that has great power. It is a container of objects into which you can add objects and from which you can easily and quickly pull out the largest object. A simple change to the implementation of the container will enable you to pull out the smallest object instead.From this rather trivial sounding data structure, we can get a simple, yet very fast, sorting algorithm, we can maintain a list of prioritized tasks, to even manage chunks of reusable memory. When talking about a data structures in the abstract, we're concerned about the operations we want to perform on that structure, how quickly we want certain operations to run (because we use them a lot), whether we're concerned about the speed of other operations, and so on. So, for example, with the stack structure, we want very fast Push and Pop operations since those are the two operations we shall be performing the most. Counting the number of items in a stack may be a "lesser" operation: maybe we're not that interested in doing it all that often. Another property of abstract data structures may be the efficiency with which it uses memory. How much overhead is there in creating such a data structure? So for example, implementing a stack as a linked list means that we have overhead for each node in the list, but implementing it in an array-like structure will only have the array's overhead. Another consideration on modern architectures is locality of reference. How close together are all the memory allocations that make up the data structure? The closer they are, the less likely we'll suffer a page fault -- that memory will be swapped out -- when using the data structure.

With a binary heap, there are two operations we're really interested in: adding a new item to the heap -- call this the method -- and removing the largest item from the heap -- call this

. We should optimize performance for these two operations. In doing this, we'll also make the broad statement that we'd like to use the minimum amount of memory we can.

There are of course other operations we could ask for. , for example, might be a method that removes any item in the heap. If we are to have that, we should presumably have or

(or both) to determine whether a particular item is in the heap and optionally return it. Possibly, we might want

as well. And so on. My overall point here is that as we add more operations we're going to make the implementation more and more complex, and, for a binary heap, the standard two operations will produce a very simple implementation with good characteristics.

Another question we have to answer is this:how quickly is quickly? The faster we want an operation, the more trade-offs there will be. For this particular implementation, we'll state that inserting an item and removing the maximum should be

. That is, the time taken for each of these operations should be proportional to the logarithm of the number of items in the heap, with as low a constant of proportionality as we can muster.

Insert()

RemoveMaximum()

Remove()

Contains() Find()

RemoveMinimum()

O(log(n))

Julian Bucknall

FFilter.FilterCallBack DisplayFilter

Here the callback method DisplayFilter is assigned to the property FilterCallBack. Every time the filter changes a call is made to this method, updating (in this case) the current filter expression.

To make use of this filter class you must include the unit in the main uses section of your program.Declare a private field in the Tform1 to hold the filter list.

FFilter: TFilterList;

Create the filter list and let it point to the client dataset. Install the callback function.

:= ;

private

// Create filterlist

// Connect filter list to the dataset

// Install callback function

FFilter := TFilterList.Create;

FFilter.DataSet := ClientDataSet1; FFilter.FilterCallBack := DisplayFilter;Next, we have to create methods to communicate with this filter list:- AddToFilter - AddInputValueToFilter- ClearFilters- RemoveLastFilter and- DisplayFilter

AddToFilter will add the value of the datagrid cell under the cursor.AddInputValueToFilter will show a dialogbox where you can enter you condition for the column the cursor is in.ClearFilters will remove all filter expressions and will show all data in the dataset.RemoveLastExpression will remove the filter expression you added as last.DisplayFilter will show the complete filter expression.

I have left much room for enhancements and hope it is useful for you. Feel free to experiment with these classes and have fun!

ClientDataSet Filtering

Figure 3.

Martin De Bontstarted programming with Delphi 1 and is ever since a Delphi adept. Having changed to .Net, C#, and PHP as professional, is still using his knowledge for the community writes many articles for us. Any correspondence or questions you can address to:[email protected]

2005 Win32 200 Win327

2005 Win32 200 Win327

Page 22: Blaise Pascal 2 Uk Print Able Download

Page 22 / 1836 June 2008 BLAISE PASCAL 2

remove maximum

move last item

compare itemsswap g and n

compare items swap g and x

There are four levels, the topmost three are full, and the bottom level is left-complete. A new node that is inserted would have to occupy the left child of the b node (fairly obviously, there would be some tree rearrangements to do).Identifying the largest item in the binary heap is easy: it's the root of the tree. Removing it though in RemoveMaximum() is problematic since deleting the node gives us two halves of a tree, which is pretty useless. So we have to patch up the tree somehow so that the heap properties are satisfied again. Since we know how the structure of the heap should look if there were one fewer node, we just move the last node of the last level (the rightmost) to the root of the tree. The structure (that is, rules 2 and 3) is now valid again, but rule 1 is likely to be invalid since we're moving a small item from the bottom of the tree to the top. So let's fix rule 1 up again. We use an algorithm called trickle-down. Look at the two children of the new root. Select the larger item and if it is larger than that at the root, swap it with the item at the root. The root now obeys rule 1. Move down to the child node that participated in the swap, and perform the same operation. Select the larger child item and swap it with the item if it is greater. Continue moving down the tree until the node we reach no longer has any children or until the item in the node is larger than both its children.

And how fast is Insert()? Again, assuming that adding the actual node does not depend on the number of nodes present, all the action is with the bubble-up process. If we assume worst-case again, the item may have to bubble all the way up to the root, through log(n) levels. So we can state that Insert() will also take log(n) time. (This time we only need to do one comparison per level, so we can say that Insert() will be roughly twice as fast as RemoveMaximum().)Is there any way we can improve the speed of RemoveMaximum() so that it approaches the speed of Insert()? Actually there is a simple tweak we can do that in the general case will improve the performance of the remove operation. Consider: when we remove the largest item, we replace it with an item on the lowest level, the rightmost one on that level. Think about that for a moment. It's very likely that the item we're swapping to the root of the tree is one of the smallest in the binary heap.Figure 2 shows this trickle-down process, step by step, as we remove

z, the maximum, from figure 1 and replace it with the g.

Binary heaps Quickly finding the largest item in a collection of items

Figure 3 shows this bubble-up process, step by step, as we add the z back in.

compare, swap m and z

compare, swap x and z

add z as new node

compare, swap k and z

2005 Win32 200 Win327

A binary heap is such a structure. A binary heap is a binary tree such that:1. For every node in the tree, the item in the node is larger than the

items in its children.2. Every level in the tree, apart from the last, is complete.3. All nodes in the lowest level of the tree are to the left. The last

level is filled from the left to the right. This is known as leftcomplete.

Figure 1 shows such a binary heap.

Now, how quick was the RemoveMaximum() operation? The initial removal of the largest item and moving the last item to the root were simple constant time operations, they didn't depend on the number of items. (We'll see later how to identify the last node immediately.) The main time spent in the operation was undoubtedly the trickle-down process. In a worst case scenario we'll have to trickle-down all the way to the bottom level. How far is that? The number of levels in a complete binary tree such as we have with a binary heap is log(n). So the time taken by RemoveMaximum() is going to be proportional to log(n). (Note that at each level we have to do at least two comparisons and that, in general, it's the comparisons that take the time.)Let's look at Insert() now. We know how to insert the node in order to solve the structure rules: add it as the last node on the lowest level (or start a new level, if the last level is already full). But again rule 1 will probably need fixing up. This time we use an algorithm called bubble-up. Look at the parent of the newly inserted item. If it is smaller, swap it and the new item, and then move up the tree. Repeat the same process at this higher level. Continue until either you reach the root, or until the item at the parent of the current node is greater than the item we're bubbling up.

Page 23: Blaise Pascal 2 Uk Print Able Download

typeinterface

function function

end

IPriority GetThis TObject CompareTo(p IPriority) integer

= : ;

: : ;;

procedurevar

begin

1end

procedurevar

begin

while do begin

if then begin

end else

end;

end;

TBinaryHeap Insert item TObject priority IPriority

tuple TTuple

tuple TTuple Create item priority FItems.Add tuple BubbleUp FItems.Count

;

TBinaryHeap BubbleUp fromIndex integer

parentIndex integer item TTuple parent TTuple

item TTuple FItems fromIndex parentIndex GetParent fromIndex (parentIndex parent TTuple FItems[parentIndex item.Priority CompareTo(parent Priority FItems fromIndex FItems parentIndex fromIndex parentIndex parentIndex GetParent fromIndex

parentIndex FItems[fromIndex] item

. ( : ; : );

: ;

:= . ( , );( ); ( - );

. ( : );

: ;: ; : ;

:= ( [ ]);:= ( );

> ):= ( ]);

( . . ) > )[ ] := [ ];

:= ;:= ( );

:= ;

:= ;

0

0

0

typeclass

private

functionfunctionprocedure procedureprocedure

publicconstructordestructor override

procedure function

end

constructor begin

inherited nil

end

destructorbegin if then begin

end inheritedend

procedure var

beginfor to do begin

nil

end;

end

TBinaryHeap

FItems TList

GetParent index integer integer GetFirstChild index integer integer BubbleUp(fromIndex integer TrickleDown Clear Create Destroy

Insert item TObject priority IPriority RemoveMaximum TObject

TBinaryHeap Create

Create FItems TList.Create FItems Add( )

;

TBinaryHeap Destroy

Assigned FItems Clear FItems Free

TBinaryHeap Clear

i Integer tuple TTuple

i FItems Count tuple TTuple FItems i tuple Priority tuple Item Free FItems Clear

=

: ;

( : ) : ;( : ) : ;

: );;

;

;; ;

( : ; : );: ;

;

. ;

;:= ; . ;

. ;

( );. ;

;;

;

. ;

: ; : ;

:= . -:= ( [ ]);

. := ;

. . ;

. ;;

1 1

If you notice, the Clear() method makes use of a type called TTuple. This is merely an aggregate of an item with its priority. Time for the Insert()and the BubbleUp() methods. We'll separate them since the RemoveMaximum() method will eventually make use of the latter. Note in the Insert() method that we make use of the list's Add() method to add the new item.

Page 23 / 1837June 2008 BLAISE PASCAL 2

That's why it's on the bottom level, after all. So, it's very likely that it will return to the bottom level, or at least close to it. The tweak we'll discuss makes use of that fact by altering the trickle-down process to something more like the bubble-up process.

Since the item is likely to be small, we shall swap it with the larger of its children every time until we get to the bottom level. In other words, instead of also checking whether the larger child is also larger than the item, we'll assume that it is so and in the process avoid one of the comparisons at every position.

Of course, we may overshoot in this tweaked trickle-down and bring the item lower than it should be. No problem: we'll merely bubble-up the item from where it ends up. Because it's one of the smallest items in the tree anyway, it's likely that we may not need to do much bubbling up. Certainly we shall avoid many of the comparisons using this tweaked process than with the original that does a double-compare at every step.

Now that we have an optimized pair of operations, let's think about the in-memory representation of this data structure. The first, most obvious, solution is to mimic the abstract tree: declare a node type with links to one parent and two children and a reference to an item. That's a lot of overhead: three references to other nodes. Can we do better?

Consider this. Number all the nodes from the root, level by level, from left to right on each level. So the root is node 1, its children are nodes 2 and 3, their children are 4 and 5, and then 6 and 7. (Figure 1 shows these node numbers.) The next level has nodes numbered from 8 to 15, and so on. Notice that, because of the definition of a binary tree (rules 2 and 3, in particular), there are no gaps in this numbering sequence. In fact we could use an array to hold the items. There is still an issue to solve though. We need to find the parent and children of a "node". Look closely at the numbering and you'll see a pattern. The children of node x are at 2x and 2x+1, and the parent is at node x/2 (using integer division, so the remainder is discarded).

Since, in most programming languages, array elements are numbered starting at 0 instead of 1 we could either modify these formulas accordingly (children at 2x+1 and at 2x+2, parent at (x-1)/2, all of which are slightly less understandable), or we could just ignore the element at position 0 (if you like, it becomes part of the overhead). We'll use the "ignore element 0" version for this implementation.

Now that we have discussed both the performance and the memory storage aspects of a binary heap, we can turn to the code.

First thing to realize is that the items need to be comparable, or, better that there is some extra information (call it a priority in honor of the primary use of a binary heap) that is comparable. We have a choice here: either make the priorities themselves comparable (which is the OOP way, if you will) or we can declare a procedure type that compares two priorities, and then pass an instance of that type to the binary heap. In this article, I'll take the first approach, but will use interfaces to declare the comparison method.

Now we can declare the class. It'll have an internal TList to hold the heap (this means we can use the capabilities of TList to grow the internal array, should we need to), and so the constructor and destructor will have to be declared to create and destroy the list. In the constructor, we add the dummy element 0.

Although BubbleUp() looks complicated, it's not particularly. We make a copy of the item being bubbled up, and then enter a loop to do the actual bubbling up. We don't save the item back into the list until we've found its rightful position and exited the loop.Moving along, we should now add the RemoveMaximum() method. This method takes out the item at element 1, moves the item at the end of the list to the front, and then deletes the element at the end of the list. It then calls the TrickleDown() method to move this top item down the tree.

Binary heaps Quickly finding the largest item in a collection of items 2005 Win32 200 Win327

Page 24: Blaise Pascal 2 Uk Print Able Download

functionbegin

if then beginnil

end

if then

end

TBinaryHeap RemoveMaximum TObject

FItems.Count Result Exit

Result TTuple FItems Item

FItems FItems Last FItems Delete(FItems Count FItems Count TrickleDown

. : ;

( = ):= ;

;;

:= ( [ ]). ;

[ ] := . ;. . - );

( . > );

;

1

1

11

1

Note that there are a couple of special cases: first, there is no item to remove (we merely return nil); second, we remove the only item and so there's no need to trickle down.

Finally, it's the turn of method. This uses the tweaked algorithm to quickly move the item down the list, and then calls the BubbleUp method to make sure it wasn't moved down too far.

TrickleDown()

procedurevar

begin

while do begin

if then begin

ifthen begin

end else begin

end end else begin

end

end;

end

TBinaryHeap TrickleDown

index integer firstChildIndex integer secondChildIndex integer item TTuple firstChild TTuple secondChild TTuple

item TTuple(FItems index firstChildIndex GetFirstChild index firstChildIndex FItems.Count secondChildIndex firstChildIndex secondChildIndex FItems Count firstChild TTuple(FItems firstChildIndex secondChild TTuple(FItems secondChildIndex firstChild Priority CompareTo(secondChild Priority

FItems index FItems firstChildIndex index firstChildIndex

FItems index FItems[secondChildIndex index secondChildIndex

FItems index FItems[firstChildIndex] index firstChildIndex firstChildIndex GetFirstChild index FItems index item BubbleUp index

. ;

: ;: ;: ;

: ;: ;: ;

:= [ ]);:= ;

:= ( );( < )

:= + ; ( < . )

:= [ ]);:= [ ]);

( . . . )>= )

[ ] := [ ];:= ;

[ ] := ];:= ;

;

[ ] := ;:= ;

;:= ( );

[ ] := ;( );

;

11

1

0

Julian M. Bucknall has worked for companies ranging from TurboPower to Microsoft and is now Chief Technology Officer for Developer Express.http://www.devexpress.com his own site http://www.boyet.com/one of his books: Tomes of Delphi: algorithms and data structures is available again. In next issue of Blaise Pascal Magazine there will be a review by Frans Doove.

This code is complicated a little bit by the fact that the current node could only have one child. We test for a child being present by checking that its index is within the list. Again, we make use of the trick from BubbleUp: make a copy of the item, and then only set it back into the list at the very end.The class is now complete and can now be used as a delegate inside something like a priority queue class.

Page 24 / 1838 June 2008 BLAISE PASCAL 2

Binary heaps Quickly finding the largest item in a collection of items 2005 Win32 200 Win327

Page 25: Blaise Pascal 2 Uk Print Able Download

Page 25 / 1839June 2008 BLAISE PASCAL 2

IntraWeb 9.x and AJAX

IntraWeb version 9 introduced full AJAX support to IntraWeb developers. A large number of visible IW controls now have OnAsync events that fire asynchronous and can be used to update certain parts of your page without refreshing the entire page. Note however, that the session counter is still increased! So now more than ever, the use of the Back button is prohibited!

AJAX is not really a new invention, but stands for Asynchronous Javascripting And XML. Fortunately for IntraWeb developers, you really do not have to know a lot about either JavaScript or XML in order to use AJAX. What it comes down to is that an AJAX event is happening asynchronously, without the need to send a complete request or the need to refresh the entire page. This means only a partial request will be made, and a part of the page will be refreshed, resulting in a more responsive and generally more pleasant user experience.IntraWeb supports AJAX events in a number of IntraWeb components through the OnAsync events and – if present – the SubmitOnAscynEvent property (by default set to True).

The power of AJAX is brought to us through the ease of the OnAsync event handler. For example, the component has the and event handlers that we can implement using normal Delphi code.As a simple example, place a , and two

on an IntraWeb Application Form.

AJAX = Asynchronous

OnAsync

TIWButton OnAsyncClick OnAsyncDoubleClick

TIWListbox TIWEdit TIWButtons

One button has a caption of Click, and implements the normal OnClick event, while the other is given a Caption of AJAX, and implements the OnAsyncClick event:

If we click on the AJAX button, then the contents of the IWEdit will again be added to the IWListbox, but there will be no full request to the server. As a result, the session counter in the browser will stick at 1, but at the server it's already at 2.

We can prove this, by clicking on the Click button again, which will send a full request to the server, and add the text to the listbox once again, but also returns with the session counter of 3 (and not 2, since it already was 2 after the AJAX event).

OnAsync EventsNot all components from the IW Standard category support OnAsync events.

The control supports 4 AJAX events: and .

The and controls support 12 AJAX events:

and .

and support 14 AJAX events:

and .

The and controls support 13 AJAX events:

and .

, and support 6 AJAX events:

.

The control supports 6 AJAX events:

. supports only one AJAX event: .

TIWButton

TIWCheckBox TIWRadioButton

TIWComboBox, TIWListBox TIWMemo

TIWEdit TIWTimeEdit

TIWImage TIWImageFile TIWImageButton

TIWLabel

TIWLink

OnAsyncClick, OnAsyncDoubleClick, OnAsyncEnter OnAsyncExit

OnAsyncChange, OnAsyncClick, OnAsyncEnter, OnAsyncExit, OnAsyncKeyDown, OnAsyncKeyPress, OnAsyncKeyUp, OnAsyncMouseDown, OnAsyncMouseMove, OnAsyncMouseOut, OnAsyncMouseOver, OnAsyncMouseUp

OnAsyncChange, OnAsyncClick, OnAsyncDoubleClick, OnAsyncEnter, OnAsyncExit, OnAsyncKeyDown, OnAsyncKeyPress, OnAsyncKeyUp, OnAsyncMouseDown, OnAsyncMouseMove, OnAsyncMouseOut, OnAsyncMouseOver, OnAsyncMouseUp OnAsyncSelect

OnAsyncChange, OnAsyncClick, OnAsyncDoubleClick, OnAsyncEnter, OnAsyncExit, OnAsyncKeyDown, OnAsyncKeyPress, OnAsyncKeyUp, OnAsyncMouseDown, OnAsyncMouseMove, OnAsyncMouseOut, OnAsyncMouseOver, OnAsyncMouseUp

OnAsyncClick, OnAsyncMouseDown, OnAsyncMouseMove, OnAsyncMouseOut, OnAsyncMouseOver, and OnAsyncMouseUp

OnAsyncClick, OnAsyncMouseDown, OnAsyncMouseMove, OnAsyncMouseOut, OnAsyncMouseOver, and OnAsyncMouseUp

OnAsyncClick

The control supports only one AJAX event: .

The supports only one AJAX event: .

TIWTimer

TIWTabControl

OnAsyncTimer

OnAsyncChange

procedurebegin

end

procedure

begin

end

TIWForm1 IWButton1Click Sender:TObject

IWListbox1 Items Add IWEdit1 Text;

TIWForm1 IWButton2AsyncClick Sender TObject EventParams: TStringList

IWListbox1.Items.Add(IWEdit1.Text);

. ( );

. . ( . )

. ( : ;);

If we now enter “Delphi and AJAX” and click on the Click button, the listbox will contain the string “Delphi and AJAX” and the session counter will have the value “1” (right after the EXEC part of the URL):

by Bob Swart

Figure 1.

Figure 2.

Figure 3.

Figure 4.

For the components in the category a similar distribution of events exists. Note that the

and do not support any, however.

The components in the IW Standard 3.2 or IW Data 3.2 also do not support OnAsync events (due to the lack of the support inside the HTML 3.2 browser).

IW Data Controls

TIWDBNavigator TIWDBGrid

XMLHttpRequest

OnAsync

OnAsync events

2005 Win32 200 Win327

Page 26: Blaise Pascal 2 Uk Print Able Download

Page 26 / 1840 June 2008 BLAISE PASCAL 2

EventParams

procedure

beginend

All OnAsync events have the following signature:

TIWForm IWControl1AsyncXXX Sender TObject EventParams: TStringList

;

. ( : ;);

This means that all information will be passed to the event handler inside the EventParams argument. The TStringList contains name=value pairs, including in all cases the callback (the name of the event called) and often also a x and y coordinate, a which value (the key or mouse button pressed) and optionally modifiers.The following table shows the different name=value pairs that are passed inside the EventParams for the different OnAsync events. Note that this list may change in different versions of IntraWeb.

When I write IWCONTROLNAME= this means that the complete text value of the control, or the selected index is given as value for the name of the control (like IWEDIT1=Hello, world or IWLISTBOX1=2). This value is only present if the SubmitOnAscynEvent property it set to True.The x and y contain the coordinates on screen, and which contains the ASCII value of the key that was pressed.The value of modifiers can be CTLR_MASK, ALT_MASK, or SHIFT_MASK (the commas for CTRL and ALT are included!). .Pressing the right Alt key (with the "Alt Gr" caption) has the effect that ALT_MASK,CTRL_MASK, is given, which may not be entirely correct.

The values of x and y are the screen coordinates where the mouse was present when the OnAsync event was triggered. The modifiers value can be ALT_MASK, CTRL_MASK, or SHIFT_MASK again. The ALT_MASK and CTRL_MASK include a comma, the SHIFT_MASK does not.

In order to retrieve the contents of the EventParams, I'm using the following code in my IntraWeb forms. First, I've defined a number of constants, so I don't have to retype the callback, x, y, which and modifiers strings (and make accidental typing mistakes):

Working with EventParams

Now, inside an OnAsync event, for example the OnAsyncClick event I can write the following code to get the X and Y coordinates:

IntraWeb 9.x and AJAX

AJAX Event EventParams veldenOnAsyncChange IWCONTROLNAME=

callback=OnAsyncClick callback=

x=y=which=modifiers=

OnAsyncDouble Click callback=x=y=which=modifiers=

OnAsyncEnter IWCONTROLNAME=callback=

OnAsyncExit IWCONTROLNAME=callback=

OnAsyncSelect IWCONTROLNAME=Callback=

OnAsyncTimer callback=AjaxRequestUniqueId=

AJAX Key Events EventParams veldenOnAsyncKeyDown IWCONTROLNAME=

callback=x=y=which=modifiers=

OnAsyncKeyUp IWCONTROLNAME=callback=x=y=which=modifiers=

OnAsyncKeyPress IWCONTROLNAME=callback=x=y=which=modifiers=

AJAX Mouse EventsEventParams veldenOnAsyncMouseDown callback=

x=y=which=modifiers=

OnAsyncMouseUp callback=x=y=which=modifiers=

OnAsyncMouseMove callback=x=y=

OnAsyncMouseOver callback=x=y=

OnAsyncMouseOut callback=x=y=

const callback ' '; x ' '; y ‘ '; which ' '; modifiers ' ';

===

==

callbackxy

whichmodifiers

procedure

begin

end

TIWForm2.IWEdit2AsyncKeyPress Sender TObject EventParams TStringList

IWMemo1.Text Chr(StrToIntDef EventParams.Valueswhich EventParams.Values x ,

EventParams.Values y ;

( : ;: );

' ' ([ ], )) ' ' [ ] ‘ '

[ ] ' ';

:= ++ + + +

+

Key [32 ] at (

)

This will give you a simple example how to get your hands on the fields of the EventParams stringlist.Note that you cannot combine the OnAsyncXXX with the normal OnXXX events: the OnAsyncXXX will “hide” the normal events (like the OnClick which will no longer fire if you've implemented an OnAsyncClick event handler). OnAsync and VisibleOnAsyncClick event, the following will not work:There are a few special circumstances you have to be aware of when using the OnAsync events of the IntraWeb controls. One of the special cases is the fact that invisible controls that are not rendered, cannot be made visible in an OnAsync event.So, if you have a TIWRegion for example, with the Visible property set to False, and you want to make it visible as the result of an OnAsyncClick event, the following will not work:procedure

begin

end

TIWForm2 IWButton3AsyncClick Sender TObject EventParams TStringList

IWRegion1 Visible True;

. ( ;);

. ;

::

:=

The problem is that the TIWRegion was already invisible, and by default not rendered. You will need a real OnClick event to render the control. Once a control is rendered, it can be made invisible and visible again (that's no problem), but the problem is that you cannot show something which isn't there in the first place. The really simple solution to this problem is to set the RenderInvisibleControls property of the IntraWeb Form or the Region (container) to true. This will ensure that the control on the form or region is rendered (even when invisible), so the OnAsync event can make it visible again without having to refresh the entire page.

OnAsync and DisableIf you have a TIWButton which retrieves some data from a database and updates a number of IntraWeb controls asynchronously inside the OnAsyncClick event, then you may want to disable the TIWButton or at least prevent it from sending another asynchronous OnAsyncClick event to the server.This can be done, but requires two steps: first you need to disable the TIWButton right after the click, which can be done using JavaScript in the onClick event using the ScriptEvents dialog, specifying the following JavaScript:This disabled trueReturn true

. = ;;

2005 Win32 200 Win327

This will disable the button as soon as you click on it.The obvious second step involves enabling the button again. The problem is that the IntraWeb application at the server side still believes that the button is enabled (since it was a local JavaScript event that disabled the button), so just setting the Enabled property of the button to True will not have the desired effect.

Page 27: Blaise Pascal 2 Uk Print Able Download

Page 27 / 1841June 2008 BLAISE PASCAL 2

In order to “trick” IntraWeb, we have to explicitly set the enabled property to False (which has no effect) and then back to True again, so the button will be enabled again.In order to simulate a big task, let's perform a Sleep(4242) and simulate the situation in the following OnAsyncClick event:

SummaryIn this article, an abstract from my Delphi Win32 VCL for the Web / IntraWeb Development courseware manual (see ).I've discussed the way IntraWeb implements and supports AJAX asynchronous event handlers in a very elegant and straightforward way using OnAsync events with EventParams that contain more details about the event itself.

http://www.eBob42.com/courseware

procedure

begintry

finally

endend

TIWForm2.IWButton6AsyncClick(Sender TObject; EventParams TStringList);

Sleep( ); (Sender as TIWButton).Enabled False; (Sender as TIWButton).Enabled True; ;

;

::

:=:=

4242 // Proceed with what is needed

Figure 5.

IntraWeb 9.x and AJAX

Bob SwartBob Swart (aka Dr.Bob - www.drbob42.com) is an author, trainer, developer, consultant, web master and reseller (in the BeNeLux) for his one-man company Bob Swart Training & Consultancy (eBob42) in Helmond Brandevoort in The Netherlands. Bob has spoken at Delphi and Borland Developer Conferences since 1993, gives frequent free seminars in Helmond Brandevoort, and blogs in his ASP.NET ECO-driven weblog at http://www.drbob42.com/blog.Bob is offering Delphi courseware manuals and training services at http://www.eBob42.com/courseware as well as on Lulu athttp://stores.lulu.com/DrBob42 and uses these in his training and seminars.As a CodeGear reseller, Bob is the first choice for your New User or Upgrade license for Delphi, C++Builder or RAD Studio (or other CodeGeartools) in BeNeLux, based on his personal support and dedication to the environment.Bob's love for Pascal and Delphi is expressed in the names of his kids Erik Mark Pascal (1994) and Natasha Louise Delphine (1996).

2005 Win32 200 Win327

BLAISE PASCAL MAGAZINE

To in advertise

or on the website

email

mob. + 31.6.21.23.62.68

or see our price list

www.blaisepascal.eu

http://www.blaisepascal.eu/index.php

?actie=advertprices/priceinform

[email protected]

Readers Please send your questions and comments to:

email [email protected] to: Edelstenenbaan 21

3402 XA IJsselstein, The NetherlandsTel.: + 31 (0) 30 68.76.981

Mobile: + 31 (0) 6 21.23.62.68

How to become a subscriber

*

subcribe

*for the first year € 25.00

First of all you need to decide whether you want:

1 the printed version ,

2 the no paper (download) version, printing enabled and code included.

3 the basic download version,

without code, downloads and printing disabled. The second issue is not free but costs € 10,00.

Any first issue can be downloaded at any time.(If it is your first download.)

Special limited-time offer:

to the “printed version” or “no paper”

download version

You can pay with PayPal or by credit card (Take Two) or by bank. Look for subscription details on page 2

code included, fully printable version,lectronic version download included;including tax, postage (4 issues = 20,00 euro’s, total € 45,00)You can have your electronic version immediatly whilst the printed issue is on its way.

(you don't have to pay postage, just pay € 25,00).

without

excluded

Page 28: Blaise Pascal 2 Uk Print Able Download

Page 28 / 1842 June 2008 BLAISE PASCAL 2

Solving unknown variables in a set of linear equations

Sometimes we need it in one of our programs: solving one or more unknown variables from a set of equations. Most of us can manage to solve x in the equation A.x + B = 0, the unknown factor x is then –B/A. But what to do when we have two or more unknown variables? What we want, is a general method to solve any number of unknown variables from a set of equations. Such a method exists, it's called Gaussian Elimination. This article describes this method and provides a Pascal Function SolveLinEq to solve an infinite number of unknown variables from a set of linear equations. And even more, for the mathematically lesser skilled amongst us, it is explained how it works.

First, as Gauss' method works only for linear equations, we must define what linear means in this context. The unknown variables in a linear equation contain no exponents, no roots and no multiplications amongst each other, so

is not linear when x and y are the unknowns but linear when A, B and C are the unknowns. Furthermore, we must have as many equations as we have unknown variables and in all these equations the unknown variables must appear on the same position. As all equations must have the same number of terms, 'zero' is allowed as a term. Let us look at an example with three equations:

The unknowns are called P, Q an R here. I could have called them x, y and z or x1, x2 and x3, that's irrelevant. As the terms of the equations are always in the same order, we can use the matrix notation for simplicity:

So this matrix contains only the known factors of the equation-terms, the coefficients. If for a certain unknown variable no term exists in an equation, a 0 must be filled in as coefficient. The coefficients can be stored in a two-dimensional array:

Coef double

Of course, when we would have 9 equations with 9 unknowns, the size of the array would be [1..9,1..10]. Using each time different array-sizes is not very practical when we want to implement a function. This flexibility would normally be achieved by using Dynamic Arrays. However, when the copy of the array containing the coefficients is changed in the function SolveLinEq, the original array is also changed! This happens to be a bug in Delphi (at least in version 7, which I use, but Borlands Quality Central still advises for version 10 not to copy multidimensional dynamic arrays).

So in order to take care of all possible array-sizes, we use “normal” arrays. Therefore we must define the following lines in the declaration part of our main program:

A Function for Gaussian Elimination

array of

2 A x + B y C x y 1

5P Q 7R 35 2P 4Q 16R 801.5P 5Q 8R 20

5 1 7 35 2 4 16 801.5 5 8 20

1 3 1 4

. . + . . =

– + =+ + =

- + - = -

-

- - -

: [ .. , .. ] ;

function var

var

begin

while do begin

for to doif then begin

endif thenfor to do begin

end

for do begin

if and thenbegin

for to do begin

if and then end

if then begin

endend

end

end

for downto do begin

if then for to do

if then begin

end elseend

end

SolveLinEq(NumEq word Coef TTerms; Error boolean) TUnk i j k cntr integer

fact double Unknowns TUnk

Error false j 1 j NumEq cntr 0 fact abs coef j j k j NumEq fact abs coef k j

cntr k fact abs coef k j ; cntr k NumEq

fact Coef j k Coef j k Coef cntr kCoef cntr k fact ;

i j to NumEq

Coef j j Coef i j

fact Coef i j Coef j j cntr k NumEq

Coef i k Coef i k Coef j k fact k NumEq) Coef i k inc cntr ; cntr NumEq

Error true exit

inc j i NumEq

fact Coef i NumEq i NumEq j i NumEq

fact fact-Coef i j Unknowns j Coef i i

Error true exit Unknowns i fact Coef i i Result Unknowns

: ; : : : ;

, , , : ;: ;

: ;

:= ;:= ;

<

:= ;:= ( [ , ]);:= +

< ( [ , ])

:= ;:= ( [ , ]);

> := +

:= [ , ];[ , ] := [ , ]; [ , ] := ;

:= +

( [ , ] <> ) ( [ , ] <> )

:= [ , ]/ [ , ];:= ;:= +

[ , ] := [ , ] - [ , ] * ;( <= ( [ , ] = ) ( );

=

:= ;;

;;

;( );

;

:=

:= [ , + ];< := +

:= [ , ]* [ ];[ , ] =

:= ;;

[ ] := / [ , ];;:= ;

;

{re-arrange equation set to always divide by largest number}

1

0 1 1

{eliminate unknown variables by making their coefficients zero}1

0 0

01 1

0

{<>0}{i}

{j<NumEq}{calculate unknown variables by substitution}

1

11

0

{i}

The function SolveLinEq can then be called as:Unkvar SolveLinEq NumEq Term ErrorUnkvar is an array of type TUnk which gives us the calculated unknowns, NumEq is an integer of type word, containing the number of equations provided to the function, Term is an array of type TTerms in which the known variables are contained and Error is a Boolean variable which will become true when the unknowns in the set of equations cannot be solved.

The complete function is as follows:

:= ( , , );

Peter Bijlsma

Gauss' Method for eliminationGauss' method eliminates the unknown variables one by one by making the coefficients zero until only one equation with one unknown is left. To do this, it is necessary to multiply the terms of an equation with such a factor that one term is exactly equal to a term in another equation. By subtracting both equations from each other, a new equation is formed in which one unknown variable is eliminated. Let me explain the working of the function by looking at an example. Consider the same coefficient matrix as we saw earlier:

5 1 7 35 2 4 16 801.5 5 8 20

-

- - -

const

typearray of

array

MaxNumEq

TTerms MaxNumEq MaxNumEq double;

TUnk MaxNumEq of double;

= ;

= [ .. , .. + ]

= [ .. ]

20 //example, maximum number of equations for your application

1 1 1 //containing coef. matrix

1 //containing unknown variables

3 2005 Win32 200 Win327

Page 29: Blaise Pascal 2 Uk Print Able Download

Page 29 / 1843June 2008 BLAISE PASCAL 2

To determine the multiplication factor, the function takes the coefficient at the upper left-hand corner of the matrix as a denominator. So this coefficient may not be zero. Actually, as I discovered that very large numbers can be formed when the denominator is near to zero, the function takes care that the divisor is always the largest absolute number. The first part of the function takes care of that by exchanging an equation starting with a very low coefficient with one which is more suitable. In our example there is no problem, so we continue with the elimination process. The multiplication factor is now calculated:

and we subtract the terms of the first equation directly from the equivalent terms of the second equation:

Of course, when is already zero, this step is skipped! A counter cntr determines whether the coefficients of the unknown terms are all zero. In that case the unknowns cannot be solved and the function is exited with the Error Boolean set true. The next loop through the program calculates the multiplication factor for the third equation: and the coefficients are subsequently re-calculated: changes into

, etc. The matrix now is as follows:

When we consider the last two equations, we see that the set of equations is now reduced to two equations with two unknown variables, as the coefficients in the first terms are zero. In the same manner as above, we can now eliminate Coef[3,2], which results in the following matrix:

The program will now execute the last part of the function. First, the unknown R is calculated:

. In the next loop this value is substituted in equation 2, revealing that the unknown Q = 3, so that finally in equation 1 the unknown P can be calculated: P = 2. If in this substitution process a division by 0 would occur, a solution is not possible and the function is exited with the Error Boolean set true. When there is no error, the function exits to give the calling program all unknowns in a TUnk-type array. When the Error Boolean is set, however, this array contains rubbish, so the programmer must take care of such a case in the main program.

Talking about errors. Sometimes there is insufficient information to calculate the unknowns. Take for instance the following equation set:

Coef 2 1 Coef 1 1 2 5

0 4

Coef 2 1 is changed into 2 0.4 5 0Coef 2,2 is changed into 4 0.4 1 4.4Coef 2,3 is changed into 16 0.4 7 13.2Coef 2,4 is changed into 80 0.4 35 66

Coef 2 1

Coef 3 1 Coef 1 1 1 5 5 0 3

Coef 3 1

1 5 0 3 5 0

5 1 7 350 4 4 13 2 660 4 7 5 9 9 5

5 1 7 350 4 4 13 2 660 0 20 80

or 20R 80

Coef 3 4 Coef 3 3 80 20 4

[ , ]/ [ , ] = /

= .

[ , ] – * =[ ] + * =[ ] – * =[ ] – * =

[ , ]

[ , ]/ [ , ] = - . / = - .

[ , ]

- . + * =

-. .. - . - .

-. .

- -: - = -

[ , ]/ [ , ] = - /- =

.

2P 3Q 82P 3Q 10

3P 2Q 76P 4Q 14

2P 3Q 82P 3Q 10

+ = + =

+ =+ =

+ = + =

These equations cannot both be true and are therefore inconsistent. There is no solution possible. Another problem is demonstrated by the following set:

These equations are certainly consistent, but still no unambiguous solution is possible as these equations are equivalent. There is more than one possible solution. Such case is not always obvious at first glance. Consider the following equation set:

Everybody can see that the solution for this set is . Yet the function sets the Error Boolean for this equation set. When we follow the elimination steps as described above, we see why. When this set is reduced to two equations, they read as follows:

And these equations are equivalent! So there are more solutions than only the zero-solution and hence no unambiguous unknowns can be calculated. When you use the function SolveLinEq, never forget to verify the status of the Error Boolean!

P Q R = 0

5.5Q 13 5R 011Q 27R 0

= =

- + . =- + =

The DemonstratorTo demonstrate the function, I wrote a demonstrator. See Figure 1. The source code of this program will, as always, be available on the website.

The SpinEdit is used to select the number of unknowns, one, two or three and the program then displays the required number of EditBoxes where the user can fill in the coefficients. By clicking the Solve button, function SolveLinEq is called and the solution is displayed. Actually, there are two different SolveLinEq functions implemented in the demonstrator, one as described above which you can use for your own programs and one for demonstration purposes. For the mathematically interested I've added a Step mode which shows the elimination and substitution process steps one by one, displaying the changing matrix as explained above. Step mode A selects the “normal” function, where the first part of the function takes care that always the largest (absolute) number is put in the upper left-hand side box, i.e. coefficient [1,1] in the matrix. Step mode B only takes care that on that position no zero is present. During the Step mode, the program waits for only a Step command to continue. This is done as follows:

In the NextStep procedure the following lines are present:StepClicked false

StepClicked Application ProcessMessages

Of course the Boolean StepClicked will become true each time Step mode A or Step mode B is clicked. The caption of the selected button is during the Step mode changed into Step for clarity. To avoid undesirable effects in the Step mode no other commands than StepClicked are allowed and therefore all buttons (except Step) are disabled.

:= ;. ;while not do

Solving unknown variables in a set of linear equations

Figure 1.

Also, a number of Test buttons have been provided. Test 1 selects the equation set used to explain Gauss' method earlier in this article. The change of the coefficients in the matrix as described can be monitored by selecting Step mode B. Test 2 selects a set of equations which is inconsistent. The Error Boolean is set in the elimination process. Test 3 selects a set of equations which has multiple solutions. The Error Boolean is here set in the substitution process. Test 4 demonstrates the difference in the selection criteria to exchange the position of the equations in the matrix.

3 2005 Win32 200 Win327

Page 30: Blaise Pascal 2 Uk Print Able Download

Page 30 / 1844 June 2008 BLAISE PASCAL 2

Step mode A always puts the absolutely largest number in the upper left-hand corner, Step mode B avoids only a division by zero. When this latter Step mode is selected, a division by almost zero takes place in the Test 4 set, resulting in very large numbers for the recalculated coefficients. Test 5 demonstrates that the Error Boolean is set when there are more solutions than only the zero-solution. When one coefficient in the matrix is changed, the zero-solution is given as a unique answer.

Applications for the functionFor practical reasons, read: I'm too lazy to type a lot of code lines, the demonstrator is limited to three unknown variables. But you can be sure that the function SolveLinEq works for as many unknowns as you wish. For what reasons do you need such a function? Here are a few examples:

The formula for a straight line, , can be calculated when two coordinate pairs are known. The linear equations are:

Don't be confused by the notation which is now slightly different. Fill in the coefficients (don't forget coefficient 1 for the Q term) and P and Q will be calculated. Likewise, the formula for a parabola( ) is determined when exactly three coordinate pairs are known:

If you have exactly 5 coordinate pairs, you might want to know which ellipse or hyperbola is represented by these figures. You'll get a 100% fit by filling in the five coordinate pairs into the following equation of degree two:

Or maybe you prefer a polynomial of the 4th degree:

Unfortunately, real life is not always that easy to obtain a formula which perfectly fits to all coordinate pairs. Normally you have many coordinate pairs and if they don't fit exactly in a formula, you want at least an approximation for that formula. Also in that case the function SolveLinEq turns out to be very useful. The coefficients must then first be determined in a process called Curve Fitting.

In the next article I will discuss some aspects on the subject Curve Fitting.

y P x Q

x1 P Q y1x2 P Q y2

y P.x² Q.x R

x1² P x1 Q R y1x2² P x2 Q R y2x3² P x3 Q R y3

x²P xyQ y²R xS yT 1

4x P x³Q x²R xS T y

= . +

. + =

. + =

= + +

. + . + =

. + . + =

. + . + =

+ + + + = -

+ + + + =

Solving unknown variables in a set of linear equations

Peter Bijlsmais born in 1946 in the Netherlands. He studied higher electronics and followed a course Algol. In 1982 he became the proud owner of an Apple II computer and programmed in Basic and 6502 assembly language. Other languages (Pascal, Perl) he picked up via self-study. He was employed as a Technical Communicator, i.e. author of technical manuals and instructor with a manufacturer of radar and military Command and Control systems. Later on he wrote software to convert XML-based text into either Websites, CD-roms with PDF files or “old fashioned” handbooks. Now he is retired. [email protected]

Every .NET program you write won't be compiled to machine code directly, but to CIL (Common Intermediate Language). The CLR (Common Language Runtime) then converts it to machine code. This happens at the clients' pc, when the user starts the application. The disadvantage of this system is that it is relatively easy to decompile your application and convert the CIL back to readable code. This won't be a problem for open source software, but not everybody is so happy to give away his/her code. Luckily there is software to prevent users from doing this.

Let's start with an example. Because the example application itself isn't very important, I kept it really simple. Figure 1 shows the interface, which consists of two input fields and some labels. When a number in one of the input fields changes, the labels below show the sum, difference, multiplication and division of the two numbers.

Example

Obfuscator? By Rob van de Bogert

The next step is to download Reflector. You can download reflector at . After downloading you only need to extract the file to whatever folder. After doing this, start Reflector.exe. Using File – Open you can open the dll or exe you want to look at. Let's open the example applications' executable now. In the treeview in Reflector the application will be located at the bottom. After opening some nodes in the treeview, we see the screen as displayed in figure 2.

http://www.aisto.com/roeder/dotnet/

Say we want to see the implementation of the AddValues method. A simple double-click will do the trick. On the right side of the screen the implementation of the method will be shown. Using the dropdown at the top the language for the code can be selected. It doesn't matter in what language the application was written originally. The example application was made in C#, but I'll show the code fragments in pascal (named Delphi in reflector). When we view the code for the AddValues method, we immediately notice something.

Figure 1.

Figure 2.

2005 .NET

Page 31: Blaise Pascal 2 Uk Print Able Download

Page 31/ 1845June 2008 BLAISE PASCAL 2

The names of local variables are replaced by something meaningless. Except for that, the code is perfectly clear and understandable. It's clear that this easy reviewing of the code could be problematic for commercial software with ingenious algorithms.

And this all leads us to the so called obfuscator. An obfuscator is an application that can manipulate your .NET software in a way that makes it more difficult to read back using Reflector. There are quite a lot of obfuscators available today. For example Dotfuscator that comes with Visual Studio. The site

obfuscators and compares a number of them.

Obfuscator

http://www.howtoselectguides.com/dotnet/obfuscators/ explains

Deepsea ObfuscatorAn obfuscator made in the Netherlands is DeepSea obfuscator. During installation you have the possibility to integrate it into your IDE. Unfortunately this does not work for Delphi .NET IDE's, but only for Visual Studio 2005 and 2008. The program can also be used as a standalone version. Figure 3 shows the interface.

The interface is really clean and clear. The first thing to do is add an assembly using 'Add assemblies'. After you've done that a press on the green arrow (Go!) is all that's needed. After a few seconds (depending on the size if the assembly) the obfuscation is complete. When we open the obfuscated assembly in Reflector, it's easily noticed that everything is renamed to something meaningless. Take a look at figure 4 and then compare it to figure 2.

function string;begin

end

frmMain AddValues value1 Decimal value2 Decimal

(value1 value2Result CS$0$0001.ToString

;

. ( : ; : ):

CS$ := + );:= (' ')

0$00010.####

Listing 1

Figure 3.

The problem of almost all (?) obfuscator software is that this renaming isn't exactly waterproof. You can make it really hard for someone to really understand your source code, but it still is possible, without having to read machine code.DeepSea Obfuscator also has the possibility to obfuscate just parts of the source code. Visit the website of DeepSea Obfuscator for detailed information about what it can do. On the website you'll also find a trial version. The url is

. The full version costs €199,-

Another solutionBefore I wrote this article my experience with obfuscator software was very limited. While I was writing it, I suddenly got another idea. In my job I had used the open source software .NETZ ( ). .NETZ is comparable to UPX for Win32 in that it compresses your executable and attaches a launcher. When the compressed executable is started, the launcher decompresses your executable in memory and launches it. If you open the compressed executable in Reflector, you can't see anything from the original source code. The only things that are visible are some functions used by the launcher. So it seems to work better than the obfuscator software, and as a bonus your executable will be smaller (unless your executable was really small, say smaller than 100 kB or so). Another advantage is that you can put dll's used by your software into the compressed executable.I do not dare to say how solid this method is, because it should be possible to detach your executable from the launcher and decompress it. My advice: use an obfuscator, compress your executable with .NETZ and then at least you made it really really hard to get to the source code.

www.deepseaobfuscator.com

http://madebits.com/netz

Figure 4.

Obfuscator?

Rob van der Bogertstarted (serious) programming in 2005 at the MCH hospital in The Hague.He started programming using Delphi 7 first. Currently he writes software using both Delphi 2006 and Visual Studio 2008 (C#). He also is interested in new technologies like WPF for example .

2005 .NET

Page 32: Blaise Pascal 2 Uk Print Able Download

Page 32 / 1846 June 2008 BLAISE PASCAL 2

Restricting Edits to numbers By Henk Schreij

It's quite often necessary to have an entry field that only accepts numeric values. A possible solution is to assign the style 'Numbers' to an Edit. This will refuse any entry that is not a number. Although this solution is often used, it is not watertight – as I demonstrate below. After this I describe a solution that provides complete certainty, although it is a bit more complicated.

For the most part, Delphi is not an independent application. It only provides simplified (sometimes highly simplified) access to Windows components. For instance, Edit is a Windows control with most of its properties made accessible. The properties are thus available in the Object Inspector (i.e. they are published). One of the properties you see there is CharCase. Insead of the usual ecDefault, you can set this property to ecLowercase or ecUppercase to restrict data entry to lower-case or upper-case letters. Unfortunately, there is no 'NumbersOnly' property – a property that is available in Windows, but which is not included in Delphi (as I show further on).

From Delphi 4 onward, there's an easy way to examine Delphi structures. For example, with an Edit you can click TEdit while pressing the Ctrl key. As you can see from Figure 1, when you do this a hand icon appears and TEdit is underlined in blue.

Figure 1. Using Ctrl + Click to access the source code

When you're in the source code, you can examine how the properties are implemented. For instance, with an Edit you see something like:

procedure var Paramsconst

array ofarray of

array of

array ofarray of

begin

TCustomEdit CreateParams TCreateParams

Passwords Boolean DWORD ES_PASSWORD ReadOnlys Boolean DWORD ES_READONLY CharCases TEditCharCase DWORD ES_UPPERCASE ES_LOWERCASE HideSelections Boolean DWORD (ES_NOHIDESEL 0) OEMConverts Boolean DWORD ES_OEMCONVERT)

( . . . )

. ( : );

: [ ] = ( , );: [ ] = ( , );: [ ] =

( , , );: [ ] = , ;

: [ ] = ( , ;

00

0

0

Password, ReadOnly, CharCase, HideSelection and OEMConvert are thus included, but Numbers is not – even though it does exist, as you can verify in the Windows SDK or Windows API Help (access to this varies depending on the Delphi version; Figure 2 is for Delphi 7).

Figure 2. Launching Windows HelpWhen you are in Windows Help, you can find the same Edit properties under Styles.

Figure 3. Looking up Edit styles in Windows Help

The Delphi Help says:

An application can use a style to determine how Windows displays text that a user enters into an edit control. The ES_LOWERCASE style converts the text into lowercase characters; the ES_UPPERCASE style converts the text into uppercase characters. Some applications may need to convert the text in a Windows string (such as a filename) into a specific character set. The ES_OEMCONVERT style ensures the proper conversion of characters in these instances.When the amount of text to be displayed exceeds the size of the edit control, an application can use styles to scroll the text through the edit control. The ES_AUTOHSCROLL style automatically scrolls text horizontally. Other available styles define different aspects of an edit control. The ES_NUMBER style restricts input to the edit control to digits only.

For example, CharCase is represented here by the ES_UPPERCASE and ES_LOWERCASE styles. But one property has not been included in Delphi: the ability to restrict the entry to 'numbers only'.

In Windows Help, you can see that an ES_NUMBER style does exist:The ES_NUMBER style restricts input to the edit control to digits only.

However, this style is not included in the Edit properties. You have to do this yourself by expanding the Edit styles (preferably in the OnCreate of the Form). An example of an edit (Edit2) that allows only numeric entry is shown in the following figure, with the code underneath:

( . . . ) NumbersOnly Edt TEdit

Form1 TForm1

TForm1 NumbersOnly Edt TEdit

SetWindowLong Edt.Handle GWL_STYLE GetWindowLong Edt Handle GWL_STYLE) ES_NUMBER

TForm1.FormCreate Sender TObject

NumbersOnly Edit2

privateprocedure

public

end

varimplementation

procedurebegin

orend;

procedure begin

end;

( : );

;

: ;

. ( : );

( , ,( . , );

( : );

( );

{Public declarations }

{$R *.dfm}

Figure 4. Demo program for a numbers-only Edit

Here we use GetWindowLong(Handle, GWL_STYLE) to fetch the desired style properties. Then we add the ES_NUMBER property with “or”. SetWindowLong in turn assigns the property to the Edit. Now you can only enter numbers in Edits that include this declaration. Place the declaration in the OnCreate of the Form. In the demo code this is only done for Edit2, but in practice you can use it for lots of other Edits. Incidentally, here the entry is actually restricted to positive integers, because commas, dots, minus signs and so on will be refused with a beep.

3 2005 Win32 200 Win327

IndexContent Find

Page 33: Blaise Pascal 2 Uk Print Able Download

Page 33 / 1847June 2008 BLAISE PASCAL 2

The declared setting only applies to keyboard input. This means that if you add a button with the code Edit2.Text:= 'abc', the Edit will not refuse it. Of course, you can prevent this in your code, but there is an even more serious problem: you can also enter letters by using copy and paste. Unfortunately, the ES_NUMBER style won't stop this. In Blaise 80 I described a solution that uses OnKeyPress to partly solve this problem:procedure var begin

if not in thenbegin

endend

TForm1 Edit3KeyPress Sender TObject Key Char

Key 8 Beep Key

. ( : ; : );

( [' '..' ', # ])

;:= # ;

;;

0 9//(#8 = Backspace)

0

This prevents copying and pasting via the keyboard (using Ctrl + V or Shift + Insert), but it does not stop you from right-clicking with the mouse in order to paste a selection, as can be seen from Figure 5:

Figure 5. Pasting with right-click

Fortunately, it is easy to intercept mouse entry and empty the ClipBoard. To do this, add to the “uses” ClipBrd and write the following OnMouseClick code:

procedure

beginif in then

end

TForm1 Edit3MouseDown Sender TObjectButton TMouseButton Shift TShiftState X Y Integer

ssRight Shift Clipboard Clear

. ( : ; : ; : ; , : );

. ;;

// uses ClipBrd

This causes the Paste command to be disabled (greyed out) when the mouse is right-clicked, so you can't surreptitiously smuggle a letter into a number field.

In the above discussion, I showed you how to view the Delphi source code. This is often very handy, if only to see how good programmers write code (so you can copy them!). I also showed you how to access the Windows reference documentation. In many cases, this can also provide a lot of useful information. By comparing the two, you can see that code that 'only accepts numbers' is not implemented for Edits. I showed you how you can do this yourself with a single line of code. Unfortunately, this approach is not watertight because it is still possible to enter letters by pasting them from the clipboard. For this reason, I concluded with a bit of code that you can use to disable the clipboard.

Conclusion

Restricting Edits to numbers 3 2005 Win32 200 Win327

So you have finally gotten the dual monitor setup you have always asked for. You are enjoying the extra desktop size but wish there was an easier way to move your mouse pointer from one monitor to the next. Even better would be the ability to move a window of a running application to the other monitor. This article will show you how to accomplish this task using Delphi.

We want the resulting application to be as transparent as possible to the end user. To achieve this, the following additional features will be implemented:• Reside in the system tray• Use system wide shortcuts

One issue with registering system-wide hot key is that the ones selected may conflict with an applications shortcut. To help avoid issues the application will allow the user to change the hot key if they find the default ones conflicting.

Since Delphi 2006, a component to add an entry into the system tray is provided. While the included application uses this component it isn't necessary for the running of the application if your Delphi version doesn't come with one.

To move the mouse to a desired desktop location you call the SetCursorPos windows API method. This method is called when you set the CursorPos property of the TMouse class. The TMouse class provides information about the mouse that is currently attached to the system.

An instance of the TMouse class is created for you already in the Controls.pas unit. There is no need to create a new instance of the TMouse class, although there is also no mechanism to prevent you from doing so.

To move the cursor to the point 10, 10 on your desktop (of the primary monitor), use one of the following methods. It is important to know that it is possible for a monitor to have negative coordinates. This occurs if you align a secondary display to the left or above the primary monitor.

All source extracts used in this article are available in the download for the article. This includes the sample application as well as a demo

System-wide hot keys have downfalls

System Tray functionality

Moving the mouse

procedure begin

end

TForm1.Button1Click(Sender TObject);

SetCursorPos( , ); Mouse.CursorPos Point( , );

;

:

:=10 10 // use API method directly

10 10// use Delphi supplied method

Monitor informationThe VCL includes a TMonitor class which gives specific information about a monitor, for example, its assigned number (which you can see when using the identify feature in the Display Options dialog). The TMonitor class also provides information about whether the monitor is the primary monitor and various properties about the size and bounds area of the monitor.

Point is a function in classes.pas

2005 Win32 / 200 Win327

by Jeremy NorthMonitor Aspects

Undo

CutCopy

DeletePaste

BLAISE PASCAL MAGAZINE

To in advertise

or on the website

email

mob. + 31.6.21.23.62.68

or see our price list

www.blaisepascal.eu

http://www.blaisepascal.eu/index.php

?actie=advertprices/priceinform

[email protected]

Page 34: Blaise Pascal 2 Uk Print Able Download

Page 34 / 1848

2005 Win32 200 Win327

June 2008 BLAISE PASCAL 2

Multiple monitorsMultiple monitors have been supported with a specific API since the Windows 98 and Windows 2000 operating systems. Delphi supports these API methods with the MultiMon unit. While we won't access any of these API methods directly for the purpose of this article, many of the mentioned VCL classes call these internally.

procedurevar begin

end

TForm1.Button2Click Sender TObjectLMonitor TMonitor

LMonitor Screen.MonitorFromPoint(Mouse CursorPos ShowMessageFmt

LMonitor.MonitorNum

( );;

. ); (' ',

[ ]);;

::

:= Mouse in monitor: %d

If the Left position is the same then the monitors are vertically aligned. If the Top position is the same then the monitors are horizontally align. If both the Left and Top values are different than the user has an irregular multiple monitor setup which this application doesn't support.

A revisit to this article to support irregular layouts is a future possibility. If you currently have an irregular layout, the application assumes a horizontal layout.

Monitor Aspects

Access to multiple monitor information is provided through the TScreen class. Like the TMouse class an instance of TScreen is created for use in the Controls.pas unit.

The TScreen class tells us how many monitors a system has (MonitorCount property) and also provides access to each specific monitors TMonitor class via the Monitors array property.

The TScreen class also has a property that allows you to get access to the primary monitor without having to iterate over the systems' monitors checking for the value of the Primary property.

Included in TScreen are three multiple monitor helper methods that are useful for the application.

- Return the TMonitor instance for the monitor that contains the point specified.

- Return the TMonitor instance for the monitor that falls within the rect specified.

- Return the TMonitor instance for the monitor that the given window falls within.

In order to be able to move the mouse to a new monitor we need to know the current position of the mouse. The TMouse class provides this with the CursorPos property. To work out which monitor the mouse is currently positioned on we can use the MonitorFromPoint method of the TScreen class.

The following source extract displays a message box with the current monitor number as the text.

MonitorFromPoint

MonitorFromRect

MonitorFromWindow

Implementing mouse movement

The Screen (TScreen) is where it happens

Single monitorFor a single monitor system, the BoundsRect value is simply the width and height of the monitor. The width and height values depend on the resolution you are currently running at.

ShowMessageFormat is a function in dialogs.pas, for earlier Delphi versions use ShowMessage Format

LMonitor.MonitorNum]

One thing you'll notice is that the monitor number is zero based. So monitor one is at index zero of the Monitors array property of the TScreen class.To move the mouse to the next monitor for a two monitor setup, the calculation is reasonably straight forward. It is important to know whether the monitors are horizontally aligned or vertically aligned.

We can check this by comparing the Left positions of each of the TMonitor instances stored in the Screen instance.

( (' ', [ ));

Mouse in monitor: %d

type

constarray of string

procedurevar

begin

if then

if then

else

end

TMonitorAlign maHorizontal maVertical

MonitorAlignText [TMonitorAlign]

TfrmMain bGetMonitorAlignmentClick Sender TObject

LMonitor1 TMonitor LMonitor2 TMonitor LMonAlign TMonitorAlign

Screen.MonitorCount exit; LMonitor1 Screen.Monitors LMonitor2 Screen.Monitors LMonitor1.Top LMonitor2.Top LMonAlign maHorizontal LMonAlign maVertical ShowMessage MonitorAlignText LMonAlign

= ( , );

: = (' ', ' ');

. ( : );

: ;: ;: ;

<>

:= [ ];:= [ ];

( = ):=

:= ;( [ ]);

;

Horizontal Vertical

// only process dual monitor setups2

01

MonitorAlignText string array is a convenient way to map a string to a TMonitorAlign value.

With the knowledge of how the monitors are aligned, we now know whether the calculation requires the mouse to move to the left (X) or the mouse needs to move from the top (Y) value.

If the monitors are aligned horizontally then the calculation needs to add the current monitor's width to the X value of CursorPos.

If the monitors are aligned vertically, then the calculation needs to add the current monitor's height to the Y value of CursorPos.

Bounds checkingWith these calculations it is possible that the resulting value might not actually be a valid location on either monitor. This is why an additional check is required before moving the cursor to such a location. This check is provided in the source extract below where the LNewMonitor and LCurMonitor values are tested for being equal.

If the values are the same, then we need to move the mouse in the opposite direction because the calculated position does not fall within the bounds of a monitor attached to the system.

The source code below includes the bounds checking and moves the

is dealer of DeepSea obfuscatorhttp://www.barnsten.com/deepsea.aspx

Special offer for

Deepsea Obfuscator 237,0010%

€ 213,00

Subscribers:

incl. Vat

All you need to to do is email us your order, a free trial can

be downloaded at www.blaisepascal.eu

Page 35: Blaise Pascal 2 Uk Print Able Download

Page 35 / 1849June 2008 BLAISE PASCAL 2

procedurevar

beginif then

if then

else

if thenbegin

if then

else

end

end

TfrmMain MoveCursor

LMonAlign TMonitorAlign LCursorPos TPoint LCurMonitor TMonitor LNewMonitor TMonitor LNewCursorPos TPoint

Screen MonitorCount exit LMonAlign GetMonitorAlign LCursorPos Mouse.CursorPos LCurMonitor Screen.MonitorFromPoint LCursorPos LMonAlign maHorizontal LNewCursorPos Point LCursorPos.X

LCurMonitor Width LCursorPos.Y LNewCursorPos Point(LCursorPos X

LCursorPos.Y LCurMonitor.Height) LNewMonitor

Screen.MonitorFromPoint LNewCursorPos LNewMonitor LCurMonitor LMonAlign maHorizontal LNewCursorPos Point LCursorPos X

LCurMonitor Width LCursorPos.Y LNewCursorPos Point(LCursorPos X

LCursorPos Y LCurMonitor.Height) Mouse CursorPos LNewCursorPos

. ;

: ;: ;: ; : ;

: ;

. <> ;:= ;:= ;:= ( );=

:= ( + . , )

:= . , + ;

:= ( );

=

=:= ( . -

. , )

:= . ,. - ;

;. := ;

;

// current cursor position// current monitor// monitor for the new position

// only process dual monitor setups2

// get the current cursor position

// if the monitors are the same then we need to subtract the values

If you give the button that calls the above code an accelerator, you can successfully switch the mouse cursor position between the monitors. This is great except we really want to be able to switch the cursor position when our application isn't the active application on the desktop..

Figure 1 shows a typical dual monitor setup. The primary monitor (labelled 1) is positioned to the left of the second monitor.

If the mouse is currently on the primary monitor, then we need to add the current X position to the width of the primary monitor to shift the mouse cursor to the next monitor. Once the mouse is positioned on the secondary monitor moving it back to the primary monitor requires two calculations. This is because the first calculation we do (attempting to shift the mouse to the right) is incorrect under these conditions.

If the mouse is currently on the secondary monitor and you shift the X value further to the right then the mouse will end up off screen. This is why the Screen.MonitorFromPoint test is necessary. This method returns the nearest (by default) monitor to the point you pass it. If the nearest monitor to the calculated point is the same as the current monitor, then we have moved the mouse the wrong direction. Moving the mouse should result in the new monitor being different to the old monitor.

There is no reason why the code attempts to add the current monitor width to the X value (height for the Y value). Even if the code subtracted the new monitor's width from the X value it would still result in the wrong calculation.While I've talked about primary and secondary monitor positions in reference to Figure 1, the code doesn't care which monitor is considered the primary one. It only cares about the bounds of each monitor and making sure that the new point exists within the bounds of the new monitor.

One issue with the above code is that it doesn't take into account a setup where the monitors have a different resolution. This is solved in the included application and how this is done is that when subtracting the X or Y coordinates (remember we first try and add X or Y values to move to the next monitor) we must use the new monitors width or height, and not the current monitors width or height.

Non uniform monitor resolutions

Figure 1.

Registering system-wide hot keysTo register a system-wide hot key call the RegisterHotKey API method. This method requires a window handle, a unique identifier as well as details about the key combination to register.

For this application the default hot key for moving the mouse is Ctrl+Alt+C. The following source extract shows how to register a system-wide hot key.

const

procedurebegin

if notor ord then

beginraise

endend

HOTKEY_MOVECURSOR ;

TfrmMain bRegisterHotKeyClick Sender TObject

RegisterHotKey Handle HOTKEY_MOVECURSOR, MOD_CONTROL MOD_ALT

Exception CreateFmt StrRegistrationError GetLastError SysErrorMessage GetLastError ;

;

=

. ( : );

( ,, (' '))

. ( , [ , ( )]);

1

C

When defining the hot key you must use the uppercase version of the key. Note how is used in the code above. Using

will not work correctly.

Once you register a hotkey you also need to know when it is triggered. To do this you need to handle the WM_HOTKEY message. Add a WM_HOTKEY handler to your form as shown below.

ordord

(' ')(' ')

Cc

Monitor Aspects2005 Win32 200 Win327

TfrmMain TForm

WMHotKey TWMHotKey WM_HOTKEY

;

= ( )…

…( : ); ;

class

protected

procedure var Message message

end

procedure var Messagebegin

if Message then

inheritedend

TfrmMain WMHotKey TWMHotKey

.HotKey HOTKEY_MOVECURSOR MoveCursor

;

. ( : );

=;

;// private method that moves the cursor

Once you have registered the hot key, you should also unregister it when you have finished. You should do this in the OnDestroy event of the form.

procedurebegin

if not thenbegin

raise

endend

TfrmMain bUnregisterHotKeyClick Sender TObject

UnregisterHotKey Handle HOTKEY_MOVECURSOR Exception CreateFmt StrUnregistrationError GetLastError SysErrorMessage GetLastError

. ( : );

( , )

. ( ,[ , ( )]);

;;

Page 36: Blaise Pascal 2 Uk Print Able Download

Page 36 / 1850 June 2008 BLAISE PASCAL 2

Monitor Aspects

Moving windowsBefore it is possible to move a window we must first identify what window is currently under the mouse cursor. The WindowFromPoint API method provides us with the handle of the window that currently falls within the point specified as the only parameter. Once we have the windows handle that the WindowFromPoint API returns, we then must make sure we get the top level window. Many controls can have a window handle and we definitely don't want to be moving windowed controls instead of actual top level windows. To get the top level window we need to call the GetParent API method in a while loop until the parent handle returned is 0. This means that we have reached the top level window that we can move.

Once we have the top level window we need to call GetWindowRect to get the width and height of the window. This will be used when we move the window. The application contains a method to perform all of this for us. It accepts a parameter of TPoint which is the current mouse position and also has out parameters to return back the Handle of the top level window, the height and width of the top level window plus the window bounds. If a top level window is found, the method returns true.

Instead of passing numerous parameters and requiring a number of out parameter types, a TWindowInfo record has been defined. As the record contains input and output parameters, the record is passed by reference.

typerecord

end

function var var

begin

while do begin

end

end

TWindowInfo Pt TPoint Hwnd THandle Rect TRect ;

GetWindowInfo AWindowInfo TWindowInfo Boolean LParent THandle LRect TRect AWindowInfo.Hwnd WindowFromPoint AWindowInfo.Pt LParent GetParent AWindowInfo.Hwnd LParent AWindowInfo.Hwnd LParent; LParent GetParent AWindowInfo.Hwnd ; Windows.GetWindowRect AWindowInfo.Hwnd, LRect AWindowInfo.Rect LRect result AWindowInfo.Hwnd ; ;

=: ;: ;: ;

( : ): ;

: ;: ;

:= ( );:= ( );

<>

:=:= ( );

( );:= ;

:= >

0

0

Included application detailsThe application included in the download also has methods to save and load the hot keys to and from the registry as well as the ability to minimize the application to the system tray.

The menus.pas unit provides two functions to convert between a string and a hot key (shortcut) value. These methods are called TextToShortCut and ShortCutToText.While the application loads for the first time the window has an opacity of 125 (using the AlphaBlend and AlphaBlendValue properties). When you restore the application, the opacity is set back to 255. The UI allows you to change the current system-wide hot keys if you wish.

Once you modify the shortcuts the Apply and Cancel buttons are enabled. Click the Apply button to save your changed shortcuts. Clicking Cancel will revert the shortcuts back to there previously saved values.

The Use Defaults button will revert the shortcuts back to their default values.

While the applications user interface is visible, the actual shortcuts are disabled and won't function. This is to allow you to enter the current shortcuts into the shortcut edit box.

With users having increased access to multi-monitor systems it is important that developers are aware of the implications when coding.

Several new properties and methods have been added to the VCL over the past releases. I will highlight some that you may find useful for your current applications.

TForm.DefaultMonitor – this property allows you to select which monitor your form will appear on when started.TCustomForm.MakeFullyVisible – this method makes sure that your form doesn't overlap monitors. This method accepts a TMonitor parameter. Your form will then be made visible on that monitor only.

Multi-monitor features in the VCL

2005 Win32 200 Win327

TForm.Position – New position values have been added to aid positioning a form. If you want to center your form on a single monitor (determined by the DefaultMonitor property) set your forms Position property to poScreenCenter.

Hopefully this article has given you a better insight into how you can use the VCL to your advantage when working with users that have multi-monitor systems.

Conclusion

The above source extract raises an exception because it is called from a button click handler. If you unregister your hot keys in the OnDestroy event of a form, it is advisable to not raise an exception.

We have our system-wide hot keys sorted and the code to move the mouse cursor between monitors, now it is time to start moving some windows around.

To move the window we call the MoveWindow API with the returned top level window handle, the updated Left and Top values (as calculated using the same method as moving the mouse cursor earlier) and with the current width and height of the window. To make sure the window is focussed we also call SetForegroundWindow with the top level window handle.In the final application the logic for moving the cursor and a window is centralised in the same method that has a single boolean parameter; which indicates if the user wants to move the window as well as the cursor.

MoveCursor AMoveWindow Booleanprocedure const( : );

Jeremy North:commenced programming with Delphi in 1997 whilst at college in the USA and since his return to Australia, he has kept pace with emerging windows technologies. More recently he has concentrated his focus on writing components and IDE Experts, as well as creating tools to help other developers work more efficiently.

Some of these components and experts are released to the public on his JED Software website http://www.jed-software.com

Some are free, while others incur a small fee. So let’s go and visit him. (his site)

Page 37: Blaise Pascal 2 Uk Print Able Download

Page 37 / 1851June 2008 BLAISE PASCAL 2

Free code for everyone:On the website is a special download:All the code that is listed here is available for free downloading:It can be code snippets, programs, trials, third party components etc.

Using the website of Blaise Pascal Magazine

The List of available downloads:

Trials:

Code snippets:

Programs including code:

The Deepsea-Obfuscator(the program is advertised in this issue on page 38-39)

Opening files(Mini application for starters)

Rotating images(The program is ment to start learning about image handling)Bitmaps and scanline(is the second part to understand rotating the image)Wallpaper(is a compleet program that has an enormous wide range of code in it like rotating and moving images, opening files, moving files, creating a Client Dataset and handling it and lots of other stuff.)GExperts(is a program you cant mis, soon you will find out why:it has an enormous range of extra’s for Delphi Versions Delphi 5/6/7/8/2005/2006/2007. You always will find the right version)Lazarus(The pascal editor that is made for several operating system:Windows / Linux / Mac) The version that is downloadable hereis al;ways the latest stable version. If you want to know more just click on the Lazarus image

The sales items:

All the international and national events agenda

Information about the way’s to subscribe

Advertising pricellist / Index of advertisers / Privacy statement

Subsribers for the free edition:

1 the printed version*

2 the no paper (download) version*

3 the basic download version

If you have subscribed before for the first (free) issue and log in you will find the followingmessage:

You have already downloaded an issue before.Your first issue will always be free.Since you seem to be interested in our magazine,we hope you are willing to pay for the next issue.It is only 10,-- for the basic version for one year. (4 issues)

So please Subscribe!

How to become a subscriber

Any first issue can be downloaded free at any time. (If it is your first download.) First of all you need to decide whether you want:

, code included, fully printable version,lectronic version

download included;including tax, excluded postage (4 issues = 20,00 euro’s, total € 45,00)

You can have your electronic version immediatly whilst the printed issue is on its way.

,printing enabled and code included.

(you don't have to pay postage, just pay € 25,00).

, without code, without extra's and printing disabled. The second issue is not free but costs € 10,00.

You can pay with PayPal or by credit card(Take Two) or by bank. Look for subscription details on page 2 in the magazine

Here it is all explained once more.

For the download versions of Blaise Pascal Magazine we made all url’s and emailadresses printed dierectly available by clicking on the adres. We also use the icons above to remind you on that.

Page 38: Blaise Pascal 2 Uk Print Able Download

Page 38 / 1852 June 2008 BLAISE PASCAL 2

Euro symbol generation with the Alt key By Henk Schreij

In most programs you can enter data using Edits, Memos, RichEdits and so on. If you are entering monetary amounts, you also need to be able to enter the euro symbol (€). Here I show that with only a few lines of code, you can use “Alt + 5” to display the euro symbol in all (!) forms of your program. This is standard if you configure the language and keyboard of your system to “Dutch / the Netherlands”, but it doesn't always work in your Delphi programs.

Depending on the language and keyboard settings selected in Windows, you can sometimes (but not always) enter the euro symbol in your Delphi programs with a keyboard shortcut. If you don't want to be dependent on Windows, you can write your own code to provide a keyboard shortcut for the euro symbol. In the Netherlands, as in most other parts of the world, the usual key combination for the euro symbol is “Alt + 5”. However, some countries have different combinations, such as Great Brittain (Alt + 4) and Germany (Alt + E). Consequently, the code described below must be modified slightly for these countries.

Delphi 5 and later include a component called ApplicationEvents (on the Additionals tab), which you can use to intercept events before they reach the rest of your program. This means that you only have to write some of code in your first form and it will work in your entire program, regardless of how many forms it contains.In issues of Blaise published in 2003 and 2006, I described how you can use this approach to allow the arrow buttons to be used to navigate to previous and next input screens, for converting decimal markers from full stops to commas, and for handling the mouse scroll-wheel bug in DBGrid.

Figure 1 shows the ApplicationEvents component in Delphi 5 to 7 and in Delphi 2005 to 2007.

ApplicationEvents component

Figure 1. ApplicationEvents in Delphi 7 and earlier (left) and in later versions (right)

CodePlace an ApplicationEvents component on Form1, find OnShortCut under Events, and double-click it. You have to use the OnShortCut event because the Alt key is a shortcut key. Shortcut keys are used for tasks such as selecting a menu item by typing an underlined letter (e.g. “File”). A shortcut key is always read out first, even before OnKeyDown is triggered,

Type the following code in the framework shown for ApplicationEvents1ShortCut (explanation below):

type classprocedure

var var var begin

if Ord and then

begin if then

endend

THackCustomEdit TCustomEdit TForm1 ApplicationEvents1ShortCut

Msg TWMKey Handled BooleanAC TWinControl

AC Screen ActiveForm ActiveControl Msg CharCode GetKeyState VK_MENU THackCustomEdit(AC) ReadOnly Exit TCustomEdit(AC) SelText Handled True

= ( );. (

: ; : );: ;

:= . . ;( . = (' '))( ( )< )

.;

. := ' ';:= ;

;;

50

€ // Alt 0128

I'll explain the first line with “type THackCustomEdit” later on. The code begins with the declaration of variable AC, which is of type TWinControl. All components that can be given the focus are of type TWinControl, and the component that has the focus is the ActiveControl. Each form has an active control, but we want to send the euro symbol to the active form, which is the reason for Screen.ActiveForm.ActiveControl. The next line uses Msg to see which key has been pressed. The character code we need is the ASCII value of the key as calculated by Ord('5'), which is 53.VK_MENU is the virtual key code of the Alt key, which is –1 if the key is pressed. I'll explain the hack code a bit later.In the next line, the euro symbol is assigned to AC (the active control) with SelText (the blink location of the cursor). In your code, you can insert the euro symbol by holding the Alt key pressed and typing the digits 0128 on the numeric keypad. Finally, the statement Handled:= True says that no further processing of the keys is necessary.

Figure 2. Example entry locations for the euro symbol

There's still one problem, which is that you can also use “Alt + 5” to enter a euro symbol in an Edit, RichEdit or Memo that is set to 'read only'. You have to intercept this as well, which is the purpose of the hack. This is necessary because a WinControl does not have a ReadOnly property, but a CustomEdit, the common ancestor of Edit, RichEdit and Memo, does have this property. Unfortunately, it is protected, so it cannot be used. You can use the hack to get around this protection, since the protection is not complete: it can be read out if a derivative of the class is declared in the same unit. This is why you have to include the line “type THackCustomEdit” ahead of the code where you use the hack. You can place this just before the code of the hack or at the beginning of the code, so it can be used everywhere.

With just a few lines of code, you can enable “Alt + 5” for entering a euro symbol in all forms. The OnShortCut event of the ApplicationEvents component is used for this purpose. However, a trick is necessary to prevent this method from being used to enter a euro symbol in a read-only field, since the common ancestor of all entry fields (CustomEdit) has ReadOnly declared as protected. The trick with the hack is simple, and you can use it in many other places to get around the restriction on using protected properties.

Conclusion

Henk Schreij:has graduated as a technical designer.He works for his own company, as a programmer of 'custom made software' for several different companies. Henk has written articles for Blaise since Delphi 1, totalling more than 100 now, mainly aimed at starting programmers.These articles usually have something of interest, too, for those with programming experience.

2005/6/ Win327

Page 39: Blaise Pascal 2 Uk Print Able Download

Page 39 / 1853June 2008 BLAISE PASCAL 2

Top Reasons to Buy

Accelerate PHP web development with a powerful visual Rapid Application Development (RAD) approach and framework

Delphi for PHP revolutionizes web development with a completely integrated, rapid visual development approach and component framework for PHP. Delphi’s proven and familiar RAD approach means you are quickly up to speed and productive. The powerful PHP editor and debugger increase coding speed and efficiency. Connectivity with leading databases provides seamless database access, and the integrated VCL for PHP component class library help developers quickly and visually create PHP web applications and integrate PHP open source components. Delphi for PHP is the fast way to build powerful and reliable PHP web applications.Make PHP programming as simple as drag and drop with the VCL for PHP library

Delphi for PHP includes an integrated PHP 5 class library called VCL for PHP.A customizable palette of over 50 reusable components include buttons, labels, check boxes, images, DHTML menus, flash objects, grids, tree views, list boxes and more. Database components are available for accessing databases, tables, queries, and stored procedures, as well as data grids and navigation. Version 2 of the VCL for PHP adds native Oracle components, Zend Framework components as well as other updates and enhanced documentation.Build data-driven Web applications with broad database connectivity

Delphi for PHP standardizes database connectivity and includes a collection of pre-built database components that make it much simpler to build apps that connect to databases.Delphi for PHP includes native components for MySQL, Oracle and CodeGear InterBase. The Data Explorer supports drag-and-drop database application creation with connectivity to MySQL, Microsoft SQL Server, Oracle, PostgreSQL, Sybase, SQL Anywhere, DB2 and InterBase. Support for all other PHP supported databases is available via ADOdb.Take advantage of HTML templates with embedded PHP and create AJAX-enabled Web 2.0 sites

AJAX is a popular method for building dynamic Web 2.0 sites and Delphi for PHP includes AJAX-enabled components to help you on your way to building modern looking interactive web sites.Additionally, AJAX enablement is built into the core of the VCL for PHP framework, so you can add AJAX capabilities to virtually any PHP code. Delphi for PHP 2.0 also includes a new visual HTML Template editor for editing HTML and creating templated forms that include HTML with embedded PHP.Expand your capabilities by creating your own components or adding others from the open source PHP ecosystem

Delphi for PHP 2

http://www.codegear.com/shop

Extend the VCL for PHP at any time with your own components or enhancements being offered through the open source PHP platform. Delphi for PHP makes it easy to create your own components and install customized packages to use in the IDE. The VCL for PHP makes it simple for you to develop new classes, because every component is built in pure PHP. Simply place these components into forms and use them in your applications. VCL for PHP components have built-in properties, methods, and events that make web interface development a snap.Integrated development environment streamlines code management and navigation

Managing and organizing you PHP code has never been easier. The Project Manager lets you view and organize project files while the Structure Pane shows the hierarchy of components displayed on the designer. The Code Explorer makes navigation straightforward and the Data Explorer enables you to browse database server-specific schema and objects. Version 2.0 adds many enhancements including a new file browser, multi language support, and a Data Viewer window for browsing database tables and executing queries.Powerful editing with integrated PHP debugging and profiling speed up developmentA sophisticated editor and debugger can make the normally frustrating process of tracking down bugs and errors in the code quick and painless. Delphi for PHP has a customizable source code editor that has color syntax highlighting, bookmarks to ease navigation through large files, and Code Insight to assist in the selection of properties and methods. The integrated debugger helps find and fix errors, view breakpoints, and local and global variables. A powerful new PHP performance profiler to help locate application bottlenecks down to a single line of PHP code so you can improve the performance of your Web apps. Delphi for PHP 2.0 includes many enhancements including faster CodeInsight and new Error Insight to help you locate errors in your source code as you type, code folding to make it easier to navigate your source, change tracking to identify changed lines of code, and much more.

Page 40: Blaise Pascal 2 Uk Print Able Download

Page 40 / 1854 June 2008 BLAISE PASCAL 2

The Microsoft .NET framework is gaining popularity every day. More and more developers choose to use this framework as a foundation for their product development. There are many reasons for this. The development speed of a .NET based product is huge. This is the result of an extensive object library, the availability of many development languages all targeting the same framework and a large environment of .NET components. The popularity of the framework is also boosted by the marketing power of Microsoft itself.

The use of the .NET framework compared to traditional software languages also has a down sight. Programs developed for this framework are all compiled to an intermediate language. This language (called IL) is converted to machine code during the execution of the program. This language is very rich compared to machine code. It contains a lot of information that can be used to derive the original source code. This can damage the intellectual property of the developers of the program.To solve this problem, there are various so called obfuscation tools available. These tools change the compiled programs such that its function remains the same, but it becomes much harder to derive the original source code.DeepSea Obfuscator is a new player in this market. It is much more accessible in terms of use and purchase compared to its competitors.This article will demonstrate the need for obfuscation for .NET programs, explain what differentiates DeepSea Obfuscator from its competition and explains how DeepSea Obfuscator will help you to make obfuscation a standard element of the delay business of developers.

Programs developed on top of the .NET framework are compiled into assemblies. An assembly is an .exe or .dll file that looks from the surface very much like a traditional executable or dynamic link library. Internally it is very different. An assembly contains code (IL) and metadata. The metadata describes all types, functions and fields contained in the assembly.This information can be read using tools like ildasm or Reflector. Ildasm is a program that Microsoft ships with the .NET SDK. Its output is rather rough and not so easy to read. In contract to ildasm, the output of Reflect, an application developed by Lutz Roeder, gives a full visual insight in the assembly. Below is a screenshot from a simple assembly as displayed by Reflector.

The need for obfuscation

DeepSea Obfuscator: .NET Obfuscation for all

This is an example of the intermediate language (IL). Although this code is reasonable readable, it still resembles machine code. Reflector can take it a big step further than that. It supports de-compilation to various software languages. The screenshot below shows the de-compiled code in Delphi.

This has a strong resemblance with the original source code.Using the analyze features of Reflector it is rather simple to detect the structure of even large and complex programs.

Obfuscation tools offer a set of transformations that transform compiled assemblies into assemblies that are much harder to read. The most common transformations will be discussed below.

The most common and most used transformation is renaming of types, functions and fields. By assigning a different name to a function, it is less likely to “draw attention” to itself.

What do obfuscation tools do?

Renaming

This example shows a HelloWorld.exe assembly with 1 type, called Program in the HelloWorld namespace. This type contains a default constructor and a Main function.

Using Reflector it is also possible to look into a function itself. Doing so reveals the code of the function as shown below for the Main function.

. hidebysig static void Main( []args)cil managed

.entrypoint

.maxstack 8L-0000 nopL_0001 ldstr L_0006 call void[mscorlib]System

.Console WriteLine(string)L_000b nopL_000c ret

methode privatestring

{

:: “ ”:

::::

}

Hello world

Procedure stringBegin

End

Program. Main(args: []);

Console.writeLine(’ ’);

Hello world

[Advertorial] Ewout Prangsma

The following code sample shows very clearly where to look for the licensing model of this program.

By replacing the names of the functions with random names, the same program now looks like this.

By only replacing names, it is now harder (at least more work) for hackers to find the licensing model.

2005 .NET

Page 41: Blaise Pascal 2 Uk Print Able Download

Page 41 / 1855June 2008 BLAISE PASCAL 2

make obfuscation a standard and natural element or the daily work of a .NET developer.

During the development of DeepSea Obfuscator, careful considerations have been given to the problems with existing tools and the responses to them by .NET developers.

1. Obfuscation has to be applicable without any need for configuration. An obfuscation tool has to recognize possible problem areas by itself and deal with them. For example, DeepSea Obfuscator will not rename serializable types and strongly typed resources are recognized and renamed correctly. If a developer does want to intervene in the obfuscation process, he can do so using standard attributes in the source code, since the source code is the workplace for the developer.

2. Developers like to use their own development languages and tools. DeepSea Obfuscator is equipped with a wide variety of integrations with various development tools. The Code assistant, used to create configuration snippets, supports various development languages such a C#, VB.NET and Delphi.

3. Developers do not want to wait for support for new framework versions or be slowed down due to slow development tools. DeepSea Obfuscator supported Silverlight within days after its release. It also makes optimal use of multi-core PC's.

4. Finally the price. DeepSea Obfuscator chooses a license model the enables developers to use their license of each PC they're working on and a price that makes .NET obfuscation accessible to all.

Ewout Prangsma is General Manager TallApplications BV, supplier of DeepSea Obfuscator.

The following topics are results of these considerations:

You can evaluate DeepSea Obfuscator right now. A free evaluation version is available on our website. There is no time limit on your evaluation.

www.deepseaobfuscator.com

String encryptionAs seen in the HelloWorld sample, strings are clearly visible in an assembly. In that sample this will not bother anyone, but there are many cases where the content of strings provides a clear insight in the meaning and purpose of a function. It is also easy to search for common strings like “Invalid serial number”.String encryption is a transformation that replaces readable strings in an assembly by some form of encrypted strings. Each tool has its own mechanism for this.This is what the HelloWorld sample could look like with string encryption:

Control flow obfuscation

Other transformations

Common problems with obfuscation

To avoid de-compilation by tools like ildasm or Reflector, some obfuscation tools alter the code of a function. By adding extra jumps or changing well known code structures it is attempted to make de-compilation impossible. In real life this transformation is little successful. Each transformation is soon recognized by Reflector and then de-compiled after all.These kinds of transformations are also often the cause of various problems. The more complex a transformation becomes, the greater chances are that the semantics of the code are changed. In that case the programs no longer behave as the developer had intended.

Besides the transformations describes above, there are various other transformations, often surrounded with various “patent pending” claims. Experience leads to believe that these kinds of transformations, by their complexity and necessary configuration, tend to cause more problems that the protection they claim to provide.

Despite the common knowledge that obfuscation is a technology that every .NET developer should use, it is still frequently unused.There are various reasons for that, but they tend to boil down to the following:

1. Obfuscation tools are traditionally expensive (usually theydouble the cost of a developers desktop). For this reasons they are not part of the standard equipment of a software developer.

2. Obfuscation tools are traditionally slow. Despite the multi-core PC's that most developers use, obfuscation tools are rarely optimized for them. The developer has to wait much longer which often results in obfuscation not being a part of a standard compilation cycle.

3. Obfuscation tools are complex. A lot of configuration is needed to make traditional obfuscation tools work properly. Since this configuration is often edited outside the source code (in a different application), the developer is forced to concern with matters outside his primary task; the development of source code.

As a result of all these reasons, obfuscation is often only used at the very end of the development process. This often results in a very late (or lack of) discovery of typical problems such as serialization or user configuration.

DeepSea ObfuscatorDeepSea Obfuscator is a new player in the obfuscation market. It is made for .NET developers by .NET developers. The concept behind DeepSea Obfuscator is simple and straight forward:

Procedure stringBegin

End

O.u. Main(d []);

Console.WriteLine(W.u($ ));

It is still clear that something is written to the console, but it is much harder to derive what is written.

:

744d8230

is dealer of DeepSea obfuscatorhttp://www.barnsten.com/deepsea.aspx

Special offer for

Deepsea Obfuscator 237,0010%

€ 213,00

Subscribers:

incl. VatAll you need to to do is email us your order

and it will be send to you.

[Advertorial] DeepSea Obfuscator: .NET Obfuscation for all2005 .NET

Page 42: Blaise Pascal 2 Uk Print Able Download

....

B B

B B

B B

B B

Bu

zzw

ord

ma

nia

a a

a a

a a

a a

....

AIR

Ado

be In

tegr

ated

Run

time

AJA

XA

sync

hron

ous

Java

Scr

ipt a

nd X

ML

AO

PA

spec

t Orie

nted

Pro

gram

min

gA

OS

DA

spec

t Orie

nted

Sof

twar

e D

evel

opm

ent

AS

App

licat

ion

Ser

ver

B2B

Bus

ines

s to

Bus

ines

sB

IB

usin

ess

Inte

llige

nce

BIS

Bus

ines

s In

tegr

atio

n S

oftw

are

BO

Bus

ines

s O

bjec

tB

PB

usin

ess

Pro

cess

BU

SA

n ab

stra

cted

med

ia o

f com

mun

icat

ion

betw

een

node

sC

A p

rogr

amm

ing

lang

uage

C++

An

obje

ct o

rient

ed v

ersi

on o

f CC

#C

-Sha

rp: A

pro

gram

min

g la

ngua

geC

LOU

DC

loud

Com

putin

gC

MC

lust

er M

anag

erD

AD

ata

Acc

ess

DE

LPH

IA

pro

gram

min

g la

ngua

geD

OT

NE

TA

run

time

envi

ronm

ent

from

Mic

roso

ftD

SD

ata

Sto

rage

DO

MD

ocum

ent O

bjec

t Mod

elE

AI

Ent

erpr

ise

App

licat

ion

Inte

grat

ion

EC

IE

nter

pris

e C

onte

nt In

tegr

atio

n

ES

BE

nter

pris

e S

ervi

ce B

usF

PC

Fre

e P

asca

l Com

pile

r: A

com

pile

r for

Pas

cal

GR

IDG

rid c

ompu

ting

IMIn

stan

t Mes

sagi

ngH

AH

igh

Ava

ilabi

lity

HA

CM

PH

igh

Ava

ilabi

lity

Clu

ster

ed M

ulti

Pro

cess

ing

HP

CH

igh

Per

form

ance

Com

putin

g cl

uste

ring

HTT

PH

yper

Text

Tra

nsfe

r Pro

toco

lH

UB

Cen

tral

dat

a di

strib

utin

g no

deIP

CIn

ter P

roce

ss C

omm

unic

atio

nJA

VAA

ran

dom

ly n

amed

pro

gram

min

g la

ngua

geJR

EJa

va R

untim

e E

nviro

nmen

tJV

MJa

va V

irtua

l Mac

hine

LBLo

ad B

alan

cing

LIN

UX

An

open

sou

rced

pop

ular

ope

ratin

g sy

stem

MB

Mes

sage

Bro

ker

MoM

Mes

sage

orie

nted

Mid

dlew

are

MQ

Mes

sage

Que

ueO

CX

OLE

cus

tom

con

trol

OD

CO

pen

Dat

abas

e C

onne

ctiv

ityO

OP

Obj

ect O

rient

ed P

rogr

amm

ing

OP

Obj

ect P

asca

lO

RB

Obj

ect R

eque

st B

roke

rP

2PP

oint

to P

oint

com

mun

icat

ion

PD

AP

erso

nal D

igita

l Ass

itant

PD

SP

ersi

sten

t Dat

a S

tora

geP

HP

Hyp

erte

xt P

repr

oces

sor:

A pr

ogra

mm

ing

lang

uage

PM

QP

ersi

sten

t Mes

sag

e Q

ueue

PS

Pub

lish/

Sub

scrib

eR

AIS

Red

unda

nt A

rray

of I

nexp

ensi

ve S

erve

rsR

IAR

ich

Inte

rnet

App

licat

ion

RP

CR

emot

e P

roce

dure

Cal

lS

OA

Ser

vice

Orie

nted

Arc

hite

ctur

eS

OA

PS

impl

e O

bjec

t Acc

ess

Pro

toco

lS

PO

KE

Dat

a co

nsum

ing

or p

rodu

cing

nod

e co

nnec

ted

to a

hub

SQ

LS

truc

ture

d Q

uery

Lan

guag

eS

SL

Sec

ure

Soc

ket L

ayer

TLS

Tran

spor

t La

yer

Sec

urity

TP

Tran

sact

ion

Pro

cess

ing

Vis

taM

S V

ista

: An

oper

atin

g sy

stem

WIN

2KM

S W

indo

ws

2000

: A p

opul

ar o

pera

ting

syst

emW

INC

EW

indo

ws

Com

pact

Edi

tion:

Bas

e fo

r Win

dow

sM

obile

WIN

XP

MS

Win

dow

s X

P: A

pop

ular

ope

ratin

g sy

stem

WS

Web

Ser

vice

XM

LeX

tend

ed M

arku

p La

ngua

ge

kbmMW := Succ(Buzzwords) $kbmMW = (Buzzwords)++ kbmMW = (Buzzwords)++

Reg

iste

r an

d do

wnl

oad

kbm

MW

Cod

eGea

r E

ditio

n fo

r F

RE

E fr

om

ww

w.t

urbo

mid

dlew

are.

com

Rea

d m

ore

abou

t kbm

MW

Pro

fess

iona

l Edi

tion

and

kbm

MW

Ent

erpr

ise

Edi

tion

at

ww

w.c

omp

onen

ts4

dev

elop

ers.

com

kbm

MW

is a

trad

emar

k of

Com

pone

nts4

Dev

elop

ers.

Tur

boM

iddl

ewar

e is

a tr

adem

ark

of C

ompo

nent

s4D

evel

oper

s. A

ll ot

her t

rade

mar

ks a

re th

e tr

adem

arks

of t

heir

resp

ectiv

e ow

ners