Quantcast
Channel: Planet Object Pascal
Viewing all 1725 articles
Browse latest View live

Delphi Code Monkey: Quotes and Sayings for Software Developers

$
0
0
I saw this today at Forbes.com:

 They are happy men whose natures sort with their vocations. ”
— Francis Bacon

I think the above is a particularly good way of explaining why I feel very happy to be a software developer. I love what I do, and so, I find, it is a lot easier to get me to do that work, than it would be to get me to do something I did not like doing.  And in the end, not only am I happy, hopefully everyone, including the business owner that I work for, and the customers of that business, can be happy to, because they each have to get what they need too.   I think there really is a temperament that is suited to software development, and that its pretty safe to say that I have it.   

Another quote that I think is apropos for the professional software developer, which I keep quoting, without knowing where it came from, and which is similar to, or dovetails with the Francis Bacon quote is:

"Hard work becomes easy when the mind is at play"

Unfortunately I do not know the origin of the quote.  I could be quoting myself, or Benjamin Franklin, or Abraham Lincoln, or Mark Twain. Who knows.    The meaning of the quote, to me, is that if a person is unable to enter into, and enjoy the technical challenge or mastery of a skill that is required to do a job well, then not only will they hate doing the work, they'll do it badly.  This is another way of saying that temperament affects outcomes, at least in our line of work.  Incidentally google and all the quote databases come up empty when looking for quotes about a mind at play.

Please share your favorite quotes about work,  being a software developer, and anything related to the temperament or working lives of developers.

Update: Apologies for the formatting mistakes on this post, and any eyestrain caused by them!


Daniel Magin's Logfile: Delphi / VMWare Fusion / OSX Mavericks / Samsung Android Devices USB Connection Problem solved

$
0
0

First let me say what a horror installation.

Second Delphi has nothing to do with this problem.

What's going up:

I use a new Samsung Galaxy S4 for developing Android Applications from Delphi. I use a MacMini with running VMWare Fusion 6.01 and a installation of Windows 8.

Connecting the Samsung Device on the MacMini and connect the Device to the Mac OSX and watching with Hardware Growler the Device connects wonderful. But connect the Device with the VMWare Fusion Dialog to Windows the Device is connect/disconnect/connect/disconnect how ever a never ending story.

After hours of search i found the solution and i like to share to the community how to solve this problem.

Please read first all steps, to see the hurdles and then do it :-)

#0 check on you samsung device developer mode is enabled if not here nice video (not from me!). Also in Developer Options enable USB Debugging !

#1 deinstall on your windows machine all Samsung drivers or existing Samsung Kies Application if installed

#2 reboot windows machine (image)

#3 after reboot plug you Samsung device to the mac and root the samsung to windows machine (yes do this we need a log entry)

#4 after some connect/disconnect loops disconnect the device

#5 shut down windows image and quit vmware

#6 navigate on the mac in finder to the vmware image

#7 secondary click or right mouse click on this file and select "Show Package Contents"

#8 search vmware.log file

#9 open this file in a text editor

#10 search for word "samsung"

#11 you find a line like

013-10-31T18:24:16.553+01:00| vmx| I120: USB: Found device [name:SAMSUNG_Android vid:04e8 pid:6860 path:10/1/1/3 speed:high family:vendor,comm serialnum:9c9679c7 arbRuntimeKey:d version:2]

#12 the intresting values are : vid:04e8 pid:6860 (your numbers can be other, depends from model and usa/europe/asia model how ever)

#13 close log file

#14 in the same folder you find a file yourImageName.vmx

#15 open this file in text editor

#16 add this line: usb.quirks.device0 = "0x4e8:0x6860 skip-reset"

you see there are the same number like the interesting value in step #12. but important the first number is the vid value the second the pid. add for each value the chars "0x"

#17 save file and close finder

#18 start vmware and your image

#19 DO NOT PLUG IN YOUR DEVICE NOW

#20 for deploying apps from Delphi you need a USB ADB Debugging Driver from Samsung. The Driver on the samsung web site is old an did not run an windows 7 and 8. do not install this driver !!! you find in the internet many drivers with virus and/or trojan malware. so be carful. i found the last original and code signed driver from samsung incl 32/64 bit and windows 8 functionality on this site:

http://www.droidacid.com/samsung-usb-drivers-for-mobile-phones-and-android-adb-drivers/

#21 download and install the driver

#22 reboot windows (!)

#23 now plug in your samsung device

#24 wait for finishing installing on windows driver detection

#25 watch on your phone screen. a message is coming to allow windows access the device 

#26 if message not coming after a minute, disconnect and connect again the device (was on my configuration)

#27 now start delphi, create a new android application, refresh device node under the android node and you see you device :-)

now i know, why i prefer iOS Devices

have fun :-)

Te Waka o Pascal: Blowing Smoke…

$
0
0
To alleviate the grind of polishing and sanitising my code (and, let’s be honest, just plain ‘fixing’ it in some cases) ready for release, I have re-kindled my participation on Stack Overflow. In a happy confluence yesterday a question came up which allowed me to exercise one of the libraries that I’m preparing to release: […]

jed-software.com: XE Plus Pack Release 14

$
0
0

Release 14 is now available to all existing XE Plus Pack users. Release 14 also brings support for Delphi XE5.

The reason why the XE5 release was delayed was that the addition on iOS 7 support and a couple of changes to internal IDE component names (which made no sense to change) broke two of my experts. Needless to say, I was waiting for Update 1 to be released before making the XE5 version available.

NOTE: The XE5 release works with or without update 1 and with or without iOS 7 support.

Introducing Debug Visualizer Wizard

This expert is a repository wizard to help made Debug Visualizers without needing to go into much detail about their implementation. It allows you to concentrate on creating custom visualizers which is perhaps one of the most unappreciated IDE features.

Those paying attention will know that this wizard is based off the Blaise Pascal Magazine article written back in the days of Delphi 2010. The code was upgraded and the templates improved and now available from Delphi XE thought to Delphi XE5.

Debug Visualizer Wizard (release 14)

Fixes

There have also been a number of fixes under the hood, however two that will be noticeable are:

  1. Support for adding bookmarks with the bookmark guide when the editor is not docked.
  2. Improved tracing output.

Pricing

XE Plus Pack still costs just 40 Euros and can be purchased cheaper if ordering four or more licenses (contact us for quotes).

  • Purchase XE Plus Pack and get the Delphi XE version.
  • Purchase XE2 Plus Pack and get support for Delphi XE2 -> Delphi XE5.

http://jed-software.com/xepp_purchase.htm

Download

Download your required version from the download page.

To try XE5 Plus Pack download the trial version.

Dr.Bob's Delphi Notes: Personal question about Chinese characters...

$
0
0
When sending messages from Android to iPhone (or vice versa) using Whatsapp or Facebook, sometimes the special "smiley" characters on one end are replaced by chinese/japanese characters on the other end, see http://www.bobswart.nl/chinees.jpg for an example. Just out of personal interest, I wonder if anyone has any idea what these characters actually mean.

Andy's Blog and Tools: IDE Fix Pack 5.4 for 2009-XE5 released

$
0
0

The new IDE Fix Pack 5.4 supports XE5, fixes some bugs in IDE Fix Pack patches and adds new Win32 and Win64 compiler optimizations.

Download IDE Fix Pack:

NameIDE VersionFileSizeDownloadsAdded
IDE Fix Pack 5.42009+UP3IDEFixPack2009Reg54.zip173.75 KB214 times 2013-11-01
IDE Fix Pack 5.42010IDEFixPack2010Reg54.zip159.74 KB298 times 2013-11-01
IDE Fix Pack 5.4XEIDEFixPackXEReg54.zip147.68 KB378 times 2013-11-01
IDE Fix Pack 5.4XE2+UP4+HF1IDEFixPackXE2Reg54.zip217.09 KB480 times 2013-11-01
IDE Fix Pack 5.4XE3+UP1IDEFixPackXE3Reg54.zip213.54 KB373 times 2013-11-01
IDE Fix Pack 5.4XE4IDEFixPackXE4Reg54.zip214.72 KB389 times 2013-11-01
IDE Fix Pack 5.4XE5IDEFixPackXE5Reg54.zip213.62 KB788 times 2013-11-01

Download fastdcc:

NameIDE VersionFileSizeDownloadsAdded
fastdcc 5.42009+UP3fastdcc2009v54.7z75.4 KB89 times 2013-11-01
fastdcc 5.42010fastdcc2010v54.7z79.34 KB91 times 2013-11-01
fastdcc 5.4XEfastdccXEv54.7z81.36 KB136 times 2013-11-01
fastdcc 5.4XE2+UP4+HF1fastdccXE2v54.7z104.53 KB149 times 2013-11-01
fastdcc 5.4XE3+UP1fastdccXE3v54.7z116.06 KB136 times 2013-11-01
fastdcc 5.4XE4fastdccXE4v54.7z107.91 KB145 times 2013-11-01
fastdcc 5.4XE5fastdccXE5v54.7z109.16 KB305 times 2013-11-01

Changed from 5.3 to 5.4

  • Fixed: Possible access violation in PageControlTabSheetCompDropFix.DeleteSelection
  • Fixed: Possible infinite loop in compiler patch (2009-XE4)
  • Fixed: Switching between C++64 and C++32 platform caused “String list does not allow duplicates”
  • Added: XE5 support
  • Added: Optimization for: DCC64 was busy allocating and zero-ing memory for units with many functions (e.g. Generics)
  • Added: Optimization for: DCC64 was busy searching a linear list for units with many Generics
  • Added: Hashtable for compiler directives (improves jedi.inc compilation speed) (2009-2010)
  • Added: Hashtable for symbol lookup in used units
  • Added: Faster inline function compilation (2009-XE)
  • Added: Much better compiler performance if a unit instantiates many Generics (e.g. Spring4D)
  • Added: Fix for *.tds symbols aren’t loaded if the debugger is started with a relative HostApp
  • Removed: Increased Linker I/O buffer

twm’s blog: All registered users deleted and blocked

$
0
0

I just deleted over 700 “users” who registered to my blog. Most, I am sure, were just spam bots, I am sorry if some of you were real people.

Registering is now blocked as is commenting. I got tired of all the notification e-mails from WordPress. In over a year there was only ever two comments that were not spam. It’s just not worth the effort. If you want to communicate with me more directly, use my Google+ profile

Firebird News: Jaybird 2.3 will become Jaybird 3.0

$
0
0
Mark Rotteveel announced : As Jaybird 2.3 is going to be a big change from Jaybird 2.2, I have decided to renumber the version to Jaybird 3.0. Changes planned for Jaybird 2.3 are now planned for Jaybird 3.0. Changes planned for Jaybird 3.0 are now planned for Jaybird 3.1 (but might get into Jaybird 3.0). […]

Te Waka o Pascal: OFFICIAL*1: Delphi is the Worlds Least Efficient Compiler!

$
0
0
That is, according to Embarcadero’s “Chief Evangelist”. I don’t know how else to interpret his claim that the Delphi compiler produces 5MB+ of executable code per line of written code*2. Of course, this isn’t what he means but it’s a conclusion that is just as valid as the initial proposition – that his app consists […]

Te Waka o Pascal: ADB WINLOG 1.0.1 – RELEASED!

$
0
0
Are you doing Android development ? Whether you are using Delphi or some other Android development tool a key tool in the Android developer’s toolbox is the logcat command, part of the Android SDK. But it can be a little… how to put this kindly… crude. So I put together a rather more useful and […]

twm’s blog: More on BitTorrent Sync

$
0
0

Following up on my post on BitTorrent Sync here is some more information and use cases.

There is at least one alternative to BitTorrent Sync that is open source: Seafile is a cloud service. I have only read about it on their website but it looks interesting.

Now to the use case:
If you are like me you are storing lots of data on your smartphone, in particular passwords and other sensitive data. While it is convenient to have this data with you all the time there is always the danger of the phone being lost or stolen and – if you are paranoid enough – the data being stored on Google’s servers (or the servers of a different cloud service).

Of course there are many options to encrypt the data on your phone like KeePass etc. What I don’t like about these solutions is the fact that they encrypt everything, not just the sensitive parts. So if I just want to look up the URL of a website which I use so infrequently that I tend to forget it, this is rather cumbersome. Therefore I use plain text files and encrypt only the parts I deem sensitive (passwords etc.), using the txtCrypt app. Since there exist alternative implementations of the txtCrypt algorithm, including a Web App I can be sure to still get to the encrypted parts even if my phone is not available for decryption.

The other problem with the phone getting stolen is backup and accessing the backup without another phone. There are lots of note keeping apps that synchronize with cloud services (e.g. Google Keep, Evernote or Flick Note). I used all of them for a while to try finding the one that I like best. Unfortunately I didn’t feel comfortable in the knowledge that I have no control over how and where the data is stored, so I abandoned them for the text file approach. For the backup part I have started using the BitTorrent Sync app to sync to my desktop computer (which is backed up anyway). There is another advantage of this approach: You can add and edit files using a real keyboard and the text editor of your choice rather than the virtual keyboard on your phone.

while true do;: ITDevCon 2013 - Some Numbers

$
0
0
Next week, in Verona (Italy) there will be the 5th edition of the biggest European Delphi Conference. This year has been extraordinary for the Delphi community. 2 new versions of Delphi and 2 new platforms (with 2 new big markets). There are very many things to talk about at ITDevCon 2013: Android, iOS, HTML5 and Javascript, [...]

while true do;: DelphiMVCFramework is now Open Source!

$
0
0
Yes, just after 1 year of development, and a couple of big projects developed with it, the DelphiMVCFramework has been published as OpenSource. The project is on google code svn https://code.google.com/p/delphimvcframework/ I’ll talk about it at ITDevCon2013 (http://www.itdevcon.it) In the trunk there are many samples and I’m planning to put many others. Main DMVCFramework features RESTful (RMM Level 3) compliant Server side [...]

Te Waka o Pascal: Extending Smoketest (Part 1) – An Inspector Calls

$
0
0
In the soon to be released Smoketest framework it is sometimes useful to create new test types to supplement the tests built-in to the framework. In this and the next post I will walk through the process of implementing and registering a custom test with the Smoketest framework. In a real-world scenario this may be […]

DelphiTools.info: Multi-Threaded String Building in Delphi

$
0
0
After looking at String concatenation and String Building in Delphi, and as a conclusion, it’s time to have a brief look at what happens in multi-threaded settings, such as in a server pushing JSON, XML or some other text data. Benchmark Results The test case is the same as that of the String Building article,…

The Podcast at Delphi.org: Hello Google Glass from Delphi XE5

$
0
0

Google’s new Glass platform is a very revolutionary Android device, but the question I really wanted to know is if I could develop for it with Delphi XE5. Turns out the answer is Yes.

There are actually two different options for developing Glassware: Mirror API and GDK.

The first is the Google Mirror API, which allows you to build services, called Glassware, that interact with Google Glass. It provides this functionality over a cloud-based API and does not require running code on Glass. This is accomplished through a REST and JSON based API. Thanks to the new TRESTClient components in Delphi XE5 this should be easy enough to do.

The GDK on the other hand is the avenue where you build an actual APK that runs on the Google Glass device itself. This gives you the most access to the device, its sensors and features. Turns out this is also easy enough to do with Delphi XE5.

The actual GDK builds on top of the Android SDK. You can develop apps to run on Glass with either the Android SDK or GDK, but the GDK is necessary to take advantage of some of the Glass specific features.

If you run SysCheck on Glass (which takes some effort) you discover it has an ARMv7 PRocessor rev 3 (v71) with Android OS Version 4.0.4 and NEON support. Those meet the main requirements for Delphi XE5 development. So I created a simple Hello World app and ran it.

This first screenshot shows Glass appearing in the Project Manager as a valid target (once the required USB drivers were installed, which was tricky for glass).

HelloGlassProjectManager

Here is a screenshot of the app running on Glass

Delphi XE5 App running on Google Glass

I didn’t hide the status bar, which most Glassware does, and it does nothing other than serve the purpose of showing a Delphi XE5 app running on Google Glass. There were no special settings (other than the dark theme, which is a matter of taste) to make the app run on Glass. It just works.

And lastly a quick selfie of me and Glass, taken through glass.

JimWithGlass

I was hoping it would look more red than orange, but should have known Tangerine would be orange.

Rest assured, there will be more coverage of Delphi and Glass. We are just getting warmed up. This app was not using the GDK (which is still in Beta) but it is an actual Delphi app running on Glass. What an exciting day!

DelphiTools.info: Source Code for the String Concatenation/Building Benchmark

$
0
0
By popular request, here is the source code used for the previous String benchmarks StringConcatBench.zip, essentially to test alternative memory managers. The source is nothing complicated as you will see, just a set of simple function with the test cases, and a couple function that measure run times. Only the benchmark functions are in the zip,…

The Podcast at Delphi.org: Stops on My North America Tour

$
0
0

I just got back from Brazil and Costa Rica, which was great. Now I am headed out to different cities in North America (Yes, technical Costa Rica is in North America, but all these cities are north of Latin America). David I and Al Mannarino are also traveling across North America for a total of 27 cities. Here are my city stops:

Minneapolis – Meet and Eat
Wednesday, November 13, 2013 @ 12:00pm-2:00pm
Ruth’s Chris Steakhouse
920 2nd Avenue S #100, Minneapolis, MN
[Register]

St. Louis – Meet and Eat
Thursday, November 14, 2013 @ 12:00pm-2:00pm
Ruth’s Chris Steakhouse
315 Chestnut Street, St. Louis, MO
[Register]

Chicago – Hands on Workshop
Saturday, November 16, 2013 @ 9:30am-3:00pm
Hyatt Regency Woodfield – Schaumburg
1800 East Golf Road, Schaumburg, IL
[Register]

  • Wed, 20-Nov Vancouver, BC 12:00pm 2:00pm PST
  • Thu, 21-Nov Calgary, AB 12:00pm 2:00pm MST
  • Tue, 3-Dec Bellevue, WA 12:00pm 2:00pm PST
  • Tue, 3-Dec Bellevue (User Group), WA 6:00pm 8:00pm PST
  • Wed, 4-Dec Portland, OR 12:00pm 2:00pm PST
  • Wed, 4-Dec Portland, OR (User Group) 6:30pm 8:30pm PST
  • Thu, 5-Dec Boise, ID (User Group) 7:00pm to 9:00pm MST

I’m planning to bring my Google Glass and show off Delphi XE5 running on Google Glass too.

Žarko Gajić: Graphical Hints Image in Virtual Treeview Node Hint (Extending TVirtualTreeHintWindow)

$
0
0

delphi-vtw-pdf-hint-graphics-previewIn a Delphi application, the THintWindow class implements the small pop-up window that appears over a control at run time, when the control has its ShowHint property set to True (and has a value assigned to the Hint property).
The implementation of the THintWindow (at least what gets displayed by it, not how) is rather simple: it will display whatever string value is assigned for the Hint property of a control. If you want more control over what gets displayed by the hint window, and how, and when the hint window will popup – you can create your own version by extending the THintWindow class.
To use your own hint you would assign your own class to the global HintWindowClass variable at application start-up time, so that the new hint window type is used for hints. You can even fine tune the display of the hint window just before it pops-up using the OnHint and OnShowHint events of the TApplicationEvents.

That’s all nice and clear. But, what if the control you are using is Virtual Treeview which has its own version of the hint window implemented in TVirtualTreeHintWindow? What if you want to extend this by including some graphics along with the text that the hint window displays? Further, what if you need to have different hint values for every node displayed by the tree?
Of course, you are not working on a new application – all logic is already there, lots of methods and events already implemented.

The answers: here’s how to simply extend both the TVirtualTreeHintWindow and the TVirtualStringTree to add some node specific graphics to the hint window displaying node specific hints.

Here’s the actual real world feature I wanted to quickly have implemented: my application uses Virtual Treeview to present a folder structure containing PDF documents to the user – each node presents either a folder or a PDF file. Hints are node specific and for a file-type node some PDF values get displayed to the user (file name, PDF Title, PDF version, and alike). I wanted also to include a simple 1st page preview (as image) of the PDF file in the hint window.

Download Sample Project Source Code.

Hints in Virtual Treeview (TVirtualStringTree)

For the Virtual Treeview to display hints (node or control specific) the Hint property must be set to true. Next, there’s the HintMode property determining what the hint actually displays (single hint for control or node specific hint value and some more values). Also, there’s the HintAnimation property which determines the kind of animation when a hint is activated. Or, as those are implemented in the source code:

  TVTHintMode = (
    // show the hint of the control
    hmDefault,            
    // show node specific hint string returned by the application
    hmHint,  
    // same as hmHint but show the control's hint if no node is concerned
    hmHintAndDefault,    
    // show the text of the node if it isn't already fully shown
    hmTooltip);

  // Determines the kind of animation when a hint is activated.
  THintAnimationType = (
    // no animation at all, just display hint/tooltip
    hatNone,                
    // fade in the hint/tooltip, like in Windows 2000
    hatFade,                
    // slide in the hint/tooltip, like in Windows 98     
    hatSlide,                
    // use what the system is using (slide for Win9x, slide/fade for Win2K+, depends on settings)
    hatSystemDefault);

Before providing more details, here’s the record type each node stores internally (note: you need some basic knowledge on Virtual Treeview to follow what follows):

  TTreeNodeData = record
  private
    fPreview : TJpegImage;
    function GetPreview: TJpegImage;
  public
    Name: string;
    RelativeName : string;
    IsFolder : boolean;
    property Preview : TJpegImage read GetPreview;
  end;
  PTreeNodeData = ^TTreeNodeData;

As stated, each node in my tree either presents a folder or a (PDF) file. Hence the record field names: Name is the full file/folder name; RelativeName is the path relative to the root directory selected; IsFolder stores if the node presents a folder or a file. Finally the Preview property will lazily get the graphics of the first page of the PDF file (more on that later below).

And here’s what is set in the form’s OnCreate:

  tree.NodeDataSize := SizeOf(TTreeNodeData);

  tree.HintMode := hmHint;
  tree.ShowHint := true;

To have node specific hints you need to implement the OnGetHint event:

procedure TMainForm.treeGetHint(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex;
  var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string);
var
  data: PTreeNodeData;
begin
  data := Sender.GetNodeData(Node);

  HintText := data.Name; //just display full name / file path
end; 

All set, now the question is how do I get some graphics also displayed by the hint window.

Fake Extending (i.e. Intercepting) the TVirtualTreeHintWindow, TVirtualStringTree (Plus Overcoming Some Issues)

First step is to have my own version of the TVirtualTreeHintWindow class, of course by extending what’s already provided. If you’ve ever done some custom THintWindow implementation you know you need to override at least two methods: CalcHintRect and Paint. The CalcHintRect gets the dimensions of the hint window rectangle required to display the hint. Paint does the actual painting (of the hint text).

The second step (actually first) would be to tell to the Tree to use my own version of the TVirtualTreeHintWindow class.

And I hit the wall first time! There’s no public property or method I can call on Virtual Treeview to have it use my own version of TVirtualTreeHintWindow. There IS a method GetHintWindowClass and a comment next to it saying: “Returns the default hint window class used for the tree. Descendants can override it to use their own classes.

Ah! I have to override the entire TVirtualStringTree (i.e. extend / make my own version) to have this. Me no like. I have it (the tree) in many forms in my application and I do not want to change all this. But, Delphi has a solution called “intercepting classes“.
So, I’ve intercepted the TVirtualStringTree, and have it as:

  TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
  private
    fHintModeImage: boolean;
    procedure SetHintModeImage(const Value: boolean);
  public
    constructor Create(AOwner: TComponent); override;
  public
    function GetHintWindowClass: THintWindowClass; override;
    property HintModeImage : boolean read fHintModeImage write SetHintModeImage;
  end;

The newly added property HintModeImage is used to decide if the node hint should also display the image – will the tree use its own TVirtualTreeHintWindow class or my extended version.

Ok, back to extending the TVirtualTreeHintWindow class. Looking into the implementation (long live open source) I see that the protected Paint method (which I can override) is used only when HintAnimation property is “hatNone”, otherwise the class does all the rendering inside the private (cannot override) AnimationCallback method (which calls InternalPaint I also cannot override). Second wall, this time a harder one!

If I want to go cheap I must have no animation on hints – well, ok, I can leave with that (and the users of the application will have to).

Ok, so here’s the simpler part, implementation of my intercepted TVirtualStringTree:

constructor TVirtualStringTree.Create(AOwner: TComponent);
begin
  fHintModeImage := false;
  inherited;
end;

function TVirtualStringTree.GetHintWindowClass: THintWindowClass;
begin
  if HintModeImage then
    result := TVirtualTreeHintWindowEx
  else
    result := inherited; //use what tree uses
end;

procedure TVirtualStringTree.SetHintModeImage(const Value: boolean);
begin
  fHintModeImage := Value;

  if fHintModeImage then
    HintAnimation := hatNone //so Paint procedure is called and can be overridden
  else
    HintAnimation := hatSystemDefault; //default
end;

Finally, here’s how the implementation of my intercepted version of TVirtualTreeHintWindow looks:

function TVirtualTreeHintWindowEx.CalcHintRect(MaxWidth: Integer;  const AHint: string; AData: TCustomData): TRect;
var
  r : TRect;
  hd : TVTHintData;
  jpg : TJpegImage;
  nodeData : PTreeNodeData;
begin
  r := inherited;

  hd := PVTHintData(AData)^;

  if Assigned(hd.Tree) AND Assigned(hd.Node) AND (HintData.Tree is TVirtualStringTree) AND (TVirtualStringTree(HintData.Tree).HintModeImage) then
  begin
    nodeData := HintData.Tree.GetNodeData(hd.Node);

    jpg := nodeData.Preview;

    if Assigned(jpg) AND (NOT jpg.Empty) then
    begin
      r.Height := r.Height + jpg.Height + 4;
      if r.Width < jpg.Width + 4 then r.Width := jpg.Width + 4;
    end;
  end;

  result :=  r;
end;

procedure TVirtualTreeHintWindowEx.Paint; //called only if HintAnimation = hatNone
var
  jpg : TJpegImage;
  nodeData : PTreeNodeData;
begin
  InternalPaint(0, 0);

  if Assigned(HintData.Tree) AND Assigned(HintData.Node) AND (HintData.Tree is TVirtualStringTree) AND (TVirtualStringTree(HintData.Tree).HintModeImage) then
  begin
    nodeData := HintData.Tree.GetNodeData(HintData.Node);

    jpg := nodeData.Preview;

   if Assigned(jpg) AND (NOT jpg.Empty) then Canvas.Draw(2, -2 + Height - jpg.Height, jpg);
  end;
end;

The CalcHintRect first calculates the size of the image (PDF first page preview if you remember), Paint than paints it to the hint window. A simple AND’d IF is used to ensure the tree is ok, the node is here, the data is here etc…

The PDF 1st Page Preview – Using Debenu PDF Library

I guess you are asking yourself from the beginning: how do you get the preview of a page of a PDF file. In short: I’m using Debenu Quick PDF Library.

Without too many details about the Debenu Quick PDF Library (at least for now), here’s how easy is to get the image of a page of a PDF:

function TTreeNodeData.GetPreview: TJpegImage;
var
  fh, pr : integer;
  ms : TMemoryStream;
  bmp : TBitmap;
  pdfFileName : string;
begin
  if fPreview = nil then fPreview := TJpegImage.Create;

  if (NOT IsFolder) AND fPreview.Empty then
  begin
    pdfFileName := self.Name;

    //<a href="http://www.debenu.com/products/development/debenu-pdf-library/" target="_blank">http://www.debenu.com/products/development/debenu-pdf-library/</a>
    with TQuickPDF.Create do
    try
      fh := DAOpenFileReadOnly(pdfFileName, '');
      if fh <> 0 then
      try
        pr := DAFindPage(fh, 1);
        if pr <> 0 then
        begin
          ms := TMemoryStream.Create;
          try
            DARenderPageToStream(fh, pr, 1, 24, ms);
            ms.Seek(0,0);

            fPreview.LoadFromStream(ms);
          finally
            ms.Free;
          end;
        end;
      finally
        DACloseFile(fh);
      end;
    finally
      Free;
    end;
  end;

  result := fPreview;
end;

Destroying/Freeing The Preview Object in Record (When No Destructors)

Note that my TTreeNodeData uses some advanced features like properties and methods in records. The Preview property is an instance of the TJpegImage. The Preview must be freed when no longer needed, and records cannot have destructors. So the question is when and where to free the image? Again, no problem, since the Tree handles record instances it exposes an event where you can free whatever object is assigned to a node when the node is destroyed, the OnFreeNode event:

procedure TMainForm.treeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  data: PTreeNodeData;
begin
  data := Sender.GetNodeData(Node);
  if Assigned(data.fPreview) then data.fPreview.Free;
  Finalize(data^);
end;

And that’s all folks. Some Delphi magic, some exploring of inner workings of controls you are using and the sky is the limit :)

Comments? More than welcome!

Lazarus Team Anouncements: Lazarus Release Candidate 1 of 1.2

$
0
0
The Lazarus team would like to announce the first Release Candidate for the upcoming Version 1.2.

We would like to invite all users to test this Release Candidate.
Please read below why everybody really should join the testing now.

News in this Version...
Viewing all 1725 articles
Browse latest View live