Planet Object Pascal

July 22, 2014

The Podcast at Delphi.org

Mobile Summer School Lesson 5: App Tethering Round-Up

I substituted for David I. yesterday for Developer Direct Mobile Summer School on Lesson 5: Connecting Mobile and Desktop together using App Tethering. The Summer School landing page and David’s blog maintain a list of downloads for all the previous lessons, but here are the resources from my session in the meantime.

I’ll post the replay videos here when they are available too.

You can download my slides and code samples from Code Central. I believe I fixed the issue where some people were not able to download it.

cc.embarcadero.com/item/29907

Here are the links to more information on App Tethering:

Here is the Developer Skill Sprint I did previously on App Tethering

And this is Al Mannarino’s C++ Mobile Day session on the topic

And some blog posts on the topic too:

There was some interest in the code sample that bypasses App Tethering’s autodiscovery to connect directly to a specific IP address. I’m working on getting that tested before posting it. Leave a comment if you are interest and I’ll see that you are notified when it is ready.

by Jim McKeeth at July 22, 2014 05:57 PM

TPersistent

A Hint About Warnings

Compiler Hints and Warnings are an important indicator of the quality of the code you are compiling.  It dismays me that I have often seen a ton of compiler warnings on commercial components suites when I compile them.  It makes you question the care taken when writing the code.

Compiler Hints and Warnings should be treated as potential coding errors.  Each one should be addressed to ensure it will not cause a errant behaviour at run-time, and the code in question is properly structured.  It is good to see I am not alone in this view.  So Take a hint (pun intended), and clean up your hints and warnings.

Sometimes this isn’t so easy.  For instance, if  component requires a given unit, for example Vcl.ImgList, as the TcxCustomTreeList does, it will add the unit to the uses clause automatically.  You might then get a  warning like  W1000 Symbol ‘TImageIndex’ is deprecated: ‘Use System.UITypes.TImageIndex’. Unfortunately, adding System.UITypes and removing Vcl.ImgList just results in the IDE re-injecting Vcl.ImgList back into the uses clause and reporting the same warning.  I really don’t want to turn off this warning globally so the best option that I know of is to add {$WARN SYMBOL_DEPRECATED OFF} to the interface section of the unit in question.  While this solution may not be ideal, it allowed me to “address” the warning so new compiler hints and warnings that may actually indicate a flaw in the code do not get lost in a multitude of messages.  Clean code is less likely to be flawed code.

by Larry Hengen at July 22, 2014 05:28 PM

Every Team needs a Goaltender

It’s been my experience that just like in sports where you have a goal tender, every development team needs a gate keeper or goal tender for their VCS to ensure nothing gets in that they don’t want.  The role of the gatekeeper in the team is not only to manage the promotion/demotion of DEV code to QA on through to PROD (production), but also to ensure the code meets syntax standards, and more importantly architectural standards or conventions.

Even if the standard way of doing things is less than optimal, consistency is king.  If a slower evolutionary method of evolving the code is not possible, at least with consistent code, you can transform it en masse at the beginning of a release cycle and dedicate a lot of QA time to ensure you didn’t break anything.  Developers who understand the “normal” way of doing things can maintain and write code comfortably, with confidence that it will work.

I have seen consultants brought in to author a new system and use it as an opportunity to play with new architecture and methodologies.  While they usually deliver the results, the code most often cannot be effectively supported by on-site developers because it is so radically different from what they know.  The same thing can happen on a team with developers at different skill levels, and different views on the latest design patterns and methodologies.

The important thing is that ‘there is no “I” in TEAM’.  Everyone needs to be able to understand and support all the code.  If an architectural pattern makes software harder to understand, then the benefits of using that pattern may be outweighed by the maintainability of the code by the team.  The team needs to decide as a whole on coding standards and practices.

One example of this is the heavy use of interfaces.  Interfaces are great for decoupling code, but at the same time it makes it harder to follow since the implementer of the interface is “disconnected”.  Using the Delphi IDE to navigate through code, by Ctrl+clicking in order to understand it, doesn’t work as it does with classes.  This isn’t a shortfall of the IDE.  There is simply no way it can know what objects are used to implement that interface (especially if you use injection).

The quality and maintainability of your code is directly related to the strength of the gatekeeper and the cohesion of the team.  Better teams build better code…

by Larry Hengen at July 22, 2014 03:58 PM

The Wiert Corner - irregular stream of stuff

jpluimers

Found out where the StackOverflow Pascal has its origins: What happened to comments in syntax highlighter? – Meta Stack Overflow.

Like any syntax highlighter, it is not perfect (only a Delphi compiler driven highlighter would have a chance to be perfect), but it does a pretty good job and gets better over time.

–jeroen


Filed under: Borland Pascal, Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi x64, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, FreePascal, Pascal, Software Development, Turbo Pascal

by Jeroen Pluimers at July 22, 2014 05:00 AM

July 21, 2014

while true do;

ITDevCon 2014, Call4Papers

Dear potential ITDevCon speaker, As every year, I’m building the agenda for next ITDevCon that will be held next october 23th, 24th in Milan (Italy), in a new location. This will be the 6th edition ( we’re getting conference experts J ) The call for papers are officially open right now, so if you want to propose some [...]

by Daniele Teti at July 21, 2014 10:28 AM

July 20, 2014

Firebird News

IB Objects and Lazarus

This post makes me realize I have done very little to make public the work I have done with IB Objects over the past years. For everyone’s knowledge, IB Objects has been available on Lazarus for years now and is very mature there. In fact, several bugs and/or deficiencies in Lazarus have been fixed based […]

by mariuz at July 20, 2014 03:41 PM

Firebird 2.5.3 sub-release is available

Firebird Project is happy to announce general availability of Firebird 2.5.3 — the latest minor release in the Firebird 2.5 series. This sub-release introduces several bug fixes and a few improvements, please refer to the Release Notes for the full list of changes. Binary kits for Windows, Linux and Mac OS X on both 32-bit and 64-bit platforms are […]

by mariuz at July 20, 2014 01:55 PM

A new version, IBX for Lazarus 1.1 is now available

Tony announced new version, IBX for Lazarus 1.1 is now available from http://www.mwasoftware.co.uk/ibx See announcement in the 3rd party Lazarus forum for the change log. Performance increased with 30-50% in some cases. Many thanks to Gabor for pointing out the performance issues and for testing updates. This kicked me into cleaning up this part of […]

by mariuz at July 20, 2014 11:23 AM

July 19, 2014

The Wiert Corner - irregular stream of stuff

jpluimers

Though fully justified text is most often in print, and not much in user interfaces any more, this might come in useful one day (it is based on the GDI functions TextOut and SetTextJustification):

David Millington Posted: Have you ever wanted to draw fully justified text ie, text that adheres to both the left and right sides of the destination rectangle? It’s more complicated than it seems, and there’s definitely no inbuilt support in the VCL. But here’s how to do it, including an open-source unit you can drop into your applications and use.

Drawing fully justified text to a canvas | Parnassus – Delphi Consulting & Plugins.

–jeroen

via:


Filed under: Delphi, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 7, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Development, Software Development

by Jeroen Pluimers at July 19, 2014 08:20 AM

jed-software.com

FireMonkey – TArc and Retina, not the best of friends

Last week I noticed a post on www.fmxexpress.com that showed a different UI for a progress bar. So instead of starting work on something I should have, I turned the code into a component and added the ability to change the colours used when displayed.

I’d known TArc didn’t render nicely on a Retina device because I was using it to render a navigation UI concept. Which I’ve had to shelve because of this issue.

The control does look good under other platforms (untested under Android – issues not anticipated though).

You can download the full source code for the control from the Quality Central report lodged for the rendering issue. It looks like you will need to use a native client to download from the QC report as it doesn’t look like you can from the web client.

The control has the following “license” in the main unit:

{

TCircleProgress is based on code made open source by developer OneChen.

Original Code Link: https://github.com/OneChen/ProgressCircle
How I found out link: http://www.fmxexpress.com/build-a-progress-spinner-using-objects-in-delphi-xe6-firemonkey-on-android-and-ios/

Developer of this component: Jeremy North (jeremy.north@gmail.com)

DO NOT PAY FOR THIS COMPONENT. DONATE TO THE ORIGINAL AUTHOR OF THE IDEA IF YOU WANT TO CONTRIBUTE.

Disclaimer: This code is provided free of charge, bugs and all.

}

 

Windows

 

The Windows capture actually shows another drawing bug with FireMonkey. Notice how the rectangle at the top has two black dots in the top left and top right corners. This happens when you eliminate sides from a rectangle and maintain one full side to be drawn. Something that I’ve reported previously.

Report No: 122616 (RAID: 47827) Status: Open
Removing Sides can leave unwanted dots in corners
http://qc.embarcadero.com/wc/qcmain.aspx?d=122616

 

OS X

 

iOS

 

NOTE: This isn’t an issue for just TArc though, it is an issue with the GPU canvas. In previous versions, you could disable the usage of the GPU canvas, however with XE6 – the option to switch it off has been deprecated.

 

Zoomed view under iOS

 

Report No: 126186 (RAID: 52756) Status: Open
[Retina] [iOS] TArc doesn’t rendering nicely on a Retina device
http://qc.embarcadero.com/wc/qcmain.aspx?d=126186

 

Reported and opened. Hopefully in the next release, this rendering issue is addressed.

by JED at July 19, 2014 05:37 AM

July 17, 2014

The Wiert Corner - irregular stream of stuff

jpluimers

I observe an increase of people not asking questions on Stack Overflow any more…

Today, two interesting questions caught my eye.

The first one was by Martijn Coppoolse about Is it possible to figure out whether a type’s property has a ‘stored’ flag or not, preferably without having to create an instance of that type? (note: emphasis is mine)

Then the most interesting one (note this is about old Turbo Pascal style object syntax that is still available in Delphi, yes polymorphism with the object keyword): Could you please remind me if Objects support polymorphism? by Roman Yankovsky.

–jeroen

PS: Martijn posted the solution he used:

So I tried looking at the StoredProc pointer, and I can differentiate between three states:
  1. nil, which means stored False;
  2. Pointer(1), which means that no stored flag was specified;
  3. an actual pointer, which means that a method was specified; and the pointer seems to point at the relevant method’s CodeAddress. However, we always use private methods for that, and those don’t seem to be enumerated by GetMethods.

Still, those three states are basically what I needed: don’t include an element when StoredProc = nil; when StoredProc = Pointer(1) make it compulsory, and make it optional otherwise when it’s a pointer.
Thanks a lot to all who helped! +Qing-Shan Xiao +Jeroen Wiert Pluimers +Asbjørn Heid

–jeroen


Filed under: Delphi, Delphi 7, Development, Software Development

by Jeroen Pluimers at July 17, 2014 07:47 PM

Firebird News

Jaybird 3.0 snapshot available for testing

Mark Rotteveel published a snapshot of Jaybird 3.0 for testing purposes. This is a very early snapshot, a lot of work still needs to be done before Jaybird 3.0 will be release-ready. We’d appreciate your feedback, but we’d like to emphasize that this version is unstable and not ready for production. The protocol implementation has […]

by mariuz at July 17, 2014 08:52 AM

The Wiert Corner - irregular stream of stuff

jpluimers

I’m not a real expert on LCID (the values like 1033 (aka 0×409 or $409) and 1043 (aka 0×413 or $413), but here are a few notes on stuff that I wrote a while ago to obtain shell32.dll resource strings for various LCIDs.

The most often used way to load resource strings is by calling the LoadString Windows API call which loads the string for the currently defined LCID.

To get them for a different LCID, there are two ways:

  1. Set the LCID for the current thread (don’t forget to notify the Delphi RTL you did this, and update FormatSettings)
  2. Write an alternative for LoadString that gets a string for a specific LCID (so you can keep the current thread in a different LCID)

The first method – altering the LCID of the current thread – is done using SetThreadLocale in Windows XP or earlier, and SetThreadUILanguage in Windows Vista/2008 and up (I’m not sure on the timeline of Windows Server versions, but I guess the split is between 2003 and 2008) as mentioned at SetThreadLocale and SetThreadUILanguage for Localization on Windows XP and Vista | words.

SetThreadLocale is deprecated, as Windows has started switching from LCID to Locale Names. This can cause odd behaviour in at least Delphi versions 2010, XE and XE2. See the answers at delphi – GetThreadLocale returns different value than GetUserDefaultLCID? for more information.

But even on XP it has the potential drawback of selecting language ID 0 (LANG_NEUTRAL) which selects the English language if it is available (as that is in the default search order). Both Writing Win32 Multilingual User Interface Applications and the answers to LoadString works only if I don’t have an English string table and Windows skipping language-specific resources and the Embarcadero Discussion Forums: How to load specific locale settingsd thread that describe this behaviour.

To work around that, you can do two things: store your resource strings in locale dependent DLLs, or (if you don’t write those DLLs yourself), write an alternative for LoadString.

I’ve done the latter for Delphi, so I could load strings for a specific LCID from the Shell32.dll.

For a full overview of all these strings, see http://www.angelfire.com/space/ceedee/shell32stringtables.txt

A few pieces of code.

You can get the full code at the BeSharp – Source Code Changeset 100520.

First a wrapper around LoadString that returns a Delphi String: pretty basic stuff like most Windows API wrappers returning a string with a character buffer and a “SetString(Result, …)” construct.

class function TStringResources.LoadString(const hInstance: HMODULE; const uId: UINT): string;
var
  Buffer: array [0 .. 1023] of char;  // reasonable length; might increase for really long resource strings.
  StringLength: Integer;
begin
  StringLength := Winapi.Windows.LoadString(hInstance, uId, Buffer, Length(Buffer));
  SetString(Result, Buffer, StringLength);
end;

Now the functions that loads the string for a specific ID and a specific LCID.

This one is a bit complex, and based on these posts (some as old as 2004):

Within the bucket, each string consists of a 2 byte length, followed (if length is bigger than zero) by length number of 2-byte characters.

A few more remarks that have nothing to do with STRINGTABLE, but more about how anciant 16-bit Windows API calls translate into the modern world:

  • LockResource is not a lock, but translates a handle into a memory pointer.
  • UnlockResource is a NOP in Win32, so no need to check result and perform RaiseLastOSError();
  • FreeResource in Win32 will return false, so no need to check result and perform RaiseLastOSError();
class function TStringResources.FindStringResourceEx(const hInstance: HMODULE; const uId, langId: UINT): string;
const
  StringsPerBucket = 16;
var
  BucketWideCharsPointer: LPCWSTR;
  BucketResourceHandle: HRSRC;
  BucketGlobalHandle: HGLOBAL;
  BucketPointer: Pointer;
  i: UINT;
  BucketNumber: Cardinal;
  BucketIntResource: PWideChar;
  IndexInBucket: UINT;
  StringLengthPointer: PWord;
  StringLength: Word;
begin
  Result := ''; // assume failure
  // Convert the string ID into a bundle number
  BucketNumber := uId div StringsPerBucket + 1;
  BucketIntResource := MAKEINTRESOURCE(BucketNumber);
  BucketResourceHandle := FindResourceEx(hInstance, RT_STRING, BucketIntResource, langId);
  if (BucketResourceHandle <> 0) then
  begin
    BucketGlobalHandle := LoadResource(hInstance, BucketResourceHandle);
    if (BucketGlobalHandle <> 0) then
    begin
      BucketPointer := LockResource(BucketGlobalHandle);
      BucketWideCharsPointer := LPCWSTR(BucketPointer);
      if (BucketWideCharsPointer <> nil) then
      begin
        // okay now walk the string table
        IndexInBucket := (uId and (StringsPerBucket - 1));
        for i := 1 to IndexInBucket do // skip n-1 entries
        begin
          StringLengthPointer := PWord(BucketWideCharsPointer);
          StringLength := StringLengthPointer^;
          Inc(BucketWideCharsPointer); // skip the length Word
          Inc(BucketWideCharsPointer, StringLength); // skip the content
        end;
        StringLengthPointer := PWord(BucketWideCharsPointer);
        StringLength := StringLengthPointer^;
        Inc(BucketWideCharsPointer); // skip the length Word
        if StringLength <> 0 then
          Result := Copy(BucketWideCharsPointer, 1, StringLength);
        UnlockResource(BucketGlobalHandle)
      end;
      FreeResource(BucketGlobalHandle);
    end;
  end;
end;

Finally a function that tries to find an ID for a string and a specific LCID.

The logic is pretty simple: try all IDs, and find a string that matches the ID. If it matches, return that ID.

class function TStringResources.FindResourceStringId(const resource_handle : HMODULE; const search_resource_string: string; const langId: UINT): UINT;
var
  resource_id: UINT;
  i: Word;
  resource_string: string;
  compare_string: string;
begin
  resource_id := High(resource_id);
  for i := Low(i) to High(i) do
  begin
    resource_string := FindStringResourceEx(resource_handle, i, langId);
    compare_string := Copy(resource_string, Length(search_resource_string));
    if (resource_string <> '') and (SameStr(resource_string, compare_string))
    then
      resource_id := i;
  end;
  Result := resource_id;
end;

Finally a few notes on LCIDs, not the least so see how scattered the information is:

  1. You can add an Excel specific LCID (locale identifier) to a format. Without it, it will use the user's locale settings.
  2. You can ommit the language hint (like [ENG]) from the formatting.
  3. The Excel LCID is very similar to the LCID Structure using hexadecimal values from the (old now defunct Locale ID Chart and replaced by the new) Microsoft Locale ID Values,  Language Identifier Constants and Strings table or list of Locale IDs Assigned by Microsoft, but with a few twists.
  4. A Locale ID consists of 4 bytes: 16 bits for the Language ID, 4 bits for the Sort ID, and 12 unused bits: Locale
    Identifiers (Windows)
    .
    The MAKELCID macro takes the Language ID and Sort ID to create a LCID.
    The LANGIDFROMLCID macro and SORTIDFROMLCID macro extracts the 2 IDs from the LCID.
  5. The language itself consists of a primary language (10 bits) and a sublanguage (5 bits) as shown in Language Identifiers (Windows).
    You assemble them using the MAKELANGID macro.
    The PRIMARYLANGID macro and SUBLANGID macro brings you back the parts.
    A list of primary and sublanguages is at Language Identifier Constants and Strings (Windows).
  6. The LCID structure (it actually is a 4 byte structure containing a Sort ID and a LanguageID) is explained at 2.2 LCID Structure together with list of Sort IDs and Language IDs.
  7. A list of LCID and supported operating systems (from Windows NT 3.51 until Windows 8) is at 5 Appendix A: Product Behavior with columns Language, Location (or type), LCID, Name and Supported Windows/ELK Version.
  8. A 2005 list of Microsoft Locale ID Values.
  9. Locale IDs Assigned by Microsoft.
  10. Table of LCID, language name, etc for various versions of Windows (7, Vista, 2003, XP) at National Language Support (NLS) API Reference.
  11. LCIDs supported on Older Versions of Windows (Windows 2000 back to DOS 6.x).

And one more: if you really like i18n, L10n and such: read Michael Kaplan's blog.

Edit: Michael's MSDN blog is officially dead, but there are the nice web archive and web cache virtues:

--jeroen


Filed under: Delphi, Delphi XE2, Delphi XE3, Delphi XE4, Development, i18n internatiolanization and L10 Localization, Software Development

by Jeroen Pluimers at July 17, 2014 05:00 AM

July 16, 2014

Andy's Blog and Tools

Cause for rlink32 Too many resources to handle

If you have many DFM files and RES files in your project you may run into the rlink32 error “Too many resources to handle”. Every DFM file is one resource and a RES file can contain multiple resources. All together must not exceed 3626 resources.

This limit comes from how rlink32 pre-allocates memory for all resources.  The following pseudo code shows the memory allocator.

function AllocateResourceArray(var AllocatedSize: Word): PResourceArray;
var
  Size: Integer;
begin
  Size := $FF00;
  repeat
    Result := GetMemory(Size);
    if Result <> nil then
    begin
      AllocatedSize := Size;
      Exit;
    end;
    Dec(Size, $400);
  until Size < $400;
  AllocatedSize := 0;
end;

As you can see the max. number of bytes for the whole resource array is limited by $FF00 (65280) bytes. A resource array item’s size is 18 Bytes. That makes 3626 items. If the memory allocator can’t allocate enough memory it tries to allocate again with 1024 bytes less. So the max. number of resources can be lower than 3626. But wait, we have 2014 and not 1992 (rlink32.dll’s copyright message) and RAM is like sand on the beach, at least some developer think that. The 64KB age is long gone, but due to this function rlink32 will fail with “Too many resources to handle” if the 3627’s resource is processed.

There is an easy fix without much code change:
Change the var-parameter from “Word” to “LongWord” and set the initial size to $11FFDC (1,179,612 bytes) which makes room for 65534 resource items which should be enough at the moment. Adjust the code that calls into this function (there is only one call). Recompile rlink32.dll.

Unfortunately I can’t recompile rlink32.dll due to the lack of source code, so I need to patch the machine code. And changing the data type from “Word” to “LongWord” isn’t that easy as you have to patch a lot more places that the compiler would just generate for you (fortunately the 32-bit opcodes are usually smaller than the 16-bit opcodes).

This bug fix for the rlink32 error will be in the next version 5.7 of IDE Fix Pack (for the IDE compiler) and fastdcc (for the command line compiler).

by Andreas Hausladen at July 16, 2014 09:19 PM

The Wiert Corner - irregular stream of stuff

jpluimers

I used to forget about the difference between Variant and OleVariant, and used them like this:

Use OleVariants for OLE, and Variants for non OLE.

There is no need to manually clear them.

Luckily I was right, as the differences are documented in the Delphi on-line help at OLE-compatible Variant type (the oldest I could find was the Delphi 2010 OleVariant documentation):

OleVariant is an OLE-compatible Variant. The main difference between Variant and OleVariant is that Variant can contain data types that only the current application knows what to do with. OleVariant can only contain data types defined as compatible with OLE Automation, which means that contained data types can be passed between programs or across the network without worrying about whether the other end will know how to handle the data.

When you assign a Variant that contains custom data (such as a Delphi string, or one of the new custom variant types) to an OleVariant, the runtime library tries to convert the Variant into one of the OleVariant standard data types (such as a Delphi string converts to an OLE BSTR string). For example, if a Variant containing an AnsiString is assigned to an OleVariant, the AnsiString becomes a WideString. The same is true when passing a Variant to an OleVariant function parameter.

–jeroen

via: System.OleVariant – RAD Studio API Documentation.


Filed under: Delphi, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development

by Jeroen Pluimers at July 16, 2014 05:00 AM

July 15, 2014

Firebird News

Deadline for submiting papers to international conference

Today, 15/July, is the deadline to submit talks proposals for the Firebird International Conference, to happen in Prague, in the end of October. More information here.

by Cantu at July 15, 2014 01:57 PM

July 14, 2014

Firebird News

Final part of the story with 1.7 Terabyte Firebird SQL database

Tuning 1.7 Terabyte FirebirdSQL database (part 3) For those who did not read the first 2 parts: Firebird Performance Degradation (part 1) More details about 1.7Tb database (part 2)

by IBSurgeon News at July 14, 2014 03:23 PM

The road to Delphi

VCL Styles for NSIS

Important Update

The new location of this project is https://code.google.com/p/vcl-styles-plugins/

NSIS

The VCL Styles Utils project, now includes  a plugin (dll) to skin the installers created by NSIS (2.46 and 3.0). The current size of the plugin is about 1.6 mb, but when is included (and compressed) in the script only add ~550 Kb to the final installer.

output_A6NOFn

How to use it

To use the plugin in a NSIS installer you must call the LoadVCLStyle function passing the skin name in the .onInit function.

Function .onInit
  InitPluginsDir
  ;Get the skin file to use
  File /oname=$PLUGINSDIR\Amakrits.vsf "..\Styles\Amakrits.vsf"
  ;Load the skin using the LoadVCLStyle function
  NSISVCLStyles::LoadVCLStyle $PLUGINSDIR\Amakrits.vsf
FunctionEnd

To use the plugin in a NSIS Uninstaller you must call the LoadVCLStyle function passing the skin name in the un.onInit function.

Function un.onInit
  InitPluginsDir
  File /oname=$PLUGINSDIR\Amakrits.vsf "..\Styles\Amakrits.vsf"
  ;Load the skin using the LoadVCLStyle function
  NSISVCLStyles::LoadVCLStyle $PLUGINSDIR\Amakrits.vsf
FunctionEnd

For download and more info check the page of the plugin


by Rodrigo at July 14, 2014 04:09 AM

July 12, 2014

twm’s blog

Adding fields to a TDataset in code

The Delphi IDE allows you to add fields to a TDataset (descendant e.g. TTable, TQuery, TAdoTable etc.) by right clicking on the component and selecting “Add Field” or “New Field”. For a particular project I didn’t want to do that because I kept changing the query for which I want to add the fields. But since there was one calculated field I had to add fields to the dataset otherwise the OnCalcFields event wouldn’t be called. So I ended up adding the fields in code.

Basically that’s easy, you just create a TField descendant (e.g. TStringField,TAutoIncField, TDateTimeField etc.) set the field name and dataset and that’s it. But there are some pitfalls:

var
  fld: TField;
  ds: TDataset;
begin
  // init Dataset
  // ...
  // add fields
  fld := TWideStringField.Create(ds);
  fld.Name := '';
  fld.FieldName := 'TE_Employee';
  ds.Fields.Add(fld);

While this looks fine, it will not work. You will get the error “Field does not have a dataset” (or similar, I don’t remember the exact error message). The reason is that adding the field to the Dataset’s Fields collection does not automatically tell the field to which dataset it belongs. For that you need to assign the field’s Dataset property.

var
  fld: TField;
  ds: TDataset;
begin
  // init Dataset
  // ...
  // add fields
  fld := TWideStringField.Create(ds);
  fld.Name := '';
  fld.FieldName := 'TE_Employee';
  fld.Dataset := ds;
  ds.Fields.Add(fld);

If you write it like this, it will seem to work, but you will get an access violation when the dataset is being destroyed. Can you spot why?

I had to trace into the RTL sources to find the problem: The field was added to the Fields collection twice, because setting its Dataset property also adds it to the Fields collection. So, when the field’s collection got freed, the Field was freed twice, resulting in the AV.

So the correct and working code is this:

var
  fld: TField;
  ds: TDataset;
begin
  // init Dataset
  // ...
  // add fields
  fld := TWideStringField.Create(ds);
  fld.Name := '';
  fld.FieldName := 'TE_Employee';
  fld.Dataset := ds; // this automatically adds the field to the Dataset's Fields collection.

You might be wondering about the line

  fld.Name := '';

I set the name of all components created in code to an empty string to avoid name collisions with any existing components or even a different instance of the component created by the same code. “A component with the name Edit1 already exists.” has bitten me too often.

Since I also used a TDbGrid to display the dataset, I also added Columns to the DBGrid to set the caption and column width. And since I am lazy (as any good programmer should be), I moved most of that code into a (sub-) procedure to make the code more readable (actually I did it so I had less to type, but the result is the same):

var
  TheDataset: TDataset;
  TheGrid: TDbGrid;

procedure TMyForm.InitDbGrid;

  procedure AddField(_fld: TField; const _Fieldname: string; const _Caption: string; _Width: Integer);
  var
    Col: TColumn;
  begin
    _fld.FieldName := _Fieldname;
    _fld.ReadOnly := True;
    _fld.Dataset := TheDataset;
    Col := TheGrid.Columns.Add;
    Col.Expanded := False;
    Col.FieldName := _Fieldname;
    Col.Title.Caption := _Caption;
    Col.Width := _Width;
  end;

begin
  AddField(TAutoIncField.Create(nil), 'SeNr', _('Number'), 50);
  AddField(TDateTimeField.Create(nil), 'TeArbeitstag', _('Date'), 70);
  AddField(TWideStringField.Create(nil), 'SeVon', _('Start'), 40);
  AddField(TWideStringField.Create(nil), 'SeBis', _('End'), 40);
  fld := TWideStringField.Create(nil);
  fld.FieldKind := fkCalculated;
  AddField(fld, 'Stunden', _('Hours'), 50);
  AddField(TWideStringField.Create(nil), 'PROJ_IDENT', _('Project'), 50);
  AddField(TWideStringField.Create(nil), 'SSchluessel', _('Activity'), 50);
  AddField(TWideStringField.Create(nil), 'SeBeschreibung', _('Description'), 200);
  ResizeGridColumns;
end;

And just to show why this code is actually useful, here are the ResizeGridColumns method and TheDatasetCalcFields and FormResize events.

procedure TMyForm.ResizeGridColumns;
var
  cnt: Integer;
  TotalWidth: Integer;
  i: Integer;
begin
  TotalWidth := 0;
  cnt := TheGrid.Columns.Count;
  for i := 0 to cnt - 2 do begin
    TotalWidth := TotalWidth + TheGrid.Columns[i].Width;
  end;
  TheGrid.Columns[cnt - 1].Width := TheGrid.ClientWidth - TotalWidth - 50;
end;

procedure TMyForm.FormResize(Sender: TObject);
begin
  ResizeGridColumns;
end;

procedure TMyForm.TheDatasetCalcFields(Dataset: TDataSet);
var
  Von: TdzNullableTime;
  Bis: TdzNullableTime;
begin
  Von.AssignVariant(Dataset['seVon']);
  Bis.AssignVariant(Dataset['seBis']);
  Dataset.FieldByName('Stunden').Value := (Bis - Von).ToHourStr(2);
end;

(TdzNullableTime is an extended record type from my dzlib library which is available from sourceforge if you are interested. It is declared in u_dzNullableTime.pas.

by dummzeuch at July 12, 2014 03:42 PM

July 11, 2014

The Podcast at Delphi.org

Skill Sprint: Android Voice – Speech Recognition and TTS

Androids can talk and listen!For my Developer Skill Sprint I was originally scheduled to show how to do a Google Glass Voice Trigger. That is pretty cool because it allows you to launch a Google Glass app with your voice, but I decided to expand on that to also show how the Google Glass app can be launched with the results of additional voice input, as well as how to take dictation and do text to speech everywhere else in Android.

I’ve still got a lot of work to do on the components, but they work as is for now. If you want to modify the component code then take a look at my Skill Sprint and blog post on the Android JNI Bridge.

 

by Jim McKeeth at July 11, 2014 07:19 PM

The road to Delphi

Delphi IDE Colorizer – Open Beta

A few months ago I started to work on a new project called Delphi IDE Colorizer. In the past weeks a beta version was tested for a dozen of Delphi developers on a closed beta. Now it’s time to move forward and a open beta version of the plugin is available. Check the next images and videos which provide a description of the Wizard.

Introduction

The Delphi IDE Colorizer (DIC) is a Wizard which allows to customize the look and feel of the workspace of the RAD Studio IDE.

Some of the features of the plugin are

  • DIC is compatible with RAD Studio XE, XE2, XE3, XE4, XE5, X6.
  • Transparent menus
  • Allow to change the icons, set the colors, and gradient direction of the title bar of the docked windows
  • Set the colors, and gradient direction of the toolbars.
  • Improve the drawing of the disabled icons used in menus and toolbars
  • Compatible with CnWizards and GExperts
  • Replace the icons used in the gutter and the debugger.
  • Includes 90+ themes.

Download

Before to download please read the FAQ of the plugin.
For download the wizard check the page of the project.

Check the next sample images
DeepskyBlue_default_layout

YellowGreen_debug_layout_assembly

DIC_Transparent_Menus

DIC_VCLStyles_Menus


by Rodrigo at July 11, 2014 05:15 PM

DIC now supports VCL Styles

I just released a major update to the Delphi IDE Colorizer adding VCL Styles support. So now you can style the non client area of the floating forms of the IDE and also use the elements of the VCL Styles on the RAD Studio IDE.

The next image shows how the VCL Styles are enabled on the wizard and which elements can you choose, for example you can select only style the forms with the VCL Styles and use the current theme settings for draw the controls and menus.

2014_07_07_23_00_55_Delphi_IDE_Colorizer_Settings

Check the full list of features on this page.

Check the next Video which show how the new feature works.


by Rodrigo at July 11, 2014 12:15 AM

July 08, 2014

The Podcast at Delphi.org

Android JNI Bridge and Custom Classes.dex

By creating a custom Classes.dex you can get access to 3rd party Java JAR APIs from your application. For my Integrate More Android with a JNI Call to your Android App Developer Skill Sprint I created a demo app that demonstrates creating a custom Classes.dex. This is a new feature in XE6 and Appmethod 1.14. [Download the demo] [Download the slides] The Demo app uses the Base64Coder JAR file (included). To build the demo:

  1. Examine the createdex.bat file to make sure it refers to the correct location for your dx.bat utility and the fmx.jar & android-support-v4.jar files.
  2. Run the createdex.bat file to create the classes.dex file which includes the two jar files above, plus the base64coder.jar file.
  3. Double check that the Deployment Manager references the new classes.dex and not the old ones, and that the remote path is “classes\”
  4. Notice that the android.JNI.Base64Coder.pas file wraps and exposes the methods of the base64coder class.
  5. Run the app on your Android device and verify that it works as expected.

The Base64Coder.JAR is Android specific, so it will not work on iOS or Windows. Some additional notes from the Developer Skill Sprint: Some useful units for making JNI calls

  • Androidapi.Jni – Java Native Interface type definitions
  • Androidapi.JNIBridge – The JNI Bridge
  • Androidapi.JNI.JavaTypes – JString and other common types.
  • Androidapi.Helpers – JStringToString and other useful conversions.
  • FMX.Platform.Android– Useful platform methods like GetAndroidApp, MainActivity and ConvertPointToPixel
  • Others useful units: Androidapi.AppGlue, Androidapi.JNIMarshal, Androidapi.JNI.Embarcadero
  • For more see: C:\Program Files (x86)\Embarcadero\Studio\14.0\source\rtl\android (Object Pascal) and C:\Program Files (x86)\Embarcadero\Studio\14.0\include\android\rtl (C++)

You will want to make use of Conditional Defines in Object Pascal and Predefined Macros in C++. In my blog post on Android Settings I showed how to make a JNI call with Object Pascal, but you can also look at the DeviceInfo Mobile Code Snippet in both C++ and Object Pascal. To create your own JNI Bridge wrappers, look at the source code in C:\Program Files (x86)\Embarcadero\Studio\14.0\source\rtl\android (Object Pascal) and C:\Program Files (x86)\Embarcadero\Studio\14.0\include\android\rtl (C++). You can also consider the following 3rd party utilities:

If you just want to include standard Android APIs then check out the FMXExpress (also an Embarcadero MVP) project on GitHub that includes all the Android APIs. Here is the video replay of my skill sprint

Also, check out Brian Long’s video on accessing the Android API with XE5

by Jim McKeeth at July 08, 2014 08:34 AM

July 07, 2014

Smart Mobile StudioSmart Mobile Studio

Smart Mobile Studio 1.1 RC (build 1.1.0.400)

We are very proud to present the release candidate for Smart Mobile Studio version 1.1  (build number v1.1.0.400). If you would like to give this groundbreaking product a test drive before we officially release it, then you can download the installer directly from SmartMobileStudio.com/download/setup_v1_1_0_400_rc.exe (The context menu is replaced with Ctrl+Shift+R (start/stop recording) and Ctrl+Shift+P [...]

The post Smart Mobile Studio 1.1 RC (build 1.1.0.400) appeared first on Smart Mobile Studio.

by Smart Mobile Studio Team at July 07, 2014 09:01 AM

July 06, 2014

Castle Game Engine news

We introduce a "build tool" for our engine, to make it easy to compile and package your games. The build...

We introduce a "build tool" for our engine, to make it easy to compile and package your games. The build tool, called "castle-engine", reads a CastleEngineManifest.xml file in your project, and can handle common operations (like compilation and packaging) for you. It wraps the compilation process (calling FPC with proper options underneath), and it can package a ready project (right now to zip (Windows) or tar.gz (Linux and other Unixes), easy packaging for Android is coming). Details are on https://sourceforge.net/p/castle-engine/wiki/Build%20tool/ .

Other improvements to the engine API from last months:

* Various 2D improvements, most notably: TCastleImage.Resize3x3 (resize images preserving corners, useful together with TGLImage.Draw3x3), TCastleImage.FlipVertical, TVideo.FlipHorizontal and TVideo.FlipVertical, TCastleLabel.Frame.

* Comfortable class helpers for TDOMElement, see AttributeXxx methods in CastleXMLUtils.

* Wavefront OBJ reading: handle negative indexes and concave faces.

* Add TCastleUIContainer.ForceCaptureInput, to reliably capture mouse look by a viewport that does not necessarily fill the whole window.

* Numerous smaller API improvements, like SmoothStep utility, TWalkCamera.MoveForward/Backward.

July 06, 2014 07:55 PM

July 05, 2014

twm’s blog

GORM experimental release

GORM is an editor for .po files that was originally written by Lars Dybdahl and to which I have been contributing quite a few features in recent years. Since Lars is too busy to do a release and currently even the original download doesn’t seem to work, I have compiled the current sources and provide a download here:

Gorm_2014-07-05.zip

In addition to the features described on the Gorm homepage this new version can do the following:

  • Edit the po file header.
  • Auto translate, using Google translate (not sure whether it is still available) or Microsoft Translator. Both need an application key that is not part of Gorm.
  • Auto translate from a local translation repository, which is an MS Access database, one per language, that can be shared by multiple developers
  • Auto translate using translation memory, that is a po file that is automatically generated.
  • Load and save translations to be ignored from a ignore.po file.
  • In addition to English, I provide it with German localization, that, of course, is created with Gorm itself.

The sources are available from the dxgettext repository on sourceforge.
Of course I like Gorm much better than PoEdit and other alternatives. If there are any bugs, that’s probably my fault.

by dummzeuch at July 05, 2014 04:59 PM

July 03, 2014

The Wiert Corner - irregular stream of stuff

jpluimers

Joseph G. Mitzen posted a very interesting (and elaborate <g>) comment on a post from me in 2009: Delphi – for … in on enumerated data types « The Wiert Corner – irregular stream of stuff.

The crux of his post is about consistency of your tools. And clearly, the Delphi team has some work to do in that regard especially when compared to the Python world where consistency is key (and takes a lot of time to introduce new features as a side effect).

He refers to the ADUG post For-in Enumeration | Australian Delphi User Group Members by DaddyHPriest that lists a number of areas where Delphi does not have enumerator support for.

Which reminds me I promised to publish some more enumeration demos showing what kind of code could be eliminated if things became more consistent.

Hopefully this summer gives me a bit more time for that (:

–jeroen

via: Delphi – for … in on enumerated data types « The Wiert Corner – irregular stream of stuff.


Filed under: Delphi, Delphi 2007, Delphi 2009, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development

by Jeroen Pluimers at July 03, 2014 11:00 AM

July 01, 2014

The Podcast at Delphi.org

Integrate Cloud Services with the REST/JSON Client

As part of the free Developer Skill Sprint on REST & JSON here are my slides and sample source code. Appmethod, RAD Studio, Delphi & C++Builder XE6 ship with the Desktop sample RESTDemos sample which includes examples for:

  • Twitter
  • Facebook
  • Google Tasks
  • Foursquare
  • Dropbox
  • Plus Some others

That includes both OAuth1 and OAuth2 usage. My Dropbox demo is a mobile app written in both C++ and Object Pascal. It uses OAuth2 and the mobile TWebBrowser to perform the authentication. You can view and download the slides as well. Useful links:

So upgrade to XE6 or download the trial today.

by Jim McKeeth at July 01, 2014 05:58 PM

twm’s blog

Comparing Variants

I hate Variants, did I say that before? They just make everything more complex than necessary.

Did you ever try to compare two variants? E.g. you have got one that contains an empty string (”) and another that contains a date. Now you want to know whether they are equal or not. Simple?

  v1 := '';
  v2 := EncodeDate(2014,07,01);
  if v1 
 v2 then
    WriteLn('not equal')
  else
    WriteLn('equal');

Not so. The code above raised a EVariantConversionError exception because it could not convert an empty string into a date.

Let me introduce you to two Delphi RTL functions from Variants.pas:

VarSameValue and VarCompareValue.

(I bet you didn’t know about them, did you?)

Assuming these functions work as described, the above must be written like this:

  v1 := '';
  v2 := EncodeDate(2014,07,01);
  if not VarSameValue(v1, v2) then
    WriteLn('not equal')
  else
    WriteLn('equal');

Unfortunately they fail as well with exactly the same error. So all that’s left is implementing it myself.

function VarIsSame(_A, _B: Variant): Boolean;
var
  LA, LB: TVarData;
begin
  LA := FindVarData(_A)^;
  LB := FindVarData(_B)^;
  if LA.VType 
 LB.VType then
    Result := False
  else
    Result := (_A = _B);
end;

Note that this too might not do what you expect:

  VarIsSame('3', 3);

will return false! That’s why it’s called VarIsSame rather than VarIsSameValue. It doesn’t try to convert variants of different types, it just checks whether they are the same.
For my use case this is exactly what I need.

Did I mention that I hate Variants?

by dummzeuch at July 01, 2014 12:35 PM

June 30, 2014

Firebird News

FireServer site is online!

The official site for the FireServer Project is now on-line! You can find basic information about the project. There are no ISO downloads available yet. We expect to have the first ISO until the end of August.

by Cantu at June 30, 2014 09:01 PM

June 28, 2014

twm’s blog

Comparing INI files

INI files are a simple but powerful means of storing a program’s configuration. They have existed since the 16 bit Windows times, where they were stored in the Windows directory, later on they were stored in the program’s executable directory and nowadays they usually go somewhere into a user’s home directory. Microsoft has tried to replace them with more structured storage, first the Registry and later (in dotNEt) with XML files, but they are still popular because they are simple to copy and move around, easy to use and can be edited with a text editor. Programmers and system administrators love this kind of configuration.

They have one problem, though: They tend to get larger than expected and since they are only barely structured, it is rather tedious to compare them. Is there anybody who has not edited an INI file in notepad and changed the order of sections and entries so he can use a tool like Beyond Compare to find the actual differences between two INI files? I have done that a lot more often than I care to remember and it was always painful and slow.

Enter dzIniFileFormatter: This is a tool I wrote actually several years ago but only today remembered that I never blogged about it. It allows to sort sections and entries in two different ways:

  • Alphabetically
  • By Template

Using either it also tries to keep comments where they belong (I use // to mark comments, even though Microsoft proposed a semicolon, but unfortunately the TIniFile implementation in Delphi removes these latter comments while it leaves // comments intact.).

I hope the user interface is self explanatory:

dzIniFileFormatter

The most useful function is probably sorting by template. It allows you to resort e.g. a modified version of an INI file so it matches the original and can easily be compared using the above mentioned Beyond Compare or any other side by side file comparison utility.

The source code (Delphi 2010) is available from the dzIniFileFormatter page on SourceForge and I have just now uploaded a pre-compiled executable. I hope you’ll find this tool as useful as I did. If you have any suggestions, please contact me via google plus (see link in the upper right corner).

by dummzeuch at June 28, 2014 08:29 PM

Weak references – or why you should enable ReportMemoryLeaksOnShutdown

I was enhancing my dzMdbViewer tool with a view that shows the table structure rather than the data of the table, when I out of curiosity added

  ReportMemoryLeaksOnShutdown := True;

to the source code. I found some memory leaks that were easy to fix (and which I would probably have fixed anyway later when reviewing the code).

I continued working on the new functionality and used some rather old code I wrote about 10 years ago (part of dzlib, but only used in a special tool) for it. It allows reading the table structure of an MS Access database and puts it into a structure of interfaces. Everything worked fine, until I closed the program and got gazillions of memory leak reports.

It turned out that back then I had created circular references between these interfaces: Tables were referencing Indexes and Columns, Indexes were referencing Tables and Columns, Columns were referencing Tables and Indexes. Of courses, this had to create memory leaks because the reference counter of a circular reference can never reach 0 so these objects were never freed.

There is a cure for this kind of problem: It’s called weak references. Since the Delphi compiler for desktop (Windows) does not support weak references (The mobile compiler supports it via a [weak] attribute, but that attribute is ignored by the desktop compiler.), it must be implemented in code. I am a lazy bastard, so I turned to Google for an answer. This is an ancient problem, so somebody was bound to have blogged about it. I found several hits on StackOverflow and also this Synopse blog post that covers the problem in depth.

So, the solution was this procedure:

procedure SetWeak(_InterfaceField: PIInterface; const _Value: IInterface);
begin
  PPointer(_InterfaceField)^ := Pointer(_Value);
end;

It is used like this:

type
  TChild = class(TInterfacedObject, IChild)
  private
    FParent: IParent; // This must be a weak reference!
  public
    constructor Create(_Parent: IParent);
    destructor Destroy; override;
  end;

constructor TChild.Create(_Parent: IParent);
begin
  inherited Create;
  SetWeak(@FParent, _Parent);
end;

destructor TChild.Destroy;
begin
  SetWeak(@FParent, Nil);
  inherited;
end;

Assuming that TParent (which implements IParent) maintains a strong reference to its TChild objects via IChild interfaces, but the TChild object also needs a reference to its parent (via an IParent interface), we get a circular reference. To solve this, the FParent reference is declared as a weak reference (which is only a comment) and assigned via the SetWeak procedure. Now, assigning FParent does not increment the reference counter of the parent, so when there are no other references to it, it will get destroyed. When the parent gets destroyed all references to its children also get removed, which in turn triggers the child to be destroyed. The child still maintains the reference to the parent, but it is a weak reference, so it must not decrement the reference counter when FParent gets NILed. So, again, the destructor of TChild must use SetWeak to assign NIL to it.

by dummzeuch at June 28, 2014 08:01 PM

June 25, 2014

Firebird News

Firebird for #Python driver FDB 1.4.1 released with fixes and a few enhancements

FDB release 1.4.1 is out: http://pypi.python.org/pypi/fdb This release fixes some issues found over last year and adds few enhancements. Check out the changelog at http://pythonhosted.org//fdb/changelog.html#version-1-4-1

by mariuz at June 25, 2014 02:43 PM

twm’s blog

Setting the caret in a TMemo

Once in a while you want to set the caret position (aka cursor position) in a TMemo to a given line and character in that line. If you google for it you will find lots of hits that tell you to do the following:

With Memo1 do
    SelStart := Perform(EM_LINEINDEX, Line, 0);

or without the ugly with statement

Memo1.SelStart := Memo1.Perform(EM_LINEINDEX, Line, 0);

But that looks to be at least pre-Delphi 2007 because there already is a TMemo.CaretPos property that does the same:

Memo1.CaretPos := Point(0, Line);

This is a lot easier to understand than the above. Note that you can’t just assign only x or y like this:

Memo1.CaretPos.y := Line; // does not work!

This won’t work, because accessing CaretPos calls a getter method that returns a TPoint value. Changing this value does not change the CaretPos property, you must write the actual CaretPos property.

Unfortunately, while this works fine in general, Borland has introduced a bug in TCustomGrid.Paint that breaks this (both) code. If you have got a TCustomGrid descendant (TStringGrid and friends) on the form or a different form, you might find that the caret of the memo shows at the position where it would be on the grid. See QC 25702 for a description and workaround.
Warning:
The workaround requires you to modify the VCL unit Grids.pas. To do that you should copy it from the Delphi installation to your project’s source code, add it to your project and only then modify it. Otherwise you might end up with a Delphi update overwriting it or even worse, failing to install.

by dummzeuch at June 25, 2014 08:40 AM

June 23, 2014

Firebird News

ANN: CopyCat LiveMirror 1.2

Microtec is pleased to announce a new release of our database mirroring and backup tool : CopyCat LiveMirror version 1.2 ! LiveMirror makes it trivial to setup a one-way replication setup between two Firebird databases, so that you can easily have a reliable, up-to-date backup at your fingertips, at all times. For more information about […]

by jonneve at June 23, 2014 05:00 PM

A few changes and fixes to libfq

There are a few changes to libfq (A Postgresql like api and wrapper for Firebird api)

by mariuz at June 23, 2014 12:00 PM

June 20, 2014

Free Pascal Answers

Free Pascal has been choosen as a project of the month (April)

Free pascal has been choose as project of the month in sourceforge, and they interviewed it’s founder Florian Klaempfl

 

http://sourceforge.net/blog/april-2014-project-of-the-month-free-pascal/


by أبو إياس at June 20, 2014 06:14 AM

June 19, 2014

The road to Delphi

DITE and DIC now supports Appmethod 1.14

I just updated the Delphi IDE Theme Editor and the Delphi IDE Colorizer to support Appmethod 1.14

Check out the next screenshots

Appmethod_1

Appmethod_2

Appmethod_3


by Rodrigo at June 19, 2014 11:08 PM

The Podcast at Delphi.org

Meet Me in Philly at the CodeCamp

Philly.NET CodeCampI’m joining Nick Hodges in King of Prussia, Pennsylvania for the Philly.NET Code Camp 2014 Refactored. I’ll be showing off the latest version of Appmethod, including the Free Forever C++ for Android version. Astute readers may have noticed that my sessions are not on .NET, and the conference isn’t actually in Philadelphia. I’m guessing that is the “Refactored” part.

If you are in the area, stop by and say hi. They still have tickets for the two day event where you can catch all three of Nick and my sessions, and maybe a few others if you are interested.


 

Unit Testing: What it is, Why you should be doing it, and how to do it

Saturday, June 21st, 2014 at 7:30 pm on 

Michael Feathers defines “legacy code” as “code that has no unit tests”. Without unit tests your code is fragile, hard to change, and unreliable. Unit testing is the only way that you can be sure that your code does what it is supposed to do.

This talk discusses the basics of Unit Testing by defining terms, discussing what Unit Testing is and is not, and talking about the best techniques and practices for writing unit tests.

All the demos will be in Delphi code, but the principles all remain the same: There no longer is an excuse for not writing unit tests.


Is Thought the Future of Mobile Input?

Sunday, June 22nd, 2014 at 10:30 am on 

The Brain-Computer Interface (BCI) is a mainstay of science fiction, but devices are appearing today to use our brainwaves as a computer input. Is it practical? How far away is it? What sort of input is possible and where is it being used?

We will look at the roots of the technologies that allow a view of the inner functions of the human mind, as well as the possibilities for direct input to, and augmentation of the mind, perception and thought processes. The process includes real-world examples and a demonstration with volunteers controlling software and hardware with only their thoughts and feelings. Gain an understanding of how this still evolving and largely unknown technology really works, how it can be used, and its longer-term implications.


Sharing Code and UI between iOS and Android

Saturday, June 21st, 2014 at 12:00 pm on 

You want to develop on Android and iOS, but rather not have to recreate your app or UI for each platform. This session shows you how to reuse up to 100% of your code and user interface to create native iOS and Android apps using Appmethod and C++. This isn’t your daddy’s C++ either; it has ARC, enhanced RTTI, visual designer, components and no pointer arithmetic (unless you are really into that).

Examples covering access to device sensors, local data storage and remote services. Also how to create a mobile app that extends the functionality of your desktop apps.


I plan on finding a good authentic Philly Cheesesteak Sandwich while I’m there too!

Philly Cheesesteak Sandwhich

by Jim McKeeth at June 19, 2014 06:27 PM

June 17, 2014

Firebird News

Fireserver Project is coming

Fireserver is a project of a custom linux server distro that includes Firebird as default database server, and can be used freely by any company who want to simplify their customer’s servers administration and support. You can read a full article about the Fireserver project in opensource.com/life/14/6/fireserver-project

by Cantu at June 17, 2014 05:10 PM

Database Workbench 4.4.7 released

Upscene Productions is proud to announce the next version of the popular multi-DBMS development tool: ” Database Workbench 4.4.7 Pro ” For more information, see here. The Free Lite Editions will be released at a later stage. Database Workbench supports: - Borland InterBase (6.x – XE ) - Firebird ( 1.x, 2.x ) - MS […]

by Martijn Tonies at June 17, 2014 02:26 PM

June 16, 2014

Lazarus Team Anouncements

Lazarus 1.2.4 Release

The Lazarus team is glad to announce the release of Lazarus 1.2.4.

This release was built with fpc 2.6.4.
The previous release 1.2.2 was built with 2.6.4 too, the release 1.2.0
was built with fpc 2.6.2.

Here is the list of changes for Lazarus and Free...

June 16, 2014 08:45 PM

Firebird News

Hopper v1.5.1 – stored routine debugger – now available!

Upscene Productions announces a new release of: “Hopper – a Stored Code Debugger” Hopper is a Stored Routine and Trigger Debugger, available for Firebird, InterBase and MySQL. For more information and a trial download, see the news @ Upscene Productions, pricing information is available. Bugfixes include null-handling and improved parameter default handling as well as […]

by Martijn Tonies at June 16, 2014 01:58 PM

June 15, 2014

twm’s blog

Delphi7Help4BDS revisited

Today I updated the Delphi 7 Help for BDS Expert (Delphi7Help4BDS) I wrote back then when Delphi 2005 came out and Borland managed to turn the online help into a mess (again).

It now supports Delphi 2005 to XE6 and allows to reconfigure F1 + any of the modifier keys Shift, Ctrl, Alt and Alt+Ctrl to call either a help file (you will need the old winhelp viewer that Microsoft dropped with (Vista?)), chm file or internet url. It comes preconfigured with a few example internet urls for searching with Google, Bing, the Embarcadero docwiki or MSDN.

To install it, get the sources from SourceForge, open the package for your Delphi version, compile and install it. You should then find a new entry in the IDE’s Help menu called “Configure Delphi7HelpForBds” which gets you the following dialog where you can configure the actions for each of the key combinations.

Delphi7HelpForBdsWizard

by dummzeuch at June 15, 2014 06:16 PM

June 14, 2014

twm’s blog

Adding remote repositories to your mercurial.ini

Among a lot of other things you can add names for remote repositories to your mercurial.ini so you can access them without having to type that long path. This can be quite convenient e.g.

[path]
dzlib=ssh://twm@hg.code.sf.net/p/dzlib/hgdzmaincode

allows me to clone a copy of my dzlib+tools main repository on sourceforge like this:

hg clone dzlib dzlib+tools

rather than having to type:

hg clone ssh://twm@hg.code.sf.net/p/dzlib/hgdzmaincode dzlib+tools

Unfortunately this also tends to add the possibility for undesired side effects. Consider this:

hg clone dzlib dzlib

What is it supposed to do? What I wanted it to do, is simple: Clone the remote repository dzlib (as configured in the [path] section) to the subdirectory dzlib.
What it actually tries to do is: Clone the remote repository dzlib to the remote repository dzlib, which is definitely not what I wanted it to do.

Since I rarely create new clones from the remote repository I have removed the entries in [path] again, because the time potentially spent on troubleshooting these side effects is much longer than having to look up the remote url the few times I actually want to clone a remote repository.

by dummzeuch at June 14, 2014 04:33 PM

Avoiding long timeouts when connecting to Mercurial repositories on SourceForge

As described in a previous post I initially had some problems connecting to Mercurial repositories on SourceForge that went away without me changing anything. In that post I give the following entry for mercurial.ini:

[ui]
ssh="C:\Program Files (x86)\PuTTY\plink.exe" -ssh -agent -v -i "D:\path\to\my\private_key.ppk"

While this works well, if Pageant is already running and has loaded the key, it results in a non responsive console if either of these conditions is missing. This is quite annoying because I tend to forget to start Pageant and it takes me quite a while to realize what the problem is. A little bit of digging into the command line parameters of plink gave me the fix: Add the -batch switch, so it won’t accept any interactive prompts. So it should look like this:

[ui]
ssh="C:\Program Files (x86)\PuTTY\plink.exe" -ssh -batch -agent -v -i "D:\path\to\my\private_key.ppk"

If Pageant is not running or the private key not loaded, any connection attempt will within seconds result in the following error message:

hg incoming
abort: no suitable response from remote hg!

by dummzeuch at June 14, 2014 04:11 PM

June 13, 2014

Firebird News

Firebird SQL syntax for VIM

If you like Vim here is the Syntax Highlighter for Firebird SQL dialect (First version) There is a github project pushed up here: https://github.com/blumf/firebird_vim_syntax Should be pretty simple for most *nix users to use. sudo apt-get install lua5.2 git clone https://github.com/blumf/firebird_vim_syntax.git cd firebird_vim_syntax make make install

by mariuz at June 13, 2014 04:47 PM

June 12, 2014

Firebird News

A few Firebird fixes are commited in LibreOffice git

A few more Firebird fixes are commited in LibreOffice git Fdo#79493 Refresh Tables option fails with Firebird https://bugs.freedesktop.org/show_bug.cgi?id=79493 Fdo#73352 firebird don’t claim to support interfaces one doesn’t https://bugs.freedesktop.org/show_bug.cgi?id=73352 Fdo#74019 – FILEOPEN: Any table or select query having more than 10 fields cannot be opened in a database with embedded FireBird https://bugs.freedesktop.org/show_bug.cgi?id=74019#c19

by mariuz at June 12, 2014 08:49 AM

June 11, 2014

Firebird News

News about Firebird 3 release

Here are some news about the next FB 3 releases time-frame, coming direct from Dmitry Yemanov: We’re approaching Beta 1 (hopefully to be released in July), with one more Beta to follow and then RC appearing this Autumn, probably around the conference time. Firebird Roadmap can be seen here.

by Cantu at June 11, 2014 05:01 PM

The Wiert Corner - irregular stream of stuff

jpluimers

A bit more than a year ago, I wrote about Delphi: you should avoid the `with` statement as it makes your code less future proof. That caused some nice comments on the blog, and some more on LinkedIn where Paul Foster mentioned it in a thread ‘Jeoren Pluimers makes a case against “with” statements.‘ Both interesting reads, especially the reasons that people use or avoid with, or keep its use in balance. There is one set of comments I want to emphasize: refactoring multiple with statements into a one function and a call per former with.

Mark Stolworthy: I think when used simply the code becomes easier to read ?

with pdata do
begin
  DatabaseName := pDB.databasename;
  TableName := 'Xdata';
  readonly:=Preadonly;
  FieldDefs.clear;
  IndexDefs.clear;
end;

with pitem do
begin
  DatabaseName := pDB.databasename;
  TableName := 'Xitem';
  readonly:=Preadonly;
  FieldDefs.clear;
  Indexdefs.clear;
end;

I disagree with code like that, as it is very easily refactored into something like this:

Jeroen Pluimers • @Mark, Your code should be refactored to use a method, similar to the example at http://wiert.me/2013/03/27/delphi-you-should-avoid-the-with-statement-as-it-makes-your-code-less-future-proof/#comment-17355 Also if this is from production code, you should use code-completion to make sure the casing of the members is correct.

Initialize(PData, pDB, 'Xdata', PReadOnly);
Initialize(PItem, pDB, 'Xitem', PReadOnly);

procedure TMyClass.Initialize(MyDataSet: TMyDataSet; MyDataBase: TMyDatabase; string TableName; ReadOnly: Boolean);
begin
  MyDataSet.DatabaseName := MyDataBase.DataBaseName;
  MyDataSet.TableName := TableName;
  MyDataSet.ReadOnly := ReadOnly;
  MyDataSet.FieldDefs.Clear();
  MyDataSet.IndexDefs.Clear();
end;

--jeroen

PS: funny to see I officially hate hate hate the WITH statement got posted this week too, as my post above had been in the blog queue more than a year ago: since 20130505 (:


Filed under: Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development

by Jeroen Pluimers at June 11, 2014 05:00 AM

June 09, 2014

twm’s blog

AutoComplete for TEdits

I am sure you know about the useful controls TJvDirectoryEdit and TJvFilenameEdit from the JVCL. They come in handy whenever you need an edit field that should allow autocomplete for file or directory names. It always irked me that I had to include not only the JVCL but also the JCL in order to just have this autocompletion feature especially since I don’t want the selection buttons that are part of the controls. So, having some time on my hands this weekend I decided to check how it is done and whether it would be possible to get the feature without the JVCL. It turned out to be easy.

But first be warned: What I describe here is not what these controls do. I took the easiest route, losing some of the features along the way.

Windows offers basically out of the box what I want with the SHAutoComplete API function in the Shlwapi.dll. The function takes the handle of an edit control (it also supports the embedded edit control of a combobox) and adds autocompletion to it. Basically all you need to do is call

  SHAutoComplete(_ed.Handle, Options);

Where _ed is some TEdit control and Options is a DWORD containing several flags.

There are two ways of autocompletion:

  • Autosuggest
  • Autoappend

Autosuggest means that the control displays a list of matching items and the user can select one of these using either the mouse or the up/down arrow keys.

Autoappend means that the control automatically appends the first matching item to the user input and selects it, so that it gets overwritten if the user continues typing. The user can use TAB to switch focus to the next control in which case he will accept the suggestion.

Now, to suggest input, the function also needs to know where to get the entries. The function supplies three possible sources:

  • Filesystem
  • URL history
  • URL MRU (most recently used)

The first one is easy: The function tries to match the user’s input with files and directories in the file system, just as TJvFilenameEdit does.

I am not sure about the difference between URL history and URL MRU. I guess they are both about Internet Explorer URLs, but I haven’t tried them because I only wanted to get the lookup behaviour of the aforementioned controls.

I ended up with the following wrapper code for the function:

type
  TAutoCompleteSourceEnum = (acsFileSystem, acsUrlHistory, acsUrlMru);
  TAutoCompleteSourceEnumSet = set of TAutoCompleteSourceEnum;
type
  TAutoCompleteTypeEnum = (actSuggest, actAppend);
  TAutoCompleteTypeEnumSet = set of TAutoCompleteTypeEnum;
type
  TErrorHandlingEnum = (ehReturnFalse, ehRaiseException);
const
  // constants and descriptions from MSDN
  // http://msdn.microsoft.com/en-us/library/windows/desktop/bb759862(v=vs.85).aspx

  // Ignore the registry default and force the AutoAppend feature off.
  // This flag must be used in combination with one or more of the
  // SHACF_FILESYS* or SHACF_URL* flags.
  SHACF_AUTOAPPEND_FORCE_OFF = $80000000;

  // Ignore the registry value and force the AutoAppend feature on. The completed string will be
  // displayed in the edit box with the added characters highlighted.
  // This flag must be used in combination with one or more of the
  // SHACF_FILESYS* or SHACF_URL* flags.
  SHACF_AUTOAPPEND_FORCE_ON = $40000000;

  // Ignore the registry default and force the AutoSuggest feature off.
  // This flag must be used in combination with one or more of the
  // SHACF_FILESYS* or SHACF_URL* flags.
  SHACF_AUTOSUGGEST_FORCE_OFF = $20000000;

  // Ignore the registry value and force the AutoSuggest feature on.
  // A selection of possible completed strings will be displayed as a
  // drop-down list, below the edit box. This flag must be used in
  // combination with one or more of the
  // SHACF_FILESYS* or SHACF_URL* flags.
  SHACF_AUTOSUGGEST_FORCE_ON = $10000000;

  // The default setting, equivalent to
  // SHACF_FILESYSTEM | SHACF_URLALL.
  // SHACF_DEFAULT cannot be combined with any other flags.
  SHACF_DEFAULT = $00000000;

  // Include the file system only.
  SHACF_FILESYS_ONLY = $00000010;

  // Include the file system and directories, UNC servers, and UNC server shares.
  SHACF_FILESYS_DIRS = $00000020;

  // Include the file system and the rest of the Shell (Desktop, Computer, and Control Panel, for example).
  SHACF_FILESYSTEM = $00000001;

  // Include the URLs in the user's History list.
  SHACF_URLHISTORY = $00000002;

  // Include the URLs in the user's Recently Used list.
  SHACF_URLMRU = $00000004;

  // Include the URLs in the users History and Recently Used lists. Equivalent to
  // SHACF_URLHISTORY | SHACF_URLMRU.
  SHACF_URLALL = SHACF_URLHISTORY or SHACF_URLMRU;

  // Allow the user to select from the autosuggest list by pressing the TAB key.
  // If this flag is not set, pressing the TAB key will shift focus to the next
  // control and close the autosuggest list.
  // If SHACF_USETAB is set, pressing the TAB key will select the first item
  // in the list. Pressing TAB again will select the next item in the list,
  // and so on. When the user reaches the end of the list, the next TAB key
  // press will cycle the focus back to the edit control.
  // This flag must be used in combination with one or more of the
  // SHACF_FILESYS* or SHACF_URL*
  // flags
  SHACF_USETAB = $00000008;

  SHACF_VIRTUAL_NAMESPACE = $00000040;

function SHAutoComplete(hwndEdit: HWnd; dwFlags: DWORD): HResult; stdcall; external 'Shlwapi.dll';

function TEdit_SetAutocomplete(_ed: TCustomEdit; _Source: TAutoCompleteSourceEnumSet = [acsFileSystem];
  _Type: TAutoCompleteTypeEnumSet = []; _ErrorHandling: TErrorHandlingEnum = ehReturnFalse): boolean;
var
  Options: DWORD;
  Res: HRESULT;
begin
  Options := 0;
  if acsFileSystem in _Source then
    Options := Options or SHACF_FILESYSTEM;
  if acsUrlHistory in _Source then
    Options := Options or SHACF_URLHISTORY;
  if acsUrlMru in _Source then
    Options := Options or SHACF_URLMRU;
  if actSuggest in _Type then
    Options := Options or SHACF_AUTOSUGGEST_FORCE_ON;
  if actAppend in _Type then
    Options := Options or SHACF_AUTOAPPEND_FORCE_ON;

  Res := SHAutoComplete(_ed.Handle, Options);
  Result := (Res = S_OK);
  if not Result then
    raise EOleException.Create(_('Call to SHAutoComplete failed.'), Res, 'Shlwapi.dll', '', 0);
end;

And I call it like this:

  TEdit_SetAutocomplete(ed_Directory, [acsFileSystem], [actSuggest, actAppend]);

As you can see in the descriptions for the possible Option values, there apparently is a registry entry for setting the default for autocomplete, but I wasn’t able to find out where. Also, for some of the options it’s not obvious, what they do. I wonder what SHACF_VIRTUAL_NAMESPACE is supposed to mean?

Another thing to keep in mind, is that the function does not offer any filtering options, especially it does not distinguish between files and directories, so it is not possible to get the equivalent of TJvDirectoryEdit using this function. In order to get the full functionality of these two JVCL controls, you would have to do what the JVCL developers did (actually that functionality is much older than the JVCL, it originally came from rxlib), and use the IAutoComplete interface described in this answer on StackOverflow. But as I said above: I took the easiest route.

by dummzeuch at June 09, 2014 01:26 PM

Firebird News

Firebird Developers Day

The 11th edition of the Firebird Developers Day (Brazilian) Conference will happen in 30/August, in Piracicaba-SP. More details to be announced soon.

by Cantu at June 09, 2014 12:53 PM

Only 3 days left on our 75% FIFA World Cup discount on all our database development tools!

We’re offering a 75% FIFA World Cup special discount on all our database development products! We’re a company offering several database development tools, our tools include test data generator tools that includes a data library for real-life-like data (useful for volume testing, giving presentations etc), auditing, design, debugging and development tools. Take a look at […]

by Martijn Tonies at June 09, 2014 11:07 AM

Andreano Lanusse | Technology and Software Development

Performance benchmark from Delphi 2010 to Delphi XE6

Thomas Grubb from Words from a Delphi CodeSmith blog, did a fantastic job comparing performance from Delphi 2010 to XE6. His motivation around this benchmark was to validate Delphi Quality, Performance, and Stability (QPS) over the years, specially now where Embarcadero claims a lot of focus on these areas with Delphi XE6 release.

His tests include VCL, FireMonkey, Win32, Win64, Android, iOS, OSX and third party library.

The whole series is based in 12 blog posts as you can se below.

Again, congratulations Thomas for the fantastic job and time invested on that. I think everyone on the Delphi community will appreciate.

Andreano Lanusse | Technology and Software Development
Follow me on Twitter: @andreanolanusse

by Andreano Lanusse at June 09, 2014 05:35 AM

June 08, 2014

Firebird News

Database .NET 11.7 released

Database .NET is an innovative, powerful and intuitive multiple database management tool, With it you can Browse objects, Design tables, Edit rows, Export data and Run queries with a consistent interface. What’s New (2014/06/09) Updated to FirebirdSql.Data.FirebirdClient.dll 4.2.0 Added Table and View List Added Open last query tabs on startup Added Using quoted identifiers for […]

by fishcodelib at June 08, 2014 11:31 PM

June 06, 2014

Firebird News

All about transactions

IBSurgeon guys published some pictures of the “All about transactions” seminar that just happened in Moscow. You may recognize some of our Firebird fellows there http://ib-aid.com/en/news/firebird-tour-in-moscow-june-4-2014

by Cantu at June 06, 2014 12:45 AM

June 05, 2014

Firebird News

CopyCat Replication Engine v. 3.06.0 released !

Microtec is pleased to announce a new release of our CopyCat Replication Engine, version 3.06.0 ! CopyCat is a set of Delphi / C++Builder components providing customizable replication for Firebird, Interbase, Microsoft SQL Server, MySQL, NexusDB and SQLite, including heteogenous replication between different database types. This latest version adds support for iOS and Android platforms! […]

by jonneve at June 05, 2014 10:24 AM

ADO.NET provider 4.2.0.0 for Firebird is ready

ADO.NET provider 4.2.0.0 for Firebird is ready and you can find more at http://blog.cincura.net/233462-ado-net-provider-4-2-0-0-for-firebird-is-ready/.

by Jiri Cincura at June 05, 2014 06:36 AM

June 04, 2014

Delphi Code Monkey

I officially hate hate hate the WITH statement.

This hilariously awful piece of code is from FooBars (fobar.pas), the name of the vendor has been removed so I can feel better about placing it up here to be openly criticized:

procedure TfooBarPainter.BarDrawMarkArrow(ABarControl: TfooBarControl;
  DC: HDC; MarkR: TRect);
var
  P: array[1..3] of TPoint;
  AColor: COLORREF;
begin
  with MarkR, P[1] do
  begin
    P[1] := Point((Left + Right - MarkSizeArrowX) div 2,
      (Top + Bottom - MarkSizeArrowY) div 2 + (Top + Bottom - MarkSizeArrowY) mod 2);
    P[2] := Point(X + MarkSizeArrowX - 1, Y);
    P[3] := Point(X + MarkSizeArrowX div 2, Y + MarkSizeArrowY - 1);
  end;
  // more code here.
end;

So sometimes I have used WITH in my code.  But when I read code like the one above, I want to throw up a bit.

I'm a bit shocked at how ugly and unreadable a "WITH a,b" makes the code above, and how my brain just about short-circuits when I spot one of the expressions on the outside of the with clause, inside it as well.

I'm a bit puzzled how anyone thought that it was worth writing code like this.

With foot, gun do
begin
   point(gun,foot);
   fire();
end.

When you make a feature possible in a language it can never ever be removed, it would seem.  But maybe it would be nice if use of With could become a compiler warning (optionally turned on) so that those who don't want it in their code can have some compiler help in finding them and rooting them out.  In the case above,  the code is from a very well known component developer.   I think the above extremely ugly, and suspect that judicious use of temporary variables referring to objects is a very inexpensive and readable way of writing code.

But I wonder, since WITH is ancient history for most of us, we've all long since stopped using it, if there are other unreadable areas in our code.  I think there are:


  •  Every USES statement with more than some X number of  items becomes an unreadable mess.   Have you ever tried organizing your uses clauses into sections? I find that the advent of unit namespace prefixes on unit names (WinApi.Windows) combined with grouping units by their unit namespace prefixes, really increased the sense of order in my applications.   A disorganized unordered list of 30 units is unreadable and inscrutable, but a uses clause organized into RTL, VCL, ThirdParty, the MyApp units, becomes instantly clearer.
  •  Every class with 100 or more methods in it becomes completely opaque and very hard to reason about.   Restricting method visibility (no unnecessarily public methods, no unnecessarily protected methods), helps a lot.
  • I find reintroduce, and overloaded methods add a lot to the mental noise and confusion in my head, and when I can, I like to get rid of them.
Any other things you wish to banish from your own personal Delphi coding standards?


by Warren Postma (noreply@blogger.com) at June 04, 2014 06:25 PM

twm’s blog

TStringList.CaseSensitive

Did you know that TStringList has got a property called CaseSensitive? It’s no surprise that it is used when comparing the strings while sorting.

But did you know that it defaults to FALSE?

WTF?

(This is Delphi 2007.)

by dummzeuch at June 04, 2014 03:15 PM

TPersistent

EMBT gets a Swift Kick in the Assetts

In case you haven’t heard yet, Apple has created a new language meant to be more friendly than Objective C.  They call it Swift, and it is aptly named judging from the benchmarks which show it to be significantly faster than Objective C even though it uses the same run-time and is compiled using the LLVM toolchain.

What does this mean for Delphi?  Perhaps a few developers looking to produce truly native (UI and code) will take another look at Apple’s development tools that they already have to access to as part of the development program.

by Larry Hengen at June 04, 2014 01:23 PM

June 03, 2014

Firebird News

Clad Genius using Firebird

It seems that Clad Genius (intelligent software for posting ads in classified sites) uses Firebird.

by Cantu at June 03, 2014 07:51 PM

twm’s blog

When TAB jumps to the next row

I just stumbled over an oddity in TJvDbGrid (which probably also applies to the standard Delphi TDbGrid):

Including dgTab in the grid’s Options resulted in TAB moving the cursor to the next row rather than to the next column as expected.

It turns out, that this is due to the (protected) property TabStops which for each column determines whether it should be included in the tab order. This property is handled internally in SetColumnAtrributs which in turn is called whenever the Options changes. It sets TabStops to true, for a column, if

  • dgTab is in the grid’s Options
  • Readonly of the grid is false

and a few other conditions of the column itself, e.g. whether it is a calculated column.

This method is not called when you change the ReadOnly property. So, if you change the grid from ReadOnly to ReadWrite like this:

    TheGrid.ReadOnly := False;
    TheGrid.Options := TheGrid.Options + [dgEditing];

everything works as expected. But if you change the order of these two lines like this:

    TheGrid.Options := TheGrid.Options + [dgEditing];
    TheGrid.ReadOnly := False;

you end up with a grid where TAB moves the cursor to the next row.

I found this in Delphi 2007, haven’t checked if it also happens in later versions.

by dummzeuch at June 03, 2014 02:03 PM

The Wiert Corner - irregular stream of stuff

jpluimers

Talking about Danny Thorpe: he also posted a nice hint on threading methods for ancient Delphi versions that equally applies to DLL exports in any Delphi version, even any programming environment.

Recently, I had to do some surgery in such a Pre-Delphi 6 application, and I was really happy to remember this answer: it instantly solved some process crashes, and the added logging allowed for investigating the actual cause.

Note that this tip isn’t just a good advice for old Delphi versions.

Even in younger Delphi versions, you have to watch methods that can be called from outside a regular Delphi context, for instance exported methods.

Heck, it applies to virtually any development environment: exceptions usually are very specific to that environment and should never cross a process boundary.

Summary

Take the approach below

  • for Execute methods in your own thread classes in Delphi 5 or earlier
  • for any method that can be called externally (like DLL exports)
procedure ThreadExecuteOrDllExport(...);
begin
  try
    CallInternalLogic(...parameters...);
  except
    on e: Exception do
    begin
      // output or log this error somewhere.
    end;
  end;
end;

--jeroen

via: multithreading - Program shutdown on Synchronize - Stack Overflow.


Filed under: Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi x64, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development

by Jeroen Pluimers at June 03, 2014 05:00 AM

June 01, 2014

twm’s blog

Delphi IDE Explorer Expert for Delphi XEx

Based on a similar expert by David Hoyle for Delphi 3/4/5, which I found on Embarcadero CodeCentral, I have written the Delphi IDE Explorer Expert for Delphi XE .. XE6. It is a package based expert that installs into the Delphi IDE and displays its internal component structure.

The original purpose was to find the button for showing and hiding the background for the Firemonkey mobile form designer and turn the bloody thing off for good. Unfortunately I could not find that form and that button, so I assume it’s not written with the VCL but itself a Firemonkey form.

Here are some screenshots of the expert:

Display Properties

Display Events

Display Inheritance

The tree view on the left side displays the hierarchy of the components as it is available via the global VCL Screen object. the right side shows the properties, events and inheritance of the selected component.

Filter Dialog

The expert also allows to filter for specific class types, e.g all TAction, TActionList etc. objects.

The full source code is available from SourceForge.

Please note: The package for Delphi XE3 is actually a Delphi XE2 package for now. I cannot start XE3 because for some reason it thinks it isn’t registered. Did I mention I hate the forced online activation?

by dummzeuch at June 01, 2014 02:21 PM

Dr.Bob's Delphi Notes

Weblog back online...

When I came home from the Delphi Developer Days 2014 event in Frankfurt, my good-old web server running Windows Server 2003 was making a lot of noise, and started to shut itself off (without the "help" of Windows updates).

by Bob@eBob42.com (Bob Swart) at June 01, 2014 02:45 AM

May 30, 2014

Firebird News

More details about 1.7 Terabyte Firebird SQL database

Some days ago ib surgeon published an article about the relationship between Firebird performance and databases growth, where they have tested the 1.7 Terabyte Firebird SQL database. Here you can find more details about such a big database.

by mariuz at May 30, 2014 10:50 AM

May 29, 2014

twm’s blog

Segmentation fault on startup in Delphi XE6 Firemonkey application for Android

After I attended the Delphi Power Workshop on mobile development with Delphi XE6 in Essen last week, the mobile development virus has taken hold of me. So I tried successfully to compile the demo apps for both, my Nexus 7 tablet and my Samsung Galaxy Note (GT-N7000) smartphone. That these worked out of the box got me hooked even more.

So, now I am writing my first useful App which is going to be a simple random number generator emulating the various dices used in games (In German dice is “Würfel” and there are several standard ones called W4, W6 (that’s the most widely used one), W8, W10, W12 and W20. My App is going to support these and in addition a custom one.

But back to the topic. I created a new “Firemonkey mobile Application” with a simple form, added a few controls and events and tried to run it on my smartphone. It immediately crashed with a segmentation fault in TFormBorder.GetSupported (unit FMX.Forms). Segmentation fault is the Android (Linux) equivalent of an Access Violation on Windows, most likely caused by referencing a NIL pointer. Being new to Android and Firemonkey development, I was expecting some very simple but hard to trace cause for this, like forgetting to call some initialization function I didn’t know about.

First thing I did was typing the error message and the method name into Google, but nothing turned up. Apparently I was the first one who had encountered that problem and talked about it.

So next I put a breakpoint into the method and checked the variables. As expected, there was a NIL pointer: Self was NIL. I traced back up the call stack and found that apparently the form’s ResizeHandle method was called before the form was properly instantiated. Then it dawned to me. I had made one of the most basic mistake in Delphi development: I had forgotten to call inherited Create in the form’s constructor.

So, even an old hand (or old fart, if you prefer that) in Delphi development can make basic mistakes. Also, what was wrong in Delph 1 in 1995 is still wrong in Delphi XE6 in 2014.

After I fixed this problem, everything works as expected.

by dummzeuch at May 29, 2014 09:31 AM

The Wiert Corner - irregular stream of stuff

jpluimers

Thanks Samaliani for posting a Delphi GetWinControlName function as answer to Is there a way to get a VCL Control’s name through the windows API?

The cool thing: it works across processes (as long as your own process has ReadProcessMemory rights).

It works from Delphi XE3 and up.

Be sure to also read the comments by Danny Thorpe on the automation framework in Delphi: that might also be a good place to get this information from.

–jeroen

via: delphi – Is there a way to get a VCL Control’s name through the windows API? – Stack Overflow.


Filed under: Delphi, Delphi XE3, Delphi XE4, Development, Software Development

by Jeroen Pluimers at May 29, 2014 05:00 AM

May 28, 2014

Firebird News

Firebird project accepts pull requests in Github mirror

Adriano dos Santos Fernandes will push the pull requests from github mirror to svn repository That way is easier to contribute to the project.

by mariuz at May 28, 2014 09:24 AM

May 26, 2014

Firebird News

NodeJS Example of querying using Promises

Tom Conlon added a Firebird NodeJS example of querying using asynchronous Promises.

by mariuz at May 26, 2014 04:07 PM

The Podcast at Delphi.org

Know Your Alignments

FireMonkey offers a lot more alignment options than those offered in the VCL. The Alignment aligns the control within its parent, setting anchors, size and position. The Default is None. To make it easier to think about them, you can group the different types of alignments.

  • Anchor and fill along edge – these are 4 of the alignments you are most likely familiar with.
    • Top, Bottom, Left, Right
  • Like the above, but takes precedence over other alignments
    • MostBottom, MostTop, MostLeft, MostRight
  • Fill parent, but preserve aspect ratio – very powerful, especially when applied to one of the new layouts, like the TScaledLayout.
    • Fit, FitLeft, FitRight
  • Resize only on one axis (width or height) to fill that axis of the parent and optionally centered
    • Vertical, VertCenter, Horizontal, HorzCenter
  • Miscellaneous
    • Client – Fills remaining space not occupied by other pinned controls.
    • Contents – Fills entire client area of the parent overlapping other controls.
    • Center – Just moves to the center without resizing.
    • Scale – Maintains relative size and position relative to the parent as it resizes.

Checkout the full DocWiki pages for more details on FMX.Types.TAlignLayout and Vcl.Controls.TAlign.

by Jim McKeeth at May 26, 2014 12:17 PM

May 23, 2014

The Podcast at Delphi.org

Clone from GitHub in Delphi IDE

There are a lot of interesting Delphi projects showing up on GitHub. GitHub offers a convenient Download ZIP function, not to mention a very easy to use Windows Desktop Client that has full support for managing local repositories, syncing them to GitHub and accessing GitHub projects via Cloning in Desktop.

Sometimes it is nice to just open the project in your IDE of choice directly from GitHub. Turns out this is just as easy as 1-2-3. Right above the Clone in Desktop and Download ZIP buttons there is a checkout URL with support for Subversion. Simple click Subversion, then click copy URL and your can then open the GitHub project directly from the Delphi or RAD Studio IDE.

github-subversion

This maintains the revision history locally so you can browse it from the history tab, but it doesn’t appear to allow checking changes back in.

You probably want to update the SVN client RAD Studio uses. This is easy enough too. Just download and install the Colab SVN 32-bit Windows client (don’t get 64-bit or Edge) and install it normally. Then edit your Registry and browse to “HKEY_CURRENT_USER\Software\Embarcadero\BDS\14.0\Subversion” and add a string value named SvnDllDir. This value of SvnDllDir should be the path to your SVN client install. Something like “C:\Program Files (x86)\Subversion Client” (without the quotes).

If you don’t like the fact the Colab Subversion site requires a login, there are other sources for download the Subversion command-line client. Just be sure you get the 32-bit version since the IDE is 32-bit. You may have luck with with the command-line tools that come with TortoiseSVN, or I’ve tested it with the Command-line client from Assembla and found it worked fine.

by Jim McKeeth at May 23, 2014 12:39 PM

May 22, 2014

The Podcast at Delphi.org

Delphi Sensors on Windows 8 Tablet

New in XE6 is support for VCL Sensors. What better way to show these off then on the 8″ Dell Venue 8 Pro Windows 8.1 Tablet. The VCLSensors sample ships with RAD Studio XE6. I simply deployed it to the Dell Venue 8 Pro and it runs great.

VCL Sensors on Dell Venue 8 Pro

 

I added one of the VCL Styles to it as well. You can see it running here with my favorite wallpaper. It shows the Latitude & Longitude from the GPS via the TLocationSensor, the motion from the accelerometer via the TMotionSensor and the compass heading + tilt from the compass and gyroscope via the TOrientationSensor.

These sensors behave exactly the same way as the FireMonkey mobile ones do on Android and iOS, but now you can take advantage of them with your desktop applications.

You can also use the Metropolis UI and the tablet optimized styles for a full screen tablet experience on the Dell tablet. Both with VCL and FireMonkey.

 

by Jim McKeeth at May 22, 2014 05:26 PM

Dr.Bob's Delphi Notes

Delphi Developer Days in Frankfurt: May 26-27

Cary Jensen and I have just completed our two US cities for Delphi Developer Days, and are about to start in Europe with Frankfurt, Amsterdam and London.

by Bob@eBob42.com (Bob Swart) at May 22, 2014 09:53 AM

The Podcast at Delphi.org

Parrot AR.Drone 2.0 Delphi Component

githubI took my code I previously used to control the Parrot AR.Drone and turned it into a reusable component. I added some more functionality to it as well, although there is a lot more to cover. The component is available on GitHub.

It should work with Delphi, C++Builder, Appmethod and RAD Studio on iOS, Android, Windows and OS X. I’d love to hear how it works for you and what you use it for!

by Jim McKeeth at May 22, 2014 01:28 AM

May 21, 2014

TPersistent

ReEnabling the GExperts Procedure List (Ctrl +G)

If you are like me, you use GExperts in your IDE.  IMHO much of the functionality GExperts offers should be part of the stock IDE.  Once you start using it, there is no going back.  Many thanks to Erik Berry and company for putting all this together and keeping it supported through so many releases of Delphi.

Sporadically I have noticed that Ctrl+G in XE4 with GExperts installed stops working.  If I restart the IDE it would again work for a while, but eventually I was frustrated enough to investigate the issue further.  Using GExpert’s IDE Menu ShortCuts option I navigated through the menu looking for menu items using the same shortcut.  I stumbled across the Find Original Symbol menu item which uses the same shortcut (it would be nice to be able to search for a shortcut but I did not see such an option).  I re-mapped it to a custom shortcut since I am used to using Ctrl+G for the GExperts Procedure List.  This worked temporarily, but then I noticed Ctrl+G was still shown in the Find Original Symbol menu option.  I re-started the IDE and it then showed the new shortcut, and Ctrl+G launches the procedure list as expected.

I hope this helps in case you are experiencing the same issues.

by Larry Hengen at May 21, 2014 04:39 PM

May 20, 2014

The Podcast at Delphi.org

Delphi XE6 is on Fire

Remember the demonstration I did showing how Delphi works great with Ouya? Well, there is a new set top box in town, the Amazon Fire TV. Just like the Ouya, it is a Android powered set top box. So, does it support everyone’s favorite Android development tool? Turns out it works great with Delphi XE6. It uses a wireless ADB connection, so you just need to follow their simple steps to Connect ADB and it shows up in the IDE as the Android device AFTB (not sure what that stands for). After that you can develop and deploy to it just like any other Android device.

When you run your app from the IDE it will popup and run on the Fire TV, but after you exit your app you won’t see it anymore. It appears Fire TV only displays apps that are loaded from their app store on the home screen. Not to worry, you can easily launch it from the Settings -> Applications screen. Simply select your app and choose Launch application.

By default your only input device is the Amazon Fire TV remote.

firetvremote

Simply handle the OnKeyUp event on your form and you will receive events with the key codes vkLeft, vkRight, vkUp, vkDown, vkMenu, vkHardwareBack, vkMediaPlayPause and a key value of 0 for the select, fast forward or rewind buttons. The Home and Voice Search buttons are always handled by the OS. If you choose to handle the vkHardwareBack then set the key value to 0 (or any other value) and the system will ignore it, otherwise your app will exit.

Fire TV also supports a gamepad as well as various other bluetooth input devices, like a bluetooth keyboard, which greatly expands the input options. You also could use App Tethering to tether a mobile or desktop/laptop app to your Fire TV app to provide input and display it on the big screen. Like an image receiver that receives pictures from your mobile device to display them to everyone in the room.

If you download the Fire TV SDK it exposes Game Controller and Notification classes. If there is interest I can post some Object Pascal wrappers for those later on.

 

by Jim McKeeth at May 20, 2014 11:50 PM

Firebird News

CopyCat LiveMirror v.1.01.0 released !

The CopyCat development team is pleased to announce a new version of CopyCat LiveMirror, version 1.01.0 ! Changed in this release include : Added a button in the LiveMirror Manager to give direct access to the latest log file for the selected configuration. Enabled replication for tables having no primary key. Excluded temporary tables from […]

by jonneve at May 20, 2014 02:16 PM

May 18, 2014

Castle Game Engine news

1. First of all, Michalis is very happy to announce that a new game using Castle Game Engine is in development...

1. First of all, Michalis is very happy to announce that a new game using Castle Game Engine is in development. The game is called "Venice", https://www.facebook.com/Venicethegame . It's a point-and-click adventure game, 2D (although we'll make some tricks to convince you otherwise :), with a nonlinear storyline. See the game's page for more info: https://www.facebook.com/Venicethegame .

The game will be available for standalone (Windows, Linux, MacOSX...) and mobile (Android, iOS) platforms.

Some initial screenshots from Venice are attached to this post :)

2. Engine development news: Easy loading and rendering of fonts with international characters in UTF-8 is implemented. The screenshots attached to this post show text with special Polish and Greek letters.

Our font loading and rendering in TTextureFont was extended to render strings in UTF-8, and to allow easily loading (or converting to Pascal source) a font with international characters. Note that everything was optimized to avoid any overhead of interpreting the characters as UTF-8 and possibly having > 256 character codes loaded.

Developers: In the simplest case, you're only interested to fill ACharacters parameter of TTextureFont.Create (if you use FreeType at runtime) or pass --sample-text to texturefont2pascal (if you embed fonts as Pascal code into the binary). Then just draw text as usual (making sure it's in UTF-8 encoding). If you deal with WideStrings (e.g. when working with FPC XML units), make sure that you have a WideString manager installed. For Android this is done automatically: https://sourceforge.net/p/castle-engine/wiki/Android%20development/#widestring-manager .

May 18, 2014 05:31 PM

Firebird News

#Ruby Firebird Extension Library 0.7.2 released : fixes unique and descending index flags after backup/restore cycle

Ruby Firebird Extension Library 0.7.2 release fixes unique and descending index flags after backup/restore cycle Thanx to Pablo Vizcay for the analysis A few cleanups : drop support for ruby 1.8.5 (deprecated) PS: and an observation from Brent Rowland Plenty of coders can sling both C and Ruby, but Ruby C extensions manage to intimidate […]

by mariuz at May 18, 2014 03:58 PM

May 15, 2014

Firebird News

Firebird International Conference is officialy announced

Firebird Project is glad to announce Firebird Conference 2014: the most important international event devoted to FirebirdSQL. Firebird Conference 2014 will be a meeting point for all Firebird users and core developers of Firebird. It’s the best place to share and receive FirebirdSQL knowledge! Firebird Conference 2014 will be October 24-25, 2014, in Prague, Czech Republic, in Clarion […]

by Cantu at May 15, 2014 06:37 PM

#Node Firebird driver : node-firebird-libfbclient can be build and used on MacOS X

Latest version for Node C++ Module for Firebird from git can be build on MacOSX fixing Linking flags (against regular Firebird installation)

by mariuz at May 15, 2014 02:02 PM

It's a blong, blong, blong road...

Delphi Developer Days

Cary Jensen and Bob Swart are well into their Delphi Developer Days 2014 tour, having travelled around America and shortly to hit Europe and the UK. Tour dates are here.

As well as a varied agenda of Delphi sessions (full details here), each stop has a different guest speaker.

For example Jim McKeeth (Embarcadero), Nick Hodges and Ray Konopka (Raize Software) have been on the bill in America, and Bruno Fierens (TMS Software) and Michael Phillipenko and Denis Zubov (FastReports) are lined up for Europe.

When the tour gets to London I’m delighted to announce that I’m on the agenda as the guest speaker!

So this is a quick heads up that if you’re booked onto the tour at London, I’ll see you there when I’m up talking about creative debugging techniques. This is an updated version of a talk that was popular when I was more active on the conference circuit some decade or more ago.

by Brian Long (noreply@blogger.com) at May 15, 2014 11:54 AM

May 12, 2014

Firebird News

Active Record Firebird Adapter for #Rails updated to version 0.8.8

Active Record Firebird Adapter 0.8.8 is updated with a few cleanups and fixes: Merge pull request from Ray Zane : Use @config instead of @connection_params. Fix sequence name limit.

by mariuz at May 12, 2014 08:08 AM

May 11, 2014

twm’s blog

Install Delphi Packages from commandline

After I had to install the gazillion jvcl packages into my Delphi IDE manually again (Yes, I know it comes with an installer, I have got my reasons not to use it.), I finally grew tired of this and wrote this tool:

dzPackageInst is a command line program for installing designtime packages into Delphi IDEs. It supports Delphi 6 up to Delphi XE6.

Example:

dzpackageinst --delphiversion=7 dcltdbf70.bpl

Installs the tdbf design time package for Delphi 7 into the ide.

It can also uninstall packages:

dzpackageinst --uninstall --delphiversion=7 dcltdbf70.bpl

And if the package uses the default naming convention, that is a suffix that corresponds to the compiler version, it can guess the Delphi version to which the package belongs, so this will also work:

dzpackageinst dcltdbf70.bpl

That’s it. (If you want more functionality, there is a similar tool called Delphi Package Installer which has a lot more features.)

You can find the sources (Delphi 2007) for dzPackageInst in the mercurial repository on SourceForge. Note that you will also need the required libraries:

A pre built executable is also available

by dummzeuch at May 11, 2014 12:49 PM

Experimental GExperts Version 1.37-2014-05-11 released

There is nothing new about the formatter code, but it includes a patch by Steffen Binas which improves the performance of the File Open dialog when there are a huge number of files.

Head over to the Experimental GExperts page to download the new version.

by dummzeuch at May 11, 2014 10:20 AM

May 10, 2014

Lazarus-Dev

(De-) Bug wars - A new hope

 "This are not the bugs you are looking for"

Well hopefully in future it will get easier to find those parts of your code, that joined the dark side.
The Lazarus Team is currently working on improving the Debugger in the IDE. And not just improving, but adding an all new shiny debugger.
In fact not just one either.

Here is what we are currently working on. In future we will offer 3 kind of debuggers in the IDE.

  1. The existing gdb based debugger: "GdbmiDebugger".
    And it's variations for gdbserver, and gdb over ssh.
    We will continue to maintain them, as they support additional targets (arm, powerppc, ...) that the new debuggers do not (or not yet) have.

  2. A gdb free debugger: "FpDebugger".
    This is still in its very early alpha stage. So far it will be for Intel targets only. And initial work concentrates on supporting Mac (which no longer comes with GDB, and urgently needs a replacement), and Windows 32 bits. But Win64 and Linux are planned too.

  3. A hybrid: "FpGdbmiDebugger".
    Like the existing GdbmiDebugger it uses GDB. In fact it inherits much of the functionality from GdbmiDebugger.
    But it will have its own routines to evaluate watches itself (without GDB). So it will be able to deal better with Pascal data. As a side effect watch evaluation will also be faster.
    Other debugging tasks, such as running or stepping the exe, and handling breakpoints are handled by the GdbmiDebugger code using GDB.

    But why this one at all?
    The same watch evaluation is available when using FpDebugger?
    Well, with FpGdbmiDebugger being GDB based, it will be easier to support more of the targets that GDB can support (like arm). It will still need some additions (e.g. a reader for arm executables, to read debug info) in order to do this. And FpGdbmiDebugger also has the potential to be extended to be gdbserver based and support remote debugging in future.

    The progress of FpGdbmiDebugger can be watched on its wiki page: FpGdbmiDebugger on our wiki.
    A page for FpDebugger does not yet exist.

The two new debuggers are developed in our SVN version (1.3). And if all goes to plan, then they will be part of Lazarus 1.4 (Probably sometime in 2015)

May Pascal live long and prosper (Oops wrong source).
May the force be with Pascal.

by noreply@blogger.com (Martin Friebe) at May 10, 2014 07:17 PM

Andy's Blog and Tools

IDE Fix Pack 5.6 for XE6 released

IDE Fix Pack version 5.6 adds support for RAD Studio XE6. All patches that are in version 5.5 for XE5 are also in 5.6 for XE6 except the patch for QC 111998 ($TDW macro used in Tools causes crash) that is fixed in XE6.

XE6 introduces a project option to compile projects with the command line compiler instead of the IDE compiler. This can be used to reduces the IDE’s memory consumption during compilation. Because the command line compiler is executed in a different process, all patches that are applied to the IDE compiler don’t work. In order to get IDE Fix Pack’s optimizations into the command line compiler the fastdcc hook DLLs are loaded into the compiler process and you see the “Compiler Speed Pack – Compiler patches applied.” output in the message pane. Only DCC32.EXE, DCC64.EXE and DCCAARM.EXE are supported.

Changelog

  • Added: Support for XE6
  • Added: CompilerSpeedPack for Android (XE6)
  • Added: Apply CompilerSpeedPack to external compiler execution (dcc32, dcc64, dccaarm) (XE6)

IDE Fix Pack Download:

Name IDE Version File Size Downloads Added
IDE Fix Pack 5.5 2009+UP3 IDEFixPack2009Reg55.7z 131.55 KB 379 times 2014-05-04
IDE Fix Pack 5.5 2010 IDEFixPack2010Reg55.7z 121.03 KB 626 times 2014-05-04
IDE Fix Pack 5.5 XE IDEFixPackXEReg55.7z 110.16 KB 677 times 2014-05-04
IDE Fix Pack 5.5 XE2+UP4+HF1 IDEFixPackXE2Reg55.7z 127.93 KB 880 times 2014-05-04
IDE Fix Pack 5.5 XE3+UP1 IDEFixPackXE3Reg55.7z 130.99 KB 591 times 2014-05-04
IDE Fix Pack 5.5 XE4 IDEFixPackXE4Reg55.7z 130.89 KB 500 times 2014-05-04
IDE Fix Pack 5.5 XE5 IDEFixPackXE5Reg55.7z 129.89 KB 1239 times 2014-05-04
IDE Fix Pack 5.6 XE6 IDEFixPackXE6Reg56.7z 267.43 KB 2208 times 2014-05-12

fastdcc Download:

Name IDE Version File Size Downloads Added
fastdcc 5.5 2009+UP3 fastdcc2009v55.7z 75.47 KB 112 times 2014-05-05
fastdcc 5.5 2010 fastdcc2010v55.7z 79.37 KB 160 times 2014-05-05
fastdcc 5.5 XE fastdccXEv55.7z 81.35 KB 185 times 2014-05-05
fastdcc 5.5 XE2+UP4+HF1 fastdccXE2v55.7z 104.62 KB 213 times 2014-05-05
fastdcc 5.5 XE3+UP1 fastdccXE3v55.7z 116.36 KB 133 times 2014-05-05
fastdcc 5.5 XE4 fastdccXE4v55.7z 108.06 KB 131 times 2014-05-05
fastdcc 5.5 XE5 fastdccXE5v55.7z 109.08 KB 274 times 2014-05-05
fastdcc 5.6 XE6 fastdccXE6v56.7z 137.57 KB 616 times 2014-05-10

by Andreas Hausladen at May 10, 2014 06:48 PM

May 09, 2014

The road to Delphi

Patching the dock title bar using the Delphi Detours Library

This is the first of a series of articles about how use the Delphi Detours Library . On this entry I will show you how you can patch the title bar of the dock windows used by the RAD Studio IDE (or a VCL application).

The Delphi IDE uses the Vcl.CaptionedDockTree.TDockCaptionDrawer class to draw the title bar of the docked forms. Unfortunately the look and feel of the docked forms doesn’t looks very nice.

OldCaptionedDockTree

So if we want create new and nice title bar we must patch this class, specifically the DrawDockCaption method.

This is the definition of the TDockCaptionDrawer class.

  TDockCaptionDrawer = class(TObject)
  private
    FDockCaptionOrientation: TDockCaptionOrientation;
    FDockCaptionPinButton: TDockCaptionPinButton;
    function GetCloseRect(const CaptionRect: TRect): TRect;
    function GetPinRect(const CaptionRect: TRect): TRect;
    function CalcButtonSize(const CaptionRect: TRect): Integer;
  protected
    property DockCaptionOrientation: TDockCaptionOrientation read FDockCaptionOrientation;
  public
    procedure DrawDockCaption(const Canvas: TCanvas;
      CaptionRect: TRect; State: TParentFormState); virtual;
    function DockCaptionHitTest(const CaptionRect: TRect;
      const MousePos: TPoint): TDockCaptionHitTest; virtual;
    constructor Create(DockCaptionOrientation: TDockCaptionOrientation); virtual;
    property DockCaptionPinButton: TDockCaptionPinButton read FDockCaptionPinButton write FDockCaptionPinButton;
  end;

The first step is create a new Delphi package in order to load the module inside of the Delphi IDE. Then we must define a trampoline with the same signature of the method to patch.

The method DrawDockCaption looks like so

    procedure DrawDockCaption(const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState); virtual;

And the trampoline definition

type
 TDockCaptionDrawerClass = class(TDockCaptionDrawer);
var
  Trampoline_TDockCaptionDrawer_DrawDockCaption      : function (Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest =nil;

You can note which the first parameter (Self : TDockCaptionDrawerClass) of the trampoline definition include a reference to the object where is contained the original method, you can use a simple TObject as well but is better use the original class, on this case I’m using cracker class to access the protected members inside of the new patched method.

After of define the trampoline , we need create the new function which be draw the caption bar, the signature of this method must be match with the trampoline.

function CustomDrawDockCaption(Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest;

The next step is patch the address of the original method. This is done using the InterceptCreate function of the DDetours unit. This function takes two parameters which are the address of the method to patch and the address of the new method, as result the function returns a pointer to the original function.

  Trampoline_TDockCaptionDrawer_DrawDockCaption  := InterceptCreate(@TDockCaptionDrawer.DrawDockCaption,   @CustomDrawDockCaption);

Remember which you need restore the original address of the patched method (usually when the application is closed or the module is unloaded) this is done using the InterceptRemove function passing the trampoline variable.

  if Assigned(Trampoline_TDockCaptionDrawer_DrawDockCaption) then
    InterceptRemove(@Trampoline_TDockCaptionDrawer_DrawDockCaption);

Now check the implementation of the new drawing method

function CustomDrawDockCaption(Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest;

  procedure DrawIcon;
  var
    FormBitmap: TBitmap;
    DestBitmap: TBitmap;
    ImageSize: Integer;
    X, Y: Integer;
  begin
    if (State.Icon <> nil) and (State.Icon.HandleAllocated) then
    begin
      if Self.DockCaptionOrientation = dcoHorizontal then
      begin
        ImageSize := CaptionRect.Bottom - CaptionRect.Top - 3;
        X := CaptionRect.Left;
        Y := CaptionRect.Top + 2;
      end
      else
      begin
        ImageSize := CaptionRect.Right - CaptionRect.Left - 3;
        X := CaptionRect.Left + 1;
        Y := CaptionRect.Top;
      end;

      FormBitmap := nil;
      DestBitmap := TBitmap.Create;
      try
        FormBitmap := TBitmap.Create;
        DestBitmap.Width :=  ImageSize;
        DestBitmap.Height := ImageSize;
        DestBitmap.Canvas.Brush.Color := clFuchsia;
        DestBitmap.Canvas.FillRect(Rect(0, 0, DestBitmap.Width, DestBitmap.Height));
        FormBitmap.Width := State.Icon.Width;
        FormBitmap.Height := State.Icon.Height;
        FormBitmap.Canvas.Draw(0, 0, State.Icon);
        ScaleImage(FormBitmap, DestBitmap, DestBitmap.Width / FormBitmap.Width);

        DestBitmap.TransparentColor := DestBitmap.Canvas.Pixels[0, DestBitmap.Height - 1];
        DestBitmap.Transparent := True;

        Canvas.Draw(X, Y, DestBitmap);
      finally
        FormBitmap.Free;
        DestBitmap.Free;
      end;

      if Self.DockCaptionOrientation = dcoHorizontal then
        CaptionRect.Left := CaptionRect.Left + 6 + ImageSize
      else
        CaptionRect.Top := CaptionRect.Top + 6 + ImageSize;
    end;
  end;

  function CalcButtonSize(const CaptionRect: TRect): Integer;
  const
    cButtonBuffer = 8;
  begin
    if Self.DockCaptionOrientation = dcoHorizontal then
      Result := CaptionRect.Bottom - CaptionRect.Top - cButtonBuffer
    else
      Result := CaptionRect.Right - CaptionRect.Left - cButtonBuffer;
  end;

  function GetCloseRect(const CaptionRect: TRect): TRect;
  const
    cSideBuffer = 4;
  var
    CloseSize: Integer;
  begin
    CloseSize := CalcButtonSize(CaptionRect);
    if Self.DockCaptionOrientation = dcoHorizontal then
    begin
      Result.Left := CaptionRect.Right - CloseSize - cSideBuffer;
      Result.Top := CaptionRect.Top + ((CaptionRect.Bottom - CaptionRect.Top) - CloseSize) div 2;
    end
    else
    begin
      Result.Left := CaptionRect.Left + ((CaptionRect.Right - CaptionRect.Left) - CloseSize) div 2;
      Result.Top := CaptionRect.Top + 2 * cSideBuffer;
    end;
    Result.Right := Result.Left + CloseSize;
    Result.Bottom := Result.Top + CloseSize;
  end;

  function GetPinRect(const CaptionRect: TRect): TRect;
  const
    cSideBuffer = 4;
  var
    PinSize: Integer;
  begin
    PinSize := CalcButtonSize(CaptionRect);
    if Self.DockCaptionOrientation = dcoHorizontal then
    begin
      Result.Left := CaptionRect.Right - 2*PinSize - 2*cSideBuffer;
      Result.Top := CaptionRect.Top + ((CaptionRect.Bottom - CaptionRect.Top) - PinSize) div 2;
    end
    else
    begin
      Result.Left := CaptionRect.Left + ((CaptionRect.Right - CaptionRect.Left) - PinSize) div 2;
      Result.Top := CaptionRect.Top + 2*cSideBuffer + 2*PinSize;
    end;
    Result.Right := Result.Left + PinSize + 2;
    Result.Bottom := Result.Top + PinSize;
  end;

var
  ShouldDrawClose: Boolean;
  CloseRect, PinRect: TRect;
  LPngImage : TPngImage;
  LStartColor, LEndColor : TColor;
begin
  Canvas.Font.Color :=  DockerFontColor;
   //check the orientation of the dock caption
  if Self.DockCaptionOrientation = dcoHorizontal then
  begin
    Canvas.Pen.Width := 1;
    //set the color for the border of the caption bar
    Canvas.Pen.Color := DockerBorderColor;

    CaptionRect.Top := CaptionRect.Top + 1;
    //set the colors for the captin bar background
    if State.Focused then
    begin
      LStartColor := DockerStartEnabledColor;
      LEndColor   := DockerEndEnabledColor;
    end
    else
    begin
      LStartColor := DockerStartDisabledColor;
      LEndColor   := DockerEndDisabledColor;
    end;

    //draw the caption bar using a gradient
    GradientFillCanvas(Canvas, LStartColor, LEndColor, Rect(CaptionRect.Left + 1, CaptionRect.Top + 1, CaptionRect.Right, CaptionRect.Bottom), gdVertical);

    //draw the border of the caption bar
    Canvas.Pen.Color := DockerBorderColor;
    with CaptionRect do
      Canvas.Polyline([Point(Left + 2, Top), Point(Right - 2, Top), Point(Right, Top + 2),
        Point(Right, Bottom - 2), Point(Right - 2, Bottom), Point(Left + 2, Bottom), Point(Left, Bottom - 2), Point(Left, Top + 2), Point(Left + 3, Top)]);

    //draw the pin buttton
    CloseRect := GetCloseRect(CaptionRect);

    if Self.DockCaptionPinButton <> dcpbNone then
    begin
      PinRect := GetPinRect(CaptionRect);

      LPngImage:=TPNGImage.Create;
      try
        if Self.DockCaptionPinButton = dcpbUp then
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock_left')
        else
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock');

        Canvas.Draw(PinRect.Left, PinRect.Top, LPngImage);
      finally
        LPngImage.free;
      end;

      CaptionRect.Right := PinRect.Right - 2;
    end
    else
      CaptionRect.Right := CloseRect.Right - 2;

    CaptionRect.Left := CaptionRect.Left + 6;
    DrawIcon;
    ShouldDrawClose := CloseRect.Left >= CaptionRect.Left;

  end
  else
  begin
    Canvas.MoveTo(CaptionRect.Left + 1, CaptionRect.Top + 1);
    Canvas.LineTo(CaptionRect.Right - 1, CaptionRect.Top + 1);

    if State.Focused then
    begin
      LStartColor := DockerStartEnabledColor;
      LEndColor   := DockerEndEnabledColor;
    end
    else
    begin
      LStartColor := DockerStartDisabledColor;
      LEndColor   := DockerEndDisabledColor;
    end;

    GradientFillCanvas(Canvas, LStartColor, LEndColor,Rect(CaptionRect.Left, CaptionRect.Top + 2, CaptionRect.Right, CaptionRect.Bottom), gdVertical);

    Canvas.Pen.Color := DockerBorderColor;
    Canvas.MoveTo(CaptionRect.Left + 1, CaptionRect.Bottom);
    Canvas.LineTo(CaptionRect.Right - 1, CaptionRect.Bottom);

    Canvas.Font.Orientation := 900;
    CloseRect := GetCloseRect(CaptionRect);

    if Self.DockCaptionPinButton <> dcpbNone then
    begin
      PinRect := GetPinRect(CaptionRect);
      LPngImage:=TPNGImage.Create;
      try
        if Self.DockCaptionPinButton = dcpbUp then
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock_left')
        else
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock');

        Canvas.Draw(PinRect.Left, PinRect.Top, LPngImage);
      finally
        LPngImage.free;
      end;
      CaptionRect.Top := PinRect.Bottom + 2;
    end
    else
      CaptionRect.Top := CloseRect.Bottom + 2;

    ShouldDrawClose   := CaptionRect.Top < CaptionRect.Bottom;
    CaptionRect.Right := CaptionRect.Left + (CaptionRect.Bottom - CaptionRect.Top - 2);
    CaptionRect.Top   := CaptionRect.Top + Canvas.TextWidth(State.Caption) + 2;

    if CaptionRect.Top > CaptionRect.Bottom then
      CaptionRect.Top := CaptionRect.Bottom;
  end;

  Canvas.Brush.Style := bsClear;
  //draw the text of the caption bar
  if State.Caption <> '' then
  begin
    if State.Focused then
      Canvas.Font.Style := Canvas.Font.Style + [fsBold]
    else
      Canvas.Font.Style := Canvas.Font.Style - [fsBold];

   if ShouldDrawClose then
     CaptionRect.Right := CaptionRect.Right - (CloseRect.Right - CloseRect.Left) - 4;

    Canvas.TextRect(CaptionRect, State.Caption,  [tfEndEllipsis, tfVerticalCenter, tfSingleLine]);
  end;

  //draw the close buttton
  if ShouldDrawClose then
  begin
    LPngImage:=TPNGImage.Create;
    try
      LPngImage.LoadFromResourceName(HInstance, 'close_dock');
      Canvas.Draw(CloseRect.Left, CloseRect.Top, LPngImage);
    finally
      LPngImage.free;
    end;
  end;

  Exit(0);
end;

Now if we install the package on the Delphi IDE the result will be like so

NewDisabledCaptionedDockTree

NewEnabledCaptionedDockTree

If you try the above code in Delphi XE6, the captions will remain with the default IDE Theme. This is because Delphi XE6 introduces a new drawer for the IDE dock forms, this is implemented in the ModernTheme200.bpl package. So in order to make this patch works on XE6 we must patch the DrawDockCaption of this package.

First you must retrieve the signature of the method to patch and then get the address of that method. check the next code.

const
  sModernThemeDrawDockCaption = '@Moderntheme@TModernDockCaptionDrawer@DrawDockCaption$qqrxp20Vcl@Graphics@TCanvasrx18System@Types@TRectrx38Vcl@Captioneddocktree@TParentFormState';

{$IF CompilerVersion>=27}
  ModernThemeModule := LoadLibrary('ModernTheme200.bpl');
  if ModernThemeModule<>0 then
  begin
   pModernThemeDrawDockCaption := GetProcAddress(ModernThemeModule, PChar(sModernThemeDrawDockCaption));
   if Assigned(pModernThemeDrawDockCaption) then
     Trampoline_ModernDockCaptionDrawer_DrawDockCaption:= InterceptCreate(pModernThemeDrawDockCaption, @CustomDrawDockCaption);
  end;
{$ENDIF}

Finally this is the full implementation of the new title bar for the docked forms.


uses
 Types,
 Windows,
 Graphics,
 CaptionedDockTree,
 PngImage,
 GraphUtil,
 Forms,
 DDetours;

{$R Dockimages.RES}

type
 TDockCaptionDrawerClass = class(TDockCaptionDrawer);
var
  Trampoline_TDockCaptionDrawer_DrawDockCaption      : function (Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest =nil;
  {$IF CompilerVersion>=27}
  Trampoline_ModernDockCaptionDrawer_DrawDockCaption : function (Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest =nil;
  {$ENDIF}
  DockerFontColor          : TColor = clBlack;
  DockerBorderColor        : TColor = clBlack;
  DockerStartEnabledColor  : TColor = clWebIvory;
  DockerEndEnabledColor    : TColor = clWebPapayaWhip;
  DockerStartDisabledColor : TColor = clSilver;
  DockerEndDisabledColor   : TColor = clSilver;

{$IF CompilerVersion>=27}
  ModernThemeModule           : HMODULE;
  pModernThemeDrawDockCaption : Pointer;
{$ENDIF}

function CustomDrawDockCaption(Self : TDockCaptionDrawerClass;const Canvas: TCanvas; CaptionRect: TRect; State: TParentFormState): TDockCaptionHitTest;

  procedure DrawIcon;
  var
    FormBitmap: TBitmap;
    DestBitmap: TBitmap;
    ImageSize: Integer;
    X, Y: Integer;
  begin
    if (State.Icon <> nil) and (State.Icon.HandleAllocated) then
    begin
      if Self.DockCaptionOrientation = dcoHorizontal then
      begin
        ImageSize := CaptionRect.Bottom - CaptionRect.Top - 3;
        X := CaptionRect.Left;
        Y := CaptionRect.Top + 2;
      end
      else
      begin
        ImageSize := CaptionRect.Right - CaptionRect.Left - 3;
        X := CaptionRect.Left + 1;
        Y := CaptionRect.Top;
      end;

      FormBitmap := nil;
      DestBitmap := TBitmap.Create;
      try
        FormBitmap := TBitmap.Create;
        DestBitmap.Width :=  ImageSize;
        DestBitmap.Height := ImageSize;
        DestBitmap.Canvas.Brush.Color := clFuchsia;
        DestBitmap.Canvas.FillRect(Rect(0, 0, DestBitmap.Width, DestBitmap.Height));
        FormBitmap.Width := State.Icon.Width;
        FormBitmap.Height := State.Icon.Height;
        FormBitmap.Canvas.Draw(0, 0, State.Icon);
        ScaleImage(FormBitmap, DestBitmap, DestBitmap.Width / FormBitmap.Width);

        DestBitmap.TransparentColor := DestBitmap.Canvas.Pixels[0, DestBitmap.Height - 1];
        DestBitmap.Transparent := True;

        Canvas.Draw(X, Y, DestBitmap);
      finally
        FormBitmap.Free;
        DestBitmap.Free;
      end;

      if Self.DockCaptionOrientation = dcoHorizontal then
        CaptionRect.Left := CaptionRect.Left + 6 + ImageSize
      else
        CaptionRect.Top := CaptionRect.Top + 6 + ImageSize;
    end;
  end;

  function CalcButtonSize(const CaptionRect: TRect): Integer;
  const
    cButtonBuffer = 8;
  begin
    if Self.DockCaptionOrientation = dcoHorizontal then
      Result := CaptionRect.Bottom - CaptionRect.Top - cButtonBuffer
    else
      Result := CaptionRect.Right - CaptionRect.Left - cButtonBuffer;
  end;

  function GetCloseRect(const CaptionRect: TRect): TRect;
  const
    cSideBuffer = 4;
  var
    CloseSize: Integer;
  begin
    CloseSize := CalcButtonSize(CaptionRect);
    if Self.DockCaptionOrientation = dcoHorizontal then
    begin
      Result.Left := CaptionRect.Right - CloseSize - cSideBuffer;
      Result.Top := CaptionRect.Top + ((CaptionRect.Bottom - CaptionRect.Top) - CloseSize) div 2;
    end
    else
    begin
      Result.Left := CaptionRect.Left + ((CaptionRect.Right - CaptionRect.Left) - CloseSize) div 2;
      Result.Top := CaptionRect.Top + 2 * cSideBuffer;
    end;
    Result.Right := Result.Left + CloseSize;
    Result.Bottom := Result.Top + CloseSize;
  end;

  function GetPinRect(const CaptionRect: TRect): TRect;
  const
    cSideBuffer = 4;
  var
    PinSize: Integer;
  begin
    PinSize := CalcButtonSize(CaptionRect);
    if Self.DockCaptionOrientation = dcoHorizontal then
    begin
      Result.Left := CaptionRect.Right - 2*PinSize - 2*cSideBuffer;
      Result.Top := CaptionRect.Top + ((CaptionRect.Bottom - CaptionRect.Top) - PinSize) div 2;
    end
    else
    begin
      Result.Left := CaptionRect.Left + ((CaptionRect.Right - CaptionRect.Left) - PinSize) div 2;
      Result.Top := CaptionRect.Top + 2*cSideBuffer + 2*PinSize;
    end;
    Result.Right := Result.Left + PinSize + 2;
    Result.Bottom := Result.Top + PinSize;
  end;

var
  ShouldDrawClose: Boolean;
  CloseRect, PinRect: TRect;
  LPngImage : TPngImage;
  LStartColor, LEndColor : TColor;
begin
  Canvas.Font.Color :=  DockerFontColor;
   //check the orientation of the dock caption
  if Self.DockCaptionOrientation = dcoHorizontal then
  begin
    Canvas.Pen.Width := 1;
    //set the color for the border of the caption bar
    Canvas.Pen.Color := DockerBorderColor;

    CaptionRect.Top := CaptionRect.Top + 1;
    //set the colors for the captin bar background
    if State.Focused then
    begin
      LStartColor := DockerStartEnabledColor;
      LEndColor   := DockerEndEnabledColor;
    end
    else
    begin
      LStartColor := DockerStartDisabledColor;
      LEndColor   := DockerEndDisabledColor;
    end;

    //draw the caption bar using a gradient
    GradientFillCanvas(Canvas, LStartColor, LEndColor, Rect(CaptionRect.Left + 1, CaptionRect.Top + 1, CaptionRect.Right, CaptionRect.Bottom), gdVertical);

    //draw the border of the caption bar
    Canvas.Pen.Color := DockerBorderColor;
    with CaptionRect do
      Canvas.Polyline([Point(Left + 2, Top), Point(Right - 2, Top), Point(Right, Top + 2),
        Point(Right, Bottom - 2), Point(Right - 2, Bottom), Point(Left + 2, Bottom), Point(Left, Bottom - 2), Point(Left, Top + 2), Point(Left + 3, Top)]);

    //draw the pin buttton
    CloseRect := GetCloseRect(CaptionRect);

    if Self.DockCaptionPinButton <> dcpbNone then
    begin
      PinRect := GetPinRect(CaptionRect);

      LPngImage:=TPNGImage.Create;
      try
        if Self.DockCaptionPinButton = dcpbUp then
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock_left')
        else
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock');

        Canvas.Draw(PinRect.Left, PinRect.Top, LPngImage);
      finally
        LPngImage.free;
      end;

      CaptionRect.Right := PinRect.Right - 2;
    end
    else
      CaptionRect.Right := CloseRect.Right - 2;

    CaptionRect.Left := CaptionRect.Left + 6;
    DrawIcon;
    ShouldDrawClose := CloseRect.Left >= CaptionRect.Left;

  end
  else
  begin
    Canvas.MoveTo(CaptionRect.Left + 1, CaptionRect.Top + 1);
    Canvas.LineTo(CaptionRect.Right - 1, CaptionRect.Top + 1);

    if State.Focused then
    begin
      LStartColor := DockerStartEnabledColor;
      LEndColor   := DockerEndEnabledColor;
    end
    else
    begin
      LStartColor := DockerStartDisabledColor;
      LEndColor   := DockerEndDisabledColor;
    end;

    GradientFillCanvas(Canvas, LStartColor, LEndColor,Rect(CaptionRect.Left, CaptionRect.Top + 2, CaptionRect.Right, CaptionRect.Bottom), gdVertical);

    Canvas.Pen.Color := DockerBorderColor;
    Canvas.MoveTo(CaptionRect.Left + 1, CaptionRect.Bottom);
    Canvas.LineTo(CaptionRect.Right - 1, CaptionRect.Bottom);

    Canvas.Font.Orientation := 900;
    CloseRect := GetCloseRect(CaptionRect);

    if Self.DockCaptionPinButton <> dcpbNone then
    begin
      PinRect := GetPinRect(CaptionRect);
      LPngImage:=TPNGImage.Create;
      try
        if Self.DockCaptionPinButton = dcpbUp then
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock_left')
        else
         LPngImage.LoadFromResourceName(HInstance, 'pin_dock');

        Canvas.Draw(PinRect.Left, PinRect.Top, LPngImage);
      finally
        LPngImage.free;
      end;
      CaptionRect.Top := PinRect.Bottom + 2;
    end
    else
      CaptionRect.Top := CloseRect.Bottom + 2;

    ShouldDrawClose   := CaptionRect.Top < CaptionRect.Bottom;
    CaptionRect.Right := CaptionRect.Left + (CaptionRect.Bottom - CaptionRect.Top - 2);
    CaptionRect.Top   := CaptionRect.Top + Canvas.TextWidth(State.Caption) + 2;

    if CaptionRect.Top > CaptionRect.Bottom then
      CaptionRect.Top := CaptionRect.Bottom;
  end;

  Canvas.Brush.Style := bsClear;
  //draw the text of the caption bar
  if State.Caption <> '' then
  begin
    if State.Focused then
      Canvas.Font.Style := Canvas.Font.Style + [fsBold]
    else
      Canvas.Font.Style := Canvas.Font.Style - [fsBold];

   if ShouldDrawClose then
     CaptionRect.Right := CaptionRect.Right - (CloseRect.Right - CloseRect.Left) - 4;

    Canvas.TextRect(CaptionRect, State.Caption,  [tfEndEllipsis, tfVerticalCenter, tfSingleLine]);
  end;

  //draw the close buttton
  if ShouldDrawClose then
  begin
    LPngImage:=TPNGImage.Create;
    try
      LPngImage.LoadFromResourceName(HInstance, 'close_dock');
      Canvas.Draw(CloseRect.Left, CloseRect.Top, LPngImage);
    finally
      LPngImage.free;
    end;
  end;

  Exit(0);
end;


{$IF CompilerVersion>=27}
const
  sModernThemeDrawDockCaption = '@Moderntheme@TModernDockCaptionDrawer@DrawDockCaption$qqrxp20Vcl@Graphics@TCanvasrx18System@Types@TRectrx38Vcl@Captioneddocktree@TParentFormState';
{$ENDIF}

procedure RefreshForms;
var
  i : Integer;
begin
   for i := 0 to Screen.FormCount-1 do
    Screen.Forms[i].Invalidate;
end;

initialization
  Trampoline_TDockCaptionDrawer_DrawDockCaption  := InterceptCreate(@TDockCaptionDrawer.DrawDockCaption,   @CustomDrawDockCaption);
{$IF CompilerVersion>=27}
  ModernThemeModule := LoadLibrary('ModernTheme200.bpl');
  if ModernThemeModule<>0 then
  begin
   pModernThemeDrawDockCaption := GetProcAddress(ModernThemeModule, PChar(sModernThemeDrawDockCaption));
   if Assigned(pModernThemeDrawDockCaption) then
     Trampoline_ModernDockCaptionDrawer_DrawDockCaption:= InterceptCreate(pModernThemeDrawDockCaption, @CustomDrawDockCaption);
  end;
{$ENDIF}
  RefreshForms();
finalization
  if Assigned(Trampoline_TDockCaptionDrawer_DrawDockCaption) then
    InterceptRemove(@Trampoline_TDockCaptionDrawer_DrawDockCaption);
{$IF CompilerVersion>=27}
  if Assigned(Trampoline_ModernDockCaptionDrawer_DrawDockCaption) then
    InterceptRemove(@Trampoline_ModernDockCaptionDrawer_DrawDockCaption);
{$ENDIF}
  RefreshForms();

end.

You can download the full source code of this package from the project page.


by Rodrigo at May 09, 2014 11:01 PM

May 08, 2014

DelphiTools.info

Delphi XE6 32bits and Scimark

In a Google+ comment to my recent article about inlining in XE6, Leif Uneus posted results from Scimark. It appears that XE6 is about 30% slower than previous versions at least from XE5 to XE for 32bits floating point. Note that Scimark does not make use of inlining, but does make heavy use of floating-point computations,…

by Eric Grange at May 08, 2014 06:00 AM

It's a blong, blong, blong road...

My CodeRage session files

At the time of writing my two sessions for CodeRage 8 are being broadcast around the Arpanet.

I’ve got two session this year, both related to Delphi mobile development, and both concerning how to reach out from the island that is the FM Application Framework (aka FMX aka FireMonkey) and gain access to the underlying mobile OS platform APIs.

The first session is Accessing the iOS API and looks at how Delphi-written iOS apps can talk to the CocoaTouch APIs and access additional iOS frameworks. We look at the Objective-C bridge and see how it is used to import iOS APIs, namely classes and protocols (Apple’s term for what we call interfaces), and how you can implement iOS interfaces and inherit from iOS classes. We also briefly look at how to pull in APIs that are not already imported by Delphi’s RTL. As a proof of concept we briefly see a Delphi iOS app that has no FMX code or units in it whatsoever, operating purely through the iOS APIs using the standard CocoaTouch model.



Files from the Accessing the iOS API session can be downloaded from here.

The second session is Accessing the Android API and looks at how Delphi-written Android apps can talk to the Android SDK classes. We look at the Java bridge and see how it is used to import Android APIs. We’ll also look at how to pull in APIs that are not already imported by Delphi’s RTL. We also look at how to add a splash screen to an Android app to cover up the startup time on anything other than the fastest devices, how to add Android menus to an app and how to launch external activities and get results back from them.



Files from the Accessing the Android API session can be downloaded from here. Take note that since several of the samples involve various required preliminary steps in order to function, as they step outside the comfort zone of Delphi XE5 RTM’s Android support, you should check the ReadMe.txt files supplied in the project directories of those projects.

[Update]

I plan to write up some of the subjects covered by these demos in further posts or articles as time and work schedules permit. However in the mean time I’ll respond to comments by expanding this post as necessary.

It appears that when the small Java source files get compiled, the Android dx tool expects them to be compiled by the JDK 1.6.x compiler as opposed to the JDK 1.7.x compiler. If you have JDK 1.7.x installed, you hit a problem with dx reporting:

bad class file magic (cafebabe) or version (0033.0000)

However, to avoid forcing a reinstall of JDK 1.6 you might like to modify my build.bat batch files and add in extra command line switches to the javac.exe command-lines. You need to insert this after the javac.exe command to force Java 1.6 byte code output, which is digestible by the Android dx command:

-source 1.6 -target 1.6

[Update 2]

Current write-ups:
  • Splash screens are written up here for Delphi XE5 and Delphi XE6.
  • Launching activities and getting results back is written up here for Delphi XE5 and Delphi XE6.

by Brian Long (noreply@blogger.com) at May 08, 2014 03:33 AM

May 07, 2014

Firebird News

Ruby Firebird Extension Library – Fb bumped to version 0.7.1 with a few fixes

Version 0.7.1 is on RubyGems now. With following changes and bug fixes: Fix naive rounding logic affecting negative scaled values. Update for current rubygems, add license MIT like ar adapter , add rakefile. Fixes error: ‘isc_info_db_SQL_dialect’ undeclared (first use in this function) replaced in Firebird 3.0 and marked as deprecated from firebird 1.5.

by mariuz at May 07, 2014 07:16 PM

Sparx Systems – Enterprise Architect 11 uses Firebird

Sparx Systems now has a fully intergrated Firebird backend Database for its Enterprise Architect application

by mariuz at May 07, 2014 07:03 PM

It's a blong, blong, blong road...

Launching other activities from Delphi Android apps

Following on from my recent post about adding Android app splash screens in Delphi XE5 and Delphi XE6 I’ve now spent some time writing up details on how to launch various Android system activities. This includes the more interesting business of getting feedback from launched activities; a common use case here is using a barcode scanner and finding what barcode what scanned.

Again there are two articles, one for Delphi XE5 and one for Delphi XE6. The XE5 version is much longer as it involves documenting a whole bunch of command-line shenanigans (much like for the splash screen) to hook the activity results. This is made much easier in Delphi XE6, thankfully.

I’ve tried to do a thorough coverage of the subject matter, highlighting any issues I bumped into – I hope it is of use to anyone tinkering with Android apps in Delphi.

by Brian Long (noreply@blogger.com) at May 07, 2014 04:40 PM

DelphiTools.info

A Look at Improved Inlining in Delphi XE6

First noticed by dewresearch, Delphi XE6 introduced a new optimization for inlined functions that return a floating-point value. Here is an exploration of what was improved… and what was not improved. When inlining was introduced in Delphi, one limitation was that functions returning a floating point values would incur an unnecessary round-trip to the stack,…

by Eric Grange at May 07, 2014 10:00 AM

May 06, 2014

Castle Game Engine news

Photo of our game "Darkest Before the Dawn" running on iPad, thanks to +Jan Adamec  ! See http://castle...

Photo of our game "Darkest Before the Dawn" running on iPad, thanks to +Jan Adamec  ! See http://castle-engine.sourceforge.net/darkest_before_dawn.php for current Android and standalone versions. iOS version soon :)

May 06, 2014 07:56 PM

PARMAJA

Temporary Off work.

For who using my source codes, or my projects.
I am in offline mode for programming, there is many reasons, like I am sick (“cervical radiculopathy), my country (Syria) have troubles, no main power electrics.

Hope you all good time.

by Zaher Dirkey at May 06, 2014 07:33 PM

The Podcast at Delphi.org

Where is StringToJString and StrToNSStr in XE6?

The useful helper routines StringToJString and StrToNSStr (and other associated ones) moved between XE5 and XE6. In XE6 you can find them in the units Androidapi.Helpers and Macapi.Helpers respectively. But how to find other useful methods? I’ll tell you what I do: Use Windows Search.

You want to go to Indexing Options to set Windows Search up to be useful.

Windows Search Indexing Options

First select Modify and browse to the Source folder and add it to the list of indexed locations. I like to add the source folder as a favorite in Explorer too, to make it easier to get back there.

C:\Program Files (x86)\Embarcadero\Studio\14.0\source

Next click Advanced and go to the File Types tab and select .PAS file and any other file types you would like to have indexed, and change them to Index Properties and File Contents. It uses the plain text filter, which in my experience is good enough, and your only option (without installing a new one).

Indexing Options - Advanced - File Types

It takes a bit for the index to rebuild, but after that you can quickly search all of the XE6 source to find APIs, Helper Methods or any number of other useful code to aid in your development process. This is where that favorite to the source folder is helpful. Either search from the root of the source folder, or browse into a subfolder to only search specific source files.

There are other indexed searching utilities, and I’ve used many of them in the past. The advantage of Windows Search (probably it’s only advantage) is that it is built in and already running.

by Jim McKeeth at May 06, 2014 03:38 PM

The Wiert Corner - irregular stream of stuff