Sunday, July 14, 2013

Raize Components Seeking FireMonkey Feedback

I purchased Raize Components about a year ago after watching a CodeRage demo. I have just barely scratched the surface of how to use this set of components. I'm in the middle of porting an old 640 X 480 D5 application. My original goal was to do this using D2010 but I didn't make enough progress and needed to take advantage of the XE4 upgrade pricing. So, now I'm porting this over to XE4.

There are a lot of things to like about RC, too many to mention here. Like many of you I am now faced with the FireMonkey decision. Should I go the VCL route or use FireMonkey? I can tell you this... if Raize had a component set for FireMonkey that was as good as the RC VCL tools my answer would be FireMonkey without one bit of hesitation..

Which brings me to this point. I need to get a new version of my software out there before it becomes obsolete. So, I'm going to stick with the VCL side for now. Once that is done then I will look at a FireMonkey port. However, if you have been using FireMonkey and you find yourself frustrated with some of the "out of the box" features there's one person who wants to hear from you, his name is Ray Konopka.

I recently visited the RC support forum and here is a portion of Ray's response when asked if he plans to port RC to FireMonkey. (read full thread)
...simply trying to port the Raize Components controls over to FireMonkey is probably not a good use of resources and would not have the same impact that the product has on the VCL side.

Instead, our plan is to determine those tasks that are difficult for developers to accomplish in FireMonkey and provide custom FireMonkey controls to address those needs. There may be some controls that are similar in design to a Raize Components controls, but will be specifically designed for FireMonkey. In fact, it will probably be a new product line.

Unfortunately, I do not have any specifics to share at this time. But I would encourage you to share with us your experiences with FireMonkey and what specific tasks are difficult for you to accomplish. We've been building a list of our own, but the more feedback we can get the better.

Ray
I'm a such a FireMonkey noob I won't be much help in building a FireMonkey "wish list". Here's where you FireMonkey guys come in. If you have a nit-pick about a standard FireMonkey control or if you find yourself frustrated because the standard FireMonkey controls makes things difficult Ray wants to hear about it.

Send your FireMonkey ideas to radiant@raize.com

I'm not going to totally rely on you guys. Believe me when I come across a FireMonkey nit-pick I'll send it to Ray.

Now, let's get this party started!

Semper Fi,
Gunny Mike
end.

Saturday, July 13, 2013

Add DBDemos to ElevatdDB Manager on Windows 7

It turns out that Windows 7 has issues with BDE Administrator. I found this out when I tried to migrated the DBDemos database to ElevateDB Manager. (ElevateDB Manager is to ElevateDB as SQL Management Studio is to SQL Server)

I got this very strange error...


PDOXUSRS.NET error
What the hell is PDOXUSRS.NET?

It's a file BDE uses to store Paradox user information. It turns out that the default location BDE uses for storing information is the root of Drive C: . Unfortunately, Windows 7 does not allow this behavior. This was one of those "I love Delphi, I hate Delphi" days. I hate spending six hours trying to figure out this kind of crap. Now that it's figured out... I love Delphi... go figure.

Here how to fix this error:

First and foremost the BDE Administrator (bdeadmin.exe) must be set to run in Compatibility mode for Windows XP (Service Pack 2). If you don't change the compatibility mode setting for this program it will sit and spin when you try to save the changes. At that point your only option is to kill it with Task Manager.

Step 1: Set bdeadmin.exe to run in compatibility mode with XP SP2



Step 2: Create a folder in the root of the C: Drive called BDEShare

Step 3: Run BDE Administrator and change the NET DIR setting to C:\BDEShare


Step 4: Right click on PARADOX and choose Apply
Step 5: Click OK
Step 6: Close the notification dialog
Step 7: Close BDE Adminstrator
Step 8: Follow the instructions in my original DBDemos post

Semper Fi,
Gunny Mike
end.

Friday, July 12, 2013

ElevateDB Will Soon Support Mac OSX

I'm very excited about a recent tidbit of information I learned regarding ElevateDB. How I came about this piece of info is kind of interesting.

I recently upgraded to XE4 Enterprise from D2010 Professional. I have about 7 minutes total FireMonkey experience. My number one goal for 2013 is to get an old D5 application with no database functionality ported over to XE4 with ElevateDB functionality.

So, I watched a recent EMBT video about converting a VCL applications to FireMonkey with the use of a converter program that comes with XE4. The presentation was done by Marco Cantu and was very interesting. When Marco was done speaking David I appeared and conducted the Q&A.

At 14:32 of the video they show a screenshot of the conversion product website that displays the CD Collector application written by the folks at ElevateSoft. This application is a sample Delphi project that comes with ElevateDB.

CD Collecter - Sample Delphi Application that comes with ElevateDB

So, being an absolute FireMonkey noob I wanted to know if this converted FireMonkey version of the CD Collector application would run on a Mac. I just assumed if you successfully convert a VCL application to FireMonkey then "poof" it would automatically run on a Mac.

I set out trying to get an answer... I got my answer... NO! The underlying database, in this case ElevateDB, would also have to support the Mac OSX operating system.

I asked my question on the ElevateDB support forum and got a surprising answer.

"No, it won't, at least not until we have Mac support for EDB added.  I'm
hoping to have it done before the end of summer."  (read entire thread)
That is very exciting news for all of us that use ElevateDB.

I have renewed enthusiasm because I now know that if I create a FireMonkey version of my old D5 application using ElevateDB I'll be able to target the Mac OSX. This a win win for me. I will finally be able to say YES to people who ask if my software is available for the Mac.

Thank you EMBT!
Thank you ElevateSoft!

Product Links:  XE4, ELevateDB, Mida Converter

Enjoy,
Gunny Mike
end.

Sunday, June 2, 2013

XE4 dbGrid Still Buggy - Please Vote Up QC 98255

This weekend I installed XE4 Enterprise on my new (well new to me) Windows 7 machine. I ran the Getting Started sample project that comes with FireDAC and the first thing I did was click the column heading in the dbGrid and guess what . . . it still has that annoying "black left edge" bug I reported a couple years ago.

My request has gotten no votes. Please go to EMBT's Quality Central and vote up QC 98255.

http://qc.embarcadero.com/wc/qcmain.aspx?d=98255


Black Left Edge Appears When Clicking Column Heading

I don't think I'm being nit-picky about this annoying behavior. When I use programs that display data in a grid, my expectation is to be able to sort the data by clicking on the column heading. I want to build the same functionality into my grids.

I hate this black line that shows up when you click a dbGrid column heading. In my mind it's very unattractive and looks extremely unprofessional.

For the amount of money we pay EMBT for Delphi you would think they would fix this bug. You would think EMBT would want to put their best foot forward and give us die-hard Delphi users, an out of the box dbGrid worthy of the Delphi name.

Go vote for QC 98255 so this damn thing gets fixed.

Semper Fi
Gunny Mike

Update 06/04/2013 6:50 PM:

It turns out that the black line is intended functionality. It is used to indicate the new location where a column is being moved to. I wish that the black line would only show up when the column heading is being dragged and not just being click.

Update 09/22/2013 11:03AM:

The following was posted on the EMBT QC site:

----------
Clinton Johnson at 6/2/2013 8:11:38 AM -
Also, as a work around, he can disable column moving by creating a proxy class to access TCustomGrid's protected items and removing goColMoving from it's Options property with code like:

Type
  TMyCustomGrid=Class(TCustomGrid)
And placing
  TMyCustomGrid(DBGrid1).Options := TMyCustomGrid(DBGrid1).Options-[goColMoving];

in the onFormCreate and after anywhere he modifies the grid's options.  Changing DBGrid1 for each unique instance, obviously.
----------

This work-a-round works perfectly fine for me since I do not need the ability to move columns around. Just wanted to pass this on.

Saturday, May 25, 2013

Konopka Answers The FireMonkey Question At Code Rage 7

I did not attend Code Rage 7 but I just learned that Ray Konopka is working on a set of FireMonkey tools. He has not published a date as to when this tool set will be available but I'm glad to hear he's working on one. Here is the Code Rage 7 video that loads at 36 minutes and 2 seconds right where the FireMonkey question gets asked:

Ray Answers The FireMonkey Question At Code Rage 7

Semper Fi,
Gunny Mike

Sunday, May 19, 2013

XE4 Upgrade Decision

I'm currently using Delphi 2010 Professional and it's time to make that upgrade decision . . . again. The first decision I had to make was should I upgrade to Rad Studio XE4 or Delphi XE4. I've decided to upgrade to Delphi XE4.

Now I have to decide which version of Delphi XE4 should I go with, Professional Upgrade ($494.10) or the Enterprise Upgrade ($1,349.10).  That's a difference of $855. So I decided to study the Delphi XE4 Feature Matrix.

The Professional version has three different Optional features:
  • 1 Requires purchase of Mobile Add-On Pack for Professional
  • 2 Requires purchase of FireDAC Client/Server Pack for Professional
  • 3 Requires purchase of Mobile Add-On Pack for Professional for use with mobile apps. Requires purchase of FireDAC Client/Server Pack for Professional for use in Windows and Mac apps.
Each one of Optional features requires a separate purchase:

1. Mobile Add-On Pack for Professional ($494.10)
2. FireDAC Client/Server Pack for Professional ($399.00)
3. Both of the above ($848.10)

For me, Chances are I'd have to purchase the above tems if I went with XE4 Professional. However, the above items are included in the Enterprise version of XE4. So that makes the difference a whopping $6.90.

With XE4 Enterprise you also get
  • Additional UML MODELING
  • dbExpress drivers available for 64-bit Windows InterBase, Firebird, Oracle, MySQL, SQL Anywhere, Informix, and SQLite
  • dbExpress drivers available for OS X InterBase, Firebird, Oracle, MySQL, SQL Anywhere, Informix, and SQLite
  • TSQLMonitor support for SQLite
  • DataSnap Mobile Connector support for latest versions of iOS, Android and BlackBerry
  • Several dbExpress server connectivity versions
  • DataSnap capability
  • A couple additional BizSnap pieces
  • Some IntraWeb pieces
So, given my track record for slow upgrades it looks like the best choice for me is the upgrade to Delphi XE4 Enterprise.

Note: The prices quoted came from embarcadero's website store on 05/19/2013.


 Semper Fi,
Gunny Mike








Sunday, March 3, 2013

Create Your Own Magical Delphi Tour

There is no time like the present to create your own "Magical Delphi Tour". I'm currently working on upgrading a software program that turns twenty years old in 2014. Wow, who would have thunk it.

You are probably thinking, "Delphi wasn't around in 1994", and you would be correct. However, Delphi's predecessor Turbo Pascal was. So my Magical Delphi Tour includes TP which was a DOS product.

So how do you run Turbo Pascal programs today... through the magic of DOSBox. DOSBox lets you run your old Turbo Pascal programs. Once your old DOS programming is running you can take the screen shots you need for your own trip down memory lane.

Thank you Borland, Code Gear, Embarcadero and DOSBox. May the next twenty years be as much fun:


Credit Card Math 1994: Turbo Pascal 5.5


Credit Card Math 1994: Turbo Pascal 5.5


Credit Card Math 1998: Delphi 3


Credit Card Math 2004: Delphi 5


Credit Card Math 2013: Delphi 2010 (1st Attempt)


Credit Card Math 2013: Delphi 2010 (2nd Attempt)
Semper Fi,
Gunny Mike

Sunday, February 24, 2013

Raize Components 6.1.2 Now Available


Raize Software is very pleased to announce the immediate availability of Raize Components 6.1.2. The primary focus of version 6.1.2 is support for Embarcadero RAD Studio XE3 Update 1 with C++ 64-bit support. Also included are enhancements and bug-fixes.

The new build is free for all registered Raize Components 6 users.
Click here for details.

For more information about Raize Components 6, click here.

In case you are like me and not very observant when it comes to some things, I want to point out that Ray includes the entire source code for the RCDemo program. I just found out about that yesterday even though I purchased the componets back in July.

You can learn a lot from Ray and how he structures his code.

Enjoy - Semper Fi
Gunny Mike





Saturday, January 19, 2013

ISV Conference 2013 - September 27-29 - Reno, NV

I just learned about the ISV Conference being held September 27th, 28th & 29th in Reno, NV. The last time I went to anything that was remotely similar to this was 1995 when I attended the STAR (Shareware Trade Association and Resources)  party which was held at the same time as the SIC (Shareware Industry Conference).

ISV Conference 2013

As a Delphi developer there are hundreds of resources available for learning how to do things with the Delphi language. StackOverflow is probably my favorite resource.

As a Micro ISV, developing software is only one part of the total picture. In fact it's my belief that developing the software is the easiest part of the process. For me the other pieces are much more difficult:

  • Sales
  • Marketing
  • Promotion
  • Distribution
  • Support
I am planning to attend the ISV Conference this year, hope to see some of you there.

Please vote in the ISV Conference poll in the top right margin.

Semper Fi,
Gunny Mike






Monday, October 8, 2012

EvelateDB 2.11 Just Released - Supports XE3

ElevateDB 2.11 is now available for download. If you're an existing customer, then you should be receiving an email shortly with download instructions. You can view the release notes, including any breaking changes, on the download page before downloading.

This release includes support for Embarcadero RAD Studio XE3 and a new package naming convention to make referencing the ElevateDB runtime packages easier for VCL/FireMonkey applications and other design-time 3rd party packages.

News Release
ElevateDB

Semper Fi,
Gunny Mike

Saturday, August 25, 2012

Making Sense of the Whole Delphi WinRT Thing

I'm not one of the "Low-Level" "Deep-Inside" Delphi smart guys. I'm just an average software developer who uses Delphi to create simple applications I sell to other average people. Oh, I learn a lot hanging around the smart guys but I seem to get lost when the discussions and comments take a deep dive.

It's no doubt that Allen Bauer's post created quite a stir around the community and the new release of XE3. I've tried to make sense of all the buzz going back and forth but at one point it just got way over my head.

Since I am just a Micro-ISV, I am looking for a simplistic answer to what this whole Delphi - WinRT crap is all about and I think I have figured it out.

I posted this on the Delphi Developer group on Facebook:
I've been trying to follow all the talk about what is going on with Delphi and WinRT ever since Allen Bauer's post went viral. I'm not as smart as most of you Delphi guys. Can someone please explain in very simplistic terms what it means when Delphi either can't or is excluded from creating WinRT apps? How does this effect a Micro-ISV like myself in terms of distribution and sales?
I received this response...
For example, you will probably not be able to sell your app through the MS Application Store, which could really hurt your exposure to prospective new customers.
Okay. So I started googling Microsoft App Store and discovered a couple interesting tidbits.

I started off reading a post by George Ou called ARM Battery Life Advantage Myth Lives On

This lead me to a post by Steven Sinofsky called Collaborating to deliver Windows RT PCs

Which lead me to another post by Steven Sinofsky called Building Windows for the ARM processor architecture

Here is what I think is going on and how it effects me and you who sell software to the average consumer.


Microsoft is leading a push to compete directly with the iPad. So, Microsoft invented a new operating system called WOA or Windows on ARM which in my opinion is a Reduced Instruction Set Computer. This new operating system is a subset of Windows 8 and will be available on the new WinRT PC's soon to be released.

It sounds like WinRT PC's (I'd prefer they were called tablets) are a separate line of personal computers designed to compete directly with the iPad market. No disk drive, no expansion slots, one or two USB ports and completely mobile. Which requires a long life battery, hence the first post I sited above. These devices will be RISC (Reduced Instruction Set Computers) running the WOA which includes WinRT. This limits the applications to only those applications that conform to the WinRT subset of instructions.

All other Non-WinRT PC's will come with a full blown Windows 8 OS in addition to the scaled down WOA running WinRT. This lets you run all the currently developed Windows Applications (those created using Delphi) and any of the new applications that conform to the WinRT subset of instructions.

What does all this mean to you and I...


Given that the WinRT PC's (I'd prefer they were called tablets) have a subset of the real Windows 8 OS, the only way to install software on these machines will be through the use of the Microsoft App Store. Since Microsoft controls this store they will make sure that any app in the store will run without problems on the new WinRT machines.

The bottom line, we (Delphi developers) will still have a huge user base availabe to us. Not everyone will flock to these new WinRT PC's (I'd prefer they were called tablets). When EMBT finally does get the details worked out and makes it available to us... we can retool, recompile and look forward to a windfall of new WinRT customers.

Enjoy - Semper Fi
Gunny Mike

Thursday, August 23, 2012

Priceless: Behind the Code with Anders Hejlsberg

I just watched this interview with Anders Hejlsberg for the first time. This is truly an amazing interview. It's rather long, about 1 hour, but it is so worth it. I'm not giving anything away... you'll have to just watch and enjoy.



Enjoy - Semper Fi
Gunny Mike

Tuesday, August 7, 2012

Raize Components Makes Id/Value Pair Logic A Breeze

I have known about Raize Components for a long time. The buzz I've always heard was something like this... "Oh yeah, Raize is good if you want a nice consistent look to all of your components within your program."

That's not really very exciting when you are thinking about spending $400.

Then I watched a video from Code Rage 5 where Ray demonstrates and talks about his components. Wow, did this change my mind. I purchased Raize Components 6.0 three days later. Here is the Code Rage 5 video I'm talking about UI Design with Raize Components.

There's also an XE2 Code Rage 6 video UI Design with Raize Components and RAD Studio XE2

You owe it to yourself to watch one or both of these videos.

Anyway, I have a passion for using Id/Value pairs in all of my lookup code. I find it much easier to pass around an integer Id instead of the actual string value. I guess this comes from years of creating databases with lookup tables based on nonsensical auto-increment Id's.  For example:

tblColors
IdValue
1Blue
2Green
3Red
4Yellow

So, I was very excited when I learned that the TRzComboBox component from Raize supports Id/Value Pairs.  You just right click on the control, choose Edit Items & Values and enter your Id value pairs.
 
When you want to retrieve the Value associated with the ItemIndex of the control you simply reference the TRzComboBox.Value property.

Okay that was the easy part. Now how do you go about doing the opposite, setting the control so the ItemIndex refletcs the Id value? That's a good question.

Suppose we have the value 7 which represents "Seven" stored in an interger variable and we want to set the control so that Seven is the highlighted item.


You simply iterate through the control testing each of the values to see if it matches. Upon a match you set the ItemIndex.

Raize makes this easy beacause it exposes both the Value property and the Values property. Value corresponds to the ItemIndex and Values is a TStringList of all the values.

Below is a simple little program to demonstrate how to do set the ItemIndex to the Value. It does require Raize Componets 6.0 from http://www.raize.com/

The key is a little helper procedure that accepts two parameters. The first is a TRzComboBox, and the second is the Id value. By passing the TRzComboBox by reference it allows any changes to the ItemIndex to happen directly to the control itself.

Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer);
var i :integer;
begin
  for i := 0 to cb.Count - 1 do
    if x = StrToInt(cb.Values[i]) then
    begin
      cb.ItemIndex := i;
      Exit;
    end;
end;
As you can see, it simply iterates through the list of values looking for a match and when found it Exits.

Enjoy,
Semper Fi - Gunny Mike

 UPDATE 08/08/2012  9:25 PM EST

I just received an email from Ray Konopka regarding TRzComboBox.Value property. It turns out that the Value property is a read/write property. That means you can assign a value to the Value property and it will change the ItemIndex property automatically! How simple is that...

RzComboBox1.Value := IntToStr(7);

Thanks Ray and keep up the great work.




object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 203
  ClientWidth = 226
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object RzButton1: TRzButton
    Left = 64
    Top = 112
    Width = 110
    Caption = 'Value = 1'
    TabOrder = 0
    OnClick = RzButton1Click
  end
  object RzComboBox1: TRzComboBox
    Left = 64
    Top = 32
    Width = 110
    Height = 21
    TabOrder = 1
    Text = 'One'
    OnChange = RzComboBox1Change
    Items.Strings = (
      'One'
      'Two'
      'Three'
      'Four'
      'Five'
      'Six'
      'Seven'
      'One Hundred'
      'Nine Nine Nine')
    ItemIndex = 0
    Values.Strings = (
      '1'
      '2'
      '3'
      '4'
      '5'
      '6'
      '7'
      '100'
      '999')
  end
end

unit SetComboBox;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
  Forms, Dialogs, StdCtrls, RzCmboBx, RzButton;

type
  TForm1 = class(TForm)
    RzButton1: TRzButton;
    RzComboBox1: TRzComboBox;
    procedure RzButton1Click(Sender: TObject);
    procedure RzComboBox1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer);
var
  Form1: TForm1;

implementation

{$R *.dfm}

Procedure SetComboBoxValue(var cb:TRzComboBox; x:integer);
var i :integer;
begin
  for i := 0 to cb.Count - 1 do
    if x = StrToInt(cb.Values[i]) then
    begin
      cb.ItemIndex := i;
      Exit;
    end;
end;

procedure TForm1.RzButton1Click(Sender: TObject);
var
  i,j : integer;
begin
  i := Random(RzComboBox1.Count);
  j := StrToInt(RzComboBox1.Values[i]);
  RzButton1.Caption := 'Value = ' + IntToStr(j);
  SetComboBoxValue(RzComboBox1,j);
end;

procedure TForm1.RzComboBox1Change(Sender: TObject);
begin
  RzButton1.Caption := 'Value = ' + RzComboBox1.Value;
end;

end.

Saturday, July 7, 2012

How to deal with Programmer's Block

Eventually, we all go through a bout of Programmer's Block. What is Programmer's Block? It's very similar to Writer's Block except it happens to programmers.

I have been struggling for a very long time with Programmer's Block and didn't realize it. I knew what I wanted to do (vaguely) but just couldn't get things off to a good start. For me, it was the big picture... I could not see the big picture.

I started playing around with the little pieces. I worked on the tiny algorithms knowing I would fit them in somehow... but I just didn't have that aha, big picture moment. And then...

I posted this question on P.SE "How do you get past the Analysis to Paralysis when working on a new project?" and within 3 minutes it received 1 down vote and 1 vote to close. I was not happy. I'm thinking great... even the people on P.SE are not going to help. (try this link instead)

Soon I got some great feedback. I'm not going to repeat it all here... don't think I could. Might be copyright violation. So, you'll just have to read it there. Make sure to read the comments... there's some really good stuff in them.

I love yellow stickies.

This post is dedicated to all of you who have or will go through "Programmers Block".

Special thanks to:
haylem & Thorbjørn Ravn Andersen

Enjoy! Semper Fi
Gunny Mike

Sunday, July 1, 2012

Restoring Quick Config on a TMS AdvStringGrid

I recently purchased the TMS Component Pack mainly because of the grid capabilities TMS offers over Delphi's native grid. So I started playing around with the grid and flipping things on and off to see how the grid would be affected.

I was playing around with the "Set Look" option of the Quick Config. I tried out every option and settled on Windows XP. Then I clicked the little X in the red box and ... poof it was gone. No more Quick Config. I spent the next three hours trying to figure out how to turn it back on.

Property ShowDesignerHelp determines wether the "Quick Config" is on or off. Geez, I was looking for a property called "QuickConfig"... no wonder I couldn't find it.

Semper Fi,
Gunny Mike































Sunday, June 10, 2012

Rounding the Currency type like they taught us in school

I started using Delphi's Currency type for it's accuracy only to discover it doesn't round the way I would have expected it to round. I remember being taught in school that when rounding numbers if the remainder was equal to or greater than five you round up otherwise you round down.

For Example:
  • 12.344 Rounds to 12.34
  • 12.345 Rounds to 12.35
  • 12.346 Rounds to 12.35
This is how I was taught in school.
This is how Microsoft Excel does it when you set the cell to display as two decimal places.
This is how Microsoft SQL does it when you format the display as two decimal places.

'---------------------------------
' Microsoft SQL
'---------------------------------
DECLARE @Money money
SET @Money = 12.345
SELECT CONVERT (varchar(10),@Money,1)
'---------------------------------
12.35
But that's not how Delphi does it.

'---------------------------------
' Delphi 2010
'---------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  s : string;
  c : currency;
begin
  c := 12.345;
  s := '';
  s := s + 'Value ' + FloatToStr(c);
  s := s + Chr(13);
  s := s + Format('Formatted as money = %m',[c]);
  ShowMessage(s);
end;


So this lead me looking around for an answer. It appears that Delphi uses what is known as Bankers Rounding which means round to the closest even number. I was never taught this in school. This is how Bankers Rounding works:
  • 12.345 Rounds to 12.34
  • 12.355 Rounds to 12.36
  • 12.365 Rounds to 12.36
I do not want this type of rounding behavior... I want the rounding that I was taught in school. The problem is Delphi's internals do not support this type of rounding. (This is where I have one of those love hate realtionships with Delphi. I hate Delphi!)

So I posed a question on StackOverflow and after clarifying what I meant, got a couple interesting responses. Here is a solution I found reading through the Embarcadero discussion mentioned in my question on SO.
function RoundCurrency(const Value: Currency): Currency;
var
  V64: Int64 absolute Result;
  Decimals: Integer;
begin
  Result := Value;
  Decimals := V64 mod 100;
  Dec(V64, Decimals);
  case Decimals of
    -99 .. -50 : Dec(V64, 100);
    50 .. 99 : Inc(V64, 100);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  s : string;
  c : currency;
begin
  c := 12.345;
  s := '';
  s := s + 'Value ' + FloatToStr(c);
  s := s + Chr(13);
  s := s + Format('Formatted as money = %m',[c]);
  s := s + Chr(13);
  s := s + Chr(13);
  s := s + 'Using the RoundCurrency function';
  s := s + Chr(13);
  s := s + Format('Formatted as money = %m',[RoundCurrency(c)]);
  ShowMessage(s);
end;

Now that's more like it. I love Delphi!

Enjoy
Semper Fi - Gunny Mike

Sunday, May 13, 2012

Plan Ahead When It Comes To FireMonkey & iOS

I don't intend to move to XE2 or XE(next) anytime soon, I have my hands full just porting over my old applications from D5 to D2010. However, I would like to take advantage of FireMonkey and the iOS market when the time is right so I'm planning ahead and so can you.

I am currently working on adding Inifile support to my application to keep track of window sizes and position. I asked on StackOverflow if FireMonkey has anything similar to GetSystemMetrics. Whiler posted a snice snippet of code that uses FX.Platform. (Merci Beaucoup Whiler)

My first thought was it's too bad I can't use this piece of code today. Then I had one of those aha moments. I thought to myself,
"Why not add this as a comment in your Delphi code."
So that's what I did.

Begin Code Snippet
{
----------------------------------------------------------------
FireMonkey Consideration:
----------------------------------------------------------------
Question asked on stackoverflow:
http://stackoverflow.com/questions/10564505
I'm rewriting an old application using Delphi 2010 and I'd like
to put placeholders in my code for when I port it over to XE2.
Just curious if FireMonkey has an equivilent to GetSystemMetrics.
I'm specifically interested in:

GetSystemMetrics(SM_CXSCREEN)
GetSystemMetrics(SM_CYSCREEN)
----------------------------------------------------------------
If you just need the main monitor size, and not the desktop size
(n monitors sum), you can use this:

uses ..., FMX.Platform;

var   p: TPointF;
begin
  p := Platform.GetScreenSize;
  ShowMessage(Format('X: %f' + LineFeed + 'Y: %f', [p.X, p.Y]));

From: Whiler
http://blogs.wittwer.fr/whiler/
----------------------------------------------------------------
}
unit IniFileStuff;

interface

uses
  Windows, SysUtils, Forms, IniFiles;

type
  TScreenType  = (MainScreen, PreviewScreen);

Procedure InitializeIniFile();
Procedure ResetScreenSection(ScreenType:TScreenType);
Function WindowStateToInt(WSType:TWindowState):integer;
Function IntToWindowState(WSInt:integer):TWindowState;
...
End Code Snippet

So, even though I'm not using FireMonkey today, I've documented my code so when I do go to use FireMonkey I'll have a decent head start.

Don't keep it - Pass it on.
Semper Fi - Gunny Mike

Wednesday, May 9, 2012

Keeping Screen Resolution in Mind

I'm redoing an old Delph 5 app that forced a screen resolution of 640 x 480 on the users. At the time this application was deveopled that screen resolution was acceptable but not anymore. Todays endless arrays of screen resolutions brings on new challenges. One of the things I plan on doing at application start is interrogate the current screen resolution and set my application screen size to a ratio of 80%.

I'm amazed at how much information is available. Here is a nice graph that shows the top 10 screen resolutions in use from 2008 through 2012.





Source: http://gs.statcounter.com/#resolution-ww-monthly-201201-201301-bar


Add MultiMon to the uses clause The button click event lets you move the program between two monitors to get the screen resolution.
procedure TScreenResolution.Button1Click(Sender: TObject);
var
  MonInfo: TMonitorInfo;
  ScreenW, ScreenH : integer;
begin
  MonInfo.cbSize := SizeOf(MonInfo);
  GetMonitorInfo(MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST), @MonInfo);
  ScreenW :=  MonInfo.rcMonitor.Right  - MonInfo.rcMonitor.Left;
  ScreenH :=  MonInfo.rcMonitor.Bottom - MonInfo.rcMonitor.Top;
  Label2.Caption := IntToStr(ScreenW);
  Label4.Caption := IntToStr(ScreenH);
end;
Semper Fi - Gunny Mike

FireMonkey Update - 05/13/2012:

I'd like to thank Whiler from StackOverflow for a FireMonkey example using FX.Platform:



Sunday, May 6, 2012

Print to File Options Supported by ReportBuilder

Wow, I'm really impressed with the out of the box, Print to File options that come with ReportBuilder. All you do is set the AllowPrintToFile to True and you are done!

The default Print to File option is PDF. But there are several others. The image formats create one image per page. The HTML option creates an *_htm_images folder for any images that might be on the report.


Image modifed to show all Type options

Print to File accepts the Page Range options as well. I even tried breaking it by printing page 3 of a 2 page report. No errors popped up and no output file was created.

I am extremely pleased with my purchase. ReportBuilder has proven to be everything I expected it to be and more.

Semper Fi - Gunny Mike



A Simple Way to Learn About Methods and Properties

I've decided this time around with Delphi, I'm going to do things as best as I possibly can. A long time ago I met Jeff Duntemann (here's his blog). If you know Jeff, you know he has an astounding vocabulary. I asked him about that once and he responded:
"Michael, the reason for my vocabulary is simple, my parents. When I asked for the definition of a particular word they told me to look it up in the dictionary. And while you are reading about that word, read about every word on both facing pages."
Jeff developed this habit when he was young and he still carrys it with him today. What a simple concept. I have decided to use this idea when I go looking up a the reference to a property or method of a Delph object. Not only am I going to read about the property I was intially interested in, I will read about all the other properties and methods.

Thank you Jeff, I finally figured out how to use your dictionary lookup idea!

Semper Fi - Gunny Mike