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: StatCounter Global Stats - Screen Resolution Market Share


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:

Does FireMonkey have anything similar to GetSystemMetrics?


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

How to get the DBDemos Database into ElevatdDB

There are several Delphi tutorials out there that use the DBDemos database that ships with Delphi. I tend to learn much better if I actually perform the tasks outlined in these tutorials rather than just reading or viewing them. However, I'd much rather perform these tasks using ElevateDB, since this is the database I have chosen for all my new applications.

I started looking around to see if someone has done this already. I was looking for a .zip file out there in internet land. I posted to the ElevateDB support group hoping someone had a .zip file I could get my hands on. What I found was much more valuable.

One of the regulars, Roy, said why don't you just use the "built-in BDE migrator" that comes with ElevateDB.
This is one of the coolest things I have done with ElevateDB. I learned so much more going through this process then I would have if I simply downloaded some .zip off the internet.This whole process takes less than 5 minutes from start to finish. It looks very complicated but believe me it's not.

Step 1 - Create a Session Called DBDemos

Make sure you have the ElevateDB Manager up and running. Right-Click on ElevateDB Manager and then choose Create New Session

General Tab

There are two things that need to be done inside the General tab.
  1. Name:  DBDemos
  2. Description:  DBDemos database that ships with Delphi
DO NOT CLICK OK . . Switch to the Local tab

Local Tab

There are two things that need to be done inside the Local tab.
  1. File Folder:  Enter the location for configuration file for this session. Don't worry if this folder doesn't exist, it will get created for you later on.
  2. Large File Support:  Make sure this box is checked.
DO NOT CLICK OK . . Switch to the Login tab



Login Tab


There are three things that need to be done inside the Login tab.
  1. User Name: Administrator
  2. Password: Enter:  EDBDefault
  3. Confirm Password:  EDBDefault
NOW CLICK OK


Click Yes if prompted to create folder.


Step 2 - Create Database Migrators

Now we need to add the database Migrators that come with ElevateDB to the DBMemos session.
  • Expand the ElevateDB Manager by clicking on the + (Plus)
  • You will see the DBDemos session we just created
  • Expand the DBDemos session by clicking on the + (Plus)
  • Right-Click on DBDemos
  • Choose Create Database Migrators


Step 3 - Create an Empty DBDemos database

Now we need to add the database Migrators that come with ElevateDB to the DBMemos session.


  • Expand the ElevateDB Manager by clicking on the + (Plus)
  • Expand the DBDemos session by clicking on the + (Plus)
  • Right-Click on Databases
  • Choose Create New Database...


There are three things that need to be done on the General tab
  1. Name:DBDemos
  2. Description: DBDemos Database that ships with Delphi
  3. Folder: Enter the location where you want the database files to reside. In my example I simply use a DB folder in the same location as the session folder.
CLICK OK WHEN DONE

Click OK when Done


Step 4 - Migrate the DBDemos Database and Into ElevateDB

 We are almost done, this is the final step.

  • Expand ElevateDB Manager by clicking on the + (Plus)
  • Expand DBDemosseaaion by clicking on the + (Plus)
  • Expand Databases by clicking on the + (Plus)
  • Right-Click on DBDemos database
  • Choose Migrate Database...


There are seven things that need to be done on the Migrate Database Source tab.
  1. Migrator: Choose BDE
  2. Ckeckbox: Make sure Include Table Data is checked
  3. Parameters Grid: Click DatabaseName to highlight the grid row
  4. Value: Enter DBDemos
  5. Click Set Paramter Value button
  6. Veify the Parameter Grid shows DBDemos for the DatabaseName
  7.  Click OK
 

Congratulations. You now have an ElevatdDB version of the DBDemos database you can use to follow along with all the Delphi tutorials out there.

Enjoy!

Semper Fi - Gunny Mike

Thursday, May 3, 2012

Rethinking the Use of Stored Procedures

As I mentioned in a previous post, I was absent from Delphi programming for about 7 years. During that time I worked 50-60 hours a week on custom database driven websites using ASP and Microsoft SQL Server. I estimate that this resulted in 200 (plus/minus) websites.

Programming for the web taught me about statelessness, bandwith conservation, and the biggie, SQL Injection. Being the lead programmer I developed standards for the use of stored procedures in everything we did. I learned a lot, made my fair share of mistakes, and developed a deep admiration for stored procedures.

The focus became take a request from a webpage, go to the server, do as much on the server as possible while you are there, and return the results to the webpage. Works great.

So, now I'm back into Delphi and rewriting a desktop application that hasn't been updated since 2004. The jump from D5E to D2010 in itself, has been a challenge. I'm also going from a non-database application to a databse application. The database I have chosen to use is ElevateDB.

One of the reasons I chose ElevateDB was it offers stored procedures. I love stored procedures, they are like black boxes. As long as the interface doesn't change they are good-to-go and offer awesome power.

So, I'm taking all this thinking I developed throughout those web years and applying it straight to Delphi and the application rewrite I'm doing. I know that a stand alone desktop application doesn't have to worry about statelessness, or bandwith conservation, and for the most part SQL injection. But it's hard to re-learn to think... until the rubber meets the road.

The rubber met the road when I decided to build my first report using ReportBuilder. I've never truely had a reporting tool before... even in my web days I built everything from scratch. So, I took the amortization schedule I built as an ElevateDB stored procedure and made that my first report. Everything is going well, the report looks professional, I'm having fun.

Then I start thinking... wow it wouldn't be nice to add a a percentage of payment next to the principal column. Wouldn't it be nice to show the percentage of interest also. And it would be totally awesome to bunch them by the year the payment is due. So, I decide to add two calculated fields to my report, no big deal. PrinPct is simply Payment divided by Principal.

Then I realized...
  • You can't add a calculated value from a stored procedure column
  • You can't do a group by based on the the year of the payment
  • Wow, building a report based on the result set of a stored procedure is not the best approach
"My first thought was, great ReportBuilder doesn't let me do what I want to do. This sucks."
Then I realized...
"It's not ReportBuilder, it's me. My thinking is wrong. Stored procedures are not meant to be reported on... they are meant to do the heavy lifting that makes the data easy to report against"
I'm glad that this happened to me early on in the process. I would have been quite upset had I created a total database with 30-40 stored procedures all built on the assumption that they could be used as datasets for reporting.

Back to the drawing board... another lesson learned.

Semper Fi, Gunny Mike

Wednesday, May 2, 2012

Reporting Tool Survey

Here is an unsophisticated poll to see which Delphi reporting toll is used. Please only vote once.

(Participation in this poll requires a Linkedin account)

Thursday, April 26, 2012

Composite Reporting With Mixed Orientation

I have spent the last two weeks researching different reporting tools for Delphi. I currently own Delphi 2010 Professional which comes with Rave built into the IDE. My customers have asked me for a "one-click" printing solution. Instead of previewing and printing each report one-at-a-time, they would like to simply press the [ Print ] buttton once and "presto" all the reports get printed. That is a fairly reasonable request.

Rave

So, I tried firing up the built in Rave tool. My first impression was tremendous anxiety. I literally felt like I was in the cockpit of an airplane staring at all these unrecognizable controls. The database product I use is ElevateDB and I had failed at several attempts to get hooked up to an active dataset. Finally, I somehow stumbled into a control that produced live data. I felt like on was on track.

So, now I'm looking to see how I can create a composite report. I like the idea of providing my customers with a "one-click" solution. However, the reports I need to create are a combination of portrait and landscape orientations. Now, the task has just gotten a little more trickier.

I need to create a composite report that allows a combination of portrait and landscape orientations.

I begin my quest for knowledge like I always do... StackOverflow. I quickly came across the following post regarding Rave. Migrating from QuickReport to FastReport, Rave Reports or what? This sounded interesting seeing how my older programs used Quick Reports. After reading some of the comments it further drove me away from Rave.

Quick Reports

I'm familiar with Quick Reports I even purchased the profession version when I was using Delphi 5 Enterprise. I know Quick Reports lets you create composite reports but does it allow for the mixing of portrait and lanscape orientations withing a single report. The answer is no. Here is the response I received from the developer:

Hi,

It can't be done with the present code. I'm not sure why but mixing report orientations just doesn't work.

Regards, QBS Software Ltd

So, Quick Reports is out. That's too bad because I have already spent several hours with that tool even though it was eight years ago.

FastReport

Now this looks promising. FastReport comes bundled with Delphi XE2 (which I will be upgrading to fairly soon). So far so good. I'm still waiting to here from them wether they support mixed orientation within a composit report. I'll update this post when I find out.

Report Builder (Digital Metaphors)

This is the reason I am writing. The answer is YES. Report Builder supports a composite report with mixed orientation. I sent three emails and received three emails from the sales and support team at Digital Metaphors within a 1 hour span. Not only did they answer my question, they gave me a link to Delphi code that shows an example of how to do this very thing. But wait there's more. . .

Here is their mission statement lifted right off the website...
At Digital Metaphors Corporation we believe that our existence is guaranteed only when we successfully complete the actions listed below on a daily basis:

  • Create software of the highest quality
  • Ensure that customers receive the maximum possible value from our software
  • Go the extra mile in every phase of the software business
  • Make things go right
  • Regardless of circumstances, use intelligence, common sense, and inspiration to create results which are a service to both our customers and our fellow employees
  • I started looking around their website for some nuggets and I came across a download called Learning ReportBuilder. This is a hands-on learning experience. It combines a 145 page step-by-step guide with a report builder tool that thoroughly teaches you how to use their product.

    I definitely felt like I was in the cockpit of an airplane looking at all the controls except this time, there was an instructor sitting right by my side guiding me through each maneuver. The controls will look familiar to any Delphi programmer. If you are in the market for a reporting tool, I urge you to download the Learning ReportBuilder hands-on tutorial before you make a decision. It's that good.

    I want to thank David Cornelius from cornelius concepts for telling me about Report Builder.

    Semper Fi,
    Gunny Mike

    Sunday, January 1, 2012

    Wisdom: Rekindle That Enthusiasm

    Happy New Year!

    I was thinking about my software the other day. I have a piece of software I created over 20 years ago and it still sells today. Somewhere along the line I lost my enthusiasm for this product. Maybe I got busy on other stuff, maybe sales weren't as robust as I thought they should have been. Anyway for whatever reason I seem to have lost enthusiasm for my software... until now.

    A few weeks ago I was watching a show on TV about singers and songwriters who created hits back in the 1960s. And when these artists got up to perform their songs even though these songs are more than 50 years old they sang them with enthusiam and gusto. This got me thinking that I'm missing the boat here with my software.

    If you're like me and you have a software product that's been selling for twenty years and it's still selling today, that tells you people like your stuff. I'm going to say that again. If you have a software product that's been selling for twenty years and it's still selling today, that tells you people like your stuff. So take it from me don't become complacent. Don't take that fact for granted.

    So this year starting today January 1, 2012, a brand-new year, I'm changing the attitude I have about my software. I will treat my software as though it were a hit song. My software is a hit. If you're in the same boat as me I want you to recognize the fact that you have a hit as well. Hits don't come along that often, in fact there are some songwriters who are known as one-hit wonders. They spend their entire lives creating songs and for just one, single solitary moment, everything came together just right and they produced a hit.

    Why is this important and what difference does it make? As you talk about your product are you enthused? People can tell. I need to be more enthused. If I'm not excited how can I expect my customers to get excited. When describing product features and benefits do you sound monotone or are you enthused? If you're not it is fair to expect people to get enthused. And believe it or not there's a group of people out there who have never seen your product before.

    My last assignment for the Marine Corps was Marine barracks Washington DC. And from Memorial Day until Labor Day every Friday night from five o'clock until midnight we were put on our dress blues and entertained the crowd who came to see the parade and the Marine Corps Silent Drill Team.

    The first three or four weeks of every new parade season was exciting. We haven't done this for a while. We get all dressed up in pretty clothes and we walk around representing the Marine Corps's finest. And then the thought of the long, dreaded season would set in. I remember the first time this happened to me and I thought "oh my goodness I have four more months of this."

    So from that point on I told myself, "Michael you are going to meet somebody tonight that has never been to Washington D.C. before. Not only has this person never been to D.C. before, but this is the only time this person will ever come to Washington D.C. in their entire life. You don't know who that person is. So treat each person that you meet tonight as though it's that person."

    If I can do that for the entire Marine Corps parade season, I can do that for my product and so can you. You are going to talk to somebody and your website will meet somebody, who has never seen your product before. This could be a one time shot. You don't know who this person is, so treat everybody as though it's that person.

    Semper Fi,
    Gunny Mike