ClarionX Updates

    follow me on Twitter

    Subscribe

    Enter your email address:

    Delivered by FeedBurner

    Blog powered by TypePad
    Member since 08/2006

    May 27, 2008

    Btrieve 6.15 is my Closest Friend

    For those of you who love "Old School" Database drivers... Btrieve Rocks!

    The core Btrieve 6.15 engine still exists inside Pervasive.SQL and its pretty much the same engine you would have known and loved since its release in 1995 for windows 95/NT.

    It provides extremely efficient, high-speed ISAM data access that can’t be beat by any other access method.

    The latest versions have relational capabilities (a SQL engine).

    Btrieve stands the test of time. Why only now, 27/5/2008 am I considering moving my major application from btrieve 6.15 (circa 1995) to SQL Server Express Edition 2005.

    Btrieve has served me faithfully for 13 years and will go on serving me. Its Gold!

    May 26, 2008

    Twitter - Even the top guys have Corruptions

    Database Corruptions

    No systems no matter how robust are immune to Database Corruptions.

    Twitter Reports:

    Around 11 am in San Francisco, our main database db006, crashed because of too many connections. We have to put the service into an unscheduled maintenance mode to recover. Folks will see degraded service for the next few hours.

    Hats off to the guys at Twitter for making something so popular.


     

    July 09, 2007

    Graduate Programmer Job - Sydney, Australia

    A company I work with requires a Graduate Programmer ( with or without Clarion Experience)....
    A forward and progressive household brand name seeks an enthusiastic and analytical self starter that is looking to develop their career in the IT world.

    At the core of our business is our technology products and team. These products are varied and range from Desktop Applications to Internet Technologies. The products are respected and renowned throughout the world in our market.

    We are currently looking for an excellent University Graduate to join our Technology Team working from our offices located just south of the Sydney CBD.

    We are currently working on some new and exciting major projects that are set to revolutionise the industry. Our senior members of the team will be working closely with the successful applicant/s providing coaching and mentoring that will ensure that you make the transition from studies to success in the corporate environment.

    This is an entry level position for those candidates that have recently successfully completed their Degree in Computer Science (or equivalent) to work on our Desktop Applications.

    Those that can demonstrate the following skills will be highly considered for this role:

    ? Excellent programming skills
    ? Relational database knowledge
    ? Excellent communication skills
    ? Willingness to learn

    This is an excellent opportunity for graduates that are keen to move in to the corporate world and demonstrate their skills, abilities and knowledge to advance their career progression.

    Applications close 20th July 2007, and all successful applicants will be contacted within a week of a close date.
    Email your applications to jmoore@ljh.com.au

    May 29, 2007

    Reading Base64 ...

    This is the first article in an Internet Protocol/encoding Series...As developers we will at one time or another need to read base64 encoded data....heres my take...

    Base64 is used to encode binary files in a text format suitable to be encapsulated in text documents. One interesting thing about base 64 is that it is one of the only data representation
    schemes in modern use that doesn’t encrypt or compress the data. It just represents data
    in a different form.

    The solution to this problem was to create a data representation protocol that would allow
    binary data to be encapsulated within another document. The defacto standard for doing
    this is called base 64. In fact, some applications use base 64 as an encryption technique,
    albeit a weak one. Basic authentication over the Internet encrypts the username-password
    using base 64.

    Here is a simple base64 decoder algorithm that has been very useful over the years...

    base64decode PROCEDURE(STRING b64)

    b64chars STRING('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')

    oString ANY

    CODE

    oString = '' !Dont use CLEAR it will cause a GPF on an ANY Variable

    ! Base64 strings especially those from emails can contain carriage returns and tabs these must be removed before decoding....

    b64 = StringReplace(b64,CHR(9),'')
    b64 = StringReplace(b64,CHR(10),'')
    b64 = StringReplace(b64,CHR(13),'')

    ! Base64 strings are groups of four characters and need to be stepped through by 4....

    LOOP i# = 1 TO LEN(CLIP(b64)) BY 4

    !Create a 24 bit Number by bit shifting the four chars values by  6 bit segments...

    BigNumber# = BSHIFT(INSTRING(b64[i#],b64chars,1,1)-1,18) + BSHIFT(INSTRING(b64[i#+1],b64chars,1,1)-1,12) + BSHIFT(INSTRING(b64[i#+2],b64chars,1,1)-1,6) + (INSTRING(b64[i#+3],b64chars,1,1)-1)

    !Extract the original 3 ascii chars by bit shifting in the other direction by 8 bit segments...

    Char1# = BAND(BSHIFT(BigNumber#,-16),11111111b)
    Char2# = BAND(BSHIFT(BigNumber#,-8),11111111b)
    Char3# = BAND(BigNumber#,11111111b)

    !handle trailing padding characters thus...and translate the character values...
    IF b64[i#+3] = '=' AND b64[i#+2] ~= '=' THEN
    oString = oString & CHR(Char1#)&CHR(Char2#)
    ELSIF b64[i#+3] = '=' AND b64[i#+2] = '=' THEN
    oString = oString & CHR(Char1#)
    ELSE
    oString = oString & CHR(Char1#)&CHR(Char2#)&CHR(Char3#)
    END
    !repeat operation for each group of four base64 chars

    END

    RETURN CLIP(oString)

    The result is the unencoded text or binary data....for more info on base64 like a encoding checkout RFC 3548...

    March 28, 2007

    Fireside Chats

    In the next few weeks ClarionX will be covering topics sent to them by readers regarding Clarion development on the windows platform.

    So if you have any questions or topics of interest...email us.

    ...

    March 27, 2007

    Global Extension Template - ClarionX.tpl

    How do you write an Global Extension Template?

    You can download the full template here.

    Here is a template I started writing along time ago when I was learning about temples and how they could help me be a more efficient developer....

    Open a text editor and create a new file called for example clarionx.tpl (template)

    1. Define the template Chain

    #TEMPLATE(ClarionXTemplates,'ClarionX Dev Tools 1.0')

    2.  Define the Global Extension Template

    #EXTENSION(ClarionXGlobal,'ClarionX Dev Tools 1.0 Global'),APPLICATION

    ,APPLICATION means that it should only be available as a Global Extension and not at the procedure level.

    3. Give the User/developer  some options to play around with in the IDE...

    To generate an include file, txa or txd and/or perform  backups of application txa after each compile...feel free to take this code and improve it....

    #DISPLAY('ClarionX Dev Tools are Enabled'),AT(10,,,)
    #PROMPT('Generate Include File ' & %Application & '.inc',CHECK),%GenerateAppIncludeFile,DEFAULT(1),AT(10,20,,)
    #PROMPT('Generate TXA File ' & %Application & '.txa',CHECK),%GenerateTxaFile,DEFAULT(0),AT(10,30,,)
    #PROMPT('Generate TXD File ' & %Application & '.txd',CHECK),%GenerateTxdFile,DEFAULT(0),AT(10,40,,)
    #PROMPT('Auto Backup eg. TXA ' & %Application & '_yyyymmdd_hhmmss.txa',CHECK),%AutoBackups,DEFAULT(1),AT(10,50,,)

    These are all pretty self  explanatory steps.

    4. Lets get to the guts....

    To get this template to work we need to make sure this template code is only executed when the template is initialised...

    #ATSTART

    #ENDAT

    Generate INC File .... Pretty Simple

    #IF (%GenerateAppIncludeFile = 1)
    #DECLARE(%AppIncludeFile)
    #SET(%AppIncludeFile,%Application & '.inc')
    #CREATE(%AppIncludeFile)
    #FOR(%Procedure),WHERE(%ProcedureExported = 1)
      %(%Procedure & %Prototype)
    #ENDFOR
    #CLOSE(%AppIncludeFile)
    #ENDIF

    Generate TXA File .... Pretty Simple

    #IF (%GenerateTxaFile = 1)
    #DECLARE(%TxaFile)
    #SET(%TxaFile,%Application & '.txa')
    #CREATE(%TxaFile)
    #EXPORT
    #CLOSE(%TxaFile)
    #ENDIF

    Generate TXD File .... Pretty Simple

    #IF (%GenerateTxdFile = 1)
    #DECLARE(%TxdFile)
    #SET(%TxdFile,%Application & '.txd')
    #CREATE(%TxdFile)
    #MESSAGE('Exporting Dictionary...',2)
    #EXPORT(%DictionaryFile)
    #CLOSE(%TxdFile)
    #ENDIF
    #ENDAT
    #ATEND

    Auto Backup .... Pretty Simple...just a datetime stamped TXA

    #IF (%AutoBackups = 1)
    #DECLARE(%BackupFile)
    #SET(%BackupFile,%Application & '_' & CLIP(FORMAT(%ProgramDateChanged,@d12)) & '_' & CLIP(FORMAT(%ProgramTimeChanged,@t5))&'.txa')
    #CREATE(%BackupFile)
    #MESSAGE('Backing Up Program Settings...',2)
    #EXPORT
    #CLOSE(%BackupFile)
    #ENDIF
    #ENDAT

    You can download the full template here. Simply register it in the template registry and thats it....

    This is a good example of the usefulness of templates. With clarionx.tpl dev tools template you can tick a checkbox and  generate a txa or txd, generate an inc file for your dlls and without knowing it checkpoint your code with autobackups ..... pretty handy.

    More templates coming soon....

    March 16, 2007

    ClarionX Rebooted!

    Today the blog has been revitalised....and we apologise for the tardy posting...but lets move on....

    Recently we have been doing some nifty things with Clarion 6.3 and breaking some new ground in the areas of reusabilty and extending applications.

    So stay tuned....for some Clarion Concept discussions...

    The ClarionX Team

    December 04, 2006

    CALL and UNLOAD...The Never Ending Story...

    Thought Clarion App Extensions...

    Wouldn't it be great if we had and architecture which allowed us or 3rd party clarion developers to extend our applications without modifying the base code ... creative use of CALL, UPLOAD and passing an interface class can achieve this...

    More to follow over the next few weeks....

    Cheers Clarion ... My Old Friend...

    When a customer rings you up, gives you a rap and asks you to send an invoice for November and mentions they don't mind paying a premium...if your using C#....that's a miracle...if your using Clarion....its probably because you have delivered a solid product ahead of time and under budget....

    Here is to Clarion and its RAD philosophy....

    How to :: Subclass Windows and do Icons in the System Tray!

    Its simple to add code to your Clarion Application and you too can have icons in the System Tray. The concept is sound and simple to do in windows yourself! Microsoft has all the tools you need in their Windows API to help you extend your clarion apps by yourself...
    Here is a starting point...

    To place icons in the system tray Win API Shell Notify Icon Function does all the work for you - providing an interface to add, change and remove icons from the system tray. (See example code below for implementation)

    If you want animated icons in the System Tray you will need to setup a timer event and change the icons to create the effect of animated gif.

    If you want to capture mouse events on the icon you will need to subclass the windows event handlers of the parent clarion window. (See example code below for implementation)

    Once subclassed you can intercept messages to the window and handle them appropriately....like left mouse clicks on the icon in the system tray. You can also handle windows shutdown grace fully! When windows shuts down it sends a system exit message to all applications running...You can then shutdown your application properly and avoid those Application is still active messages....(See example code below for implementation)

    In further articles I will explain Balloon tips and other issues surrounding icons and windows services.

    Learning through doing is an excellent way to become a better programmer but not necessarily a better developer. Having said that a good mix of both skill sets is essential. I believe that any experience a good or painful one helps us grow.

    Here are some example pieces of code that I use in some of my personal applications at home.

    Example Code: (Subclassing Windows Event handlers)

    After opening window do the following....

    SubClassWindows ROUTINE
    SavedProc1 = Window{PROP:WndProc}
    Window{PROP:WndProc} = ADDRESS(SubFunc1)
    SavedProc2 = Window{PROP:ClientWndProc}
    Window{PROP:ClientWndProc} = ADDRESS(SubFunc2)
    DO SetupNID

    Once subclassed you can intercept messages to the window and handle them appropriately....like left mouse clicks on the icon in the system tray. You can also handle windows shutdown grace fully!

    Example Code: (Subclass WndProc)

    Some code adapted from a clarionmag article some years ago.

    SubFunc1 FUNCTION (hWnd,wMsg,wP,lP) ! Declare Procedure
    WM_QUERYENDSESSION Equate(00011H)
    WM_ENDSESSION Equate(00016H)
    CODE ! Begin processed code
    CASE wMsg
    IF WM_QUERYENDSESSION
         RETURN(TRUE)
    OF WM_ENDSESSION
         POST(EVENT:CloseWindow,,MainThread)
         RETURN(TRUE)
    OF EVENT:NIM
    CASE BAND(lP, 0FFFFh)
    OF LOC:WM_LBUTTONUP ! Left mouse click
       POST(Event:NIM:MouseLeft,,MainThread)
    OF LOC:WM_LBUTTONDBLCLK ! Left mouse double click
       POST(Event:NIM:MouseLeft2,,MainThread)
    OF LOC:WM_RBUTTONDOWN ! Right mouse click - pressed
    OF LOC:WM_RBUTTONUP ! Right mouse click - released
       POST(Event:NIM:MouseRight,,MainThread)
    OF LOC:WM_RBUTTONDBLCLK ! Right mouse double click
       POST(Event:NIM:MouseRight2,,MainThread)
    END
    RETURN(0)
    ELSE
    ! Pass the unhandled event and it's params on to the previous window procedure  in the chain
              RETURN(CallWindowProc(SavedProc1,hWnd,wMsg,wP,lP))
          END
    Example Code:(Icons in the Tray)

    Shell Notify Icon does all the work for you here!!!!

    SetupNID ROUTINE
    TrayCString = 'generic_ico'
    NID:cbSize = SIZE(NotifyIconData)
    NID:hWnd = Window{Prop:Handle}
    NID:uID = 100
    NID:uFlags = NIF_ICON + NIF_MESSAGE + NIF_TIP
    NID:uCBmessage = Event:NIM
    !your defined message to capture in the parent clarion window
    NID:hIcon = LoadIcon(SYSTEM{PROP:APPINSTANCE},ADDRESS(TrayCString))
    NID:ToolTip = CLIP(SVC:ToolTip) & CHR(0)
    DO AddIconToTray
    AddIconToTray ROUTINE
    IF Shell_NotifyIcon(NIM_ADD, ADDRESS(NotifyIconData)) THEN
    Icon change success fult
    END
    ChangeIconInTray ROUTINE
    IF Shell_NotifyIcon(NIM_MODIFY, ADDRESS(NotifyIconData)) THEN
    !Suceeded
    ELSE
    !Failed
    END
    RemoveIconFromTray ROUTINE
    IF Shell_NotifyIcon(NIM_DELETE, ADDRESS(NotifyIconData)) THEN

    Removed

    END

    A lot of this code would be easily adaptable to your own reusable class...enjoy learning...