Euro Zone inhabitants can hardly forget their obsolete currencies
By , journalist and programmer
Euro calculator main dialog
The Euro replaced 12 obsolete currencies
Although their old currencies are officially out of circulation now, the Europeans living in the 12 member countries of the European Monetary Union can hardly get familiar with their new currency, the Euro. They still are converting Euros to Dutch guilders, German Marks, French francs or whatever their old money was.

For many citizens this is the only way to 'feel' how expensive things really are. Or, better said: have become. Dutch people, surprised by substantially higher prices, got very nervous and soonly nicknamed the new currency Neuro. Their German neighbours are speaking of Teuro, expressing how 'teuer' (expensive) life has become after the introduction of the common currency in 2002.

But apart from politics: even Mister Euro himself: Dutchman Wim Duisenberg, the first president of the European Central Bank in Frankfurt (Germany), admits he is still converting his spendings to Dutch guilders, surely when large amounts are involved. In other words: more than a year after the introduction of the 'European dollar', a simple Euro currency calculator is still no luxury. Therefore it is offered as freeware here.
Although written as a desktop tool for citizens of the Euro Zone in the first place, the code includes a few programming 'tricks' which may make it of interest for you as a programmer, even if you don't live or reside in one of the twelve Euro-countries.

Subclassed edit controls
The first to be mentioned is the subclassed edit control. The application's main dialog shows 2 textboxes, the upper displaying an amount in one of the 12 former currencies, the lower showing the countervalue in Euros. At a first glance this looks simple to achieve: just give the controls the %ES_NUMBER style. Unfortunately, this lets the control accept numbers only. The decimal delimiter or separator, very important in money calculations, will be refused. Hence, the controls would not accept either centen, centimes, Pfennige and so on, or Eurocents respectively.

Also, a control should accept only one delimiter and - last but not least - the decimal delimiter is not the same in all countries. Some states, such as The Netherlands, officially use the comma, other countries stick with the period. While internally using the period for calculations (simply because this is Power Basic's default), we want the controls to show up with the local decimal delimiter. In other words: allow the user to type both, comma or dot, but modify it when it is the 'wrong' one.

To achieve the above mentioned goals, we need to intercept Windows' %WM_CHAR message. This, unfortunately, cannot be done in the dialog's normal callback function. Therefore we need to subclass the edit controls. Well, thanks to Lance Edmonds' sample in Power Basic's Peer-to-Peer forums, this is not really the huge problem it looks like.

To begin with, we have to 'set' the subclass(es). This is done in the regular callback function of the dialog, during %WM_INITDIALOG. Also, the removal - very important! - is done in the dialog's callback, during %WM_DESTROY. Note that hOldCurrProc and hOldEuroProc are global handles. Also note that this code does not represent the entire callback function, just the part that demonstrates how subclassing is set and de-activated.

 
CALLBACK FUNCTION MainDlgProc()
  
  SELECT CASE CBMSG 
    CASE %WM_INITDIALOG
      ' subclass the edit controls:
      hOldCurrProc = SetWindowLong(GetDlgItem(CBHNDL, %IDC_CURRTEXTBOX), %GWL_WNDPROC, CODEPTR(SubClassProc))
      hOldEuroProc = SetWindowLong(GetDlgItem(CBHNDL, %IDC_EUROTEXTBOX), %GWL_WNDPROC, CODEPTR(SubClassProc))
          
    CASE %WM_DESTROY
       ' de-activate the subclassing
      SetWindowLong GetDlgItem(CBHNDL, %IDC_CURRTEXTBOX), %GWL_WNDPROC, hOldCurrProc
      SetWindowLong GetDlgItem(CBHNDL, %IDC_EUROTEXTBOX), %GWL_WNDPROC, hOldEuroProc
  END SELECT 
END FUNCTION

Screenshot of an About-box
This About box shows the settings of a Germany-based user who prefers to convert Euros to Dutch guilders.
Could be mister Duisenberg's copy, don't you think?

And this is the SubClassProc function itself. It handles the %WM_CHAR messages, generated during input in one of the edit controls. Note that GetDecimal is a function to find out which country-specific character is used as the decimal seperator (comma or dot).

     
FUNCTION SubClassProc(BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
  LOCAL sTemp AS STRING, sDecimal AS STRING
  LOCAL CtrlID AS LONG

  sDecimal = GetDecimal                                                  ' get local decimal delimiter
  CtrlID   = GetDlgCtrlID(hWnd)                                          ' get ControlID using control handle

  SELECT CASE wMsg
    CASE %WM_CHAR
      SELECT CASE wParam                                                 ' wParam contains ASCII code of char
        CASE 8, 48 TO 57                                                 ' backspace and 0...9 / do nothing

        CASE 44, 46                                                      ' comma or dot (possible decimal separators)
          CONTROL GET TEXT GetParent(hWnd), CtrlID TO sTemp              ' get processed text so far
          IF INSTR(sTemp, sDecimal) THEN EXIT FUNCTION                   ' allow only 1 decimal delimiter
          IF wParam <> ASC(sDecimal) THEN wParam = ASC(sDecimal)         ' pass official separator to textbox

        CASE ELSE
          EXIT FUNCTION                                                  ' do not pass any other character
      END SELECT
  END SELECT

  ' finally pass the text to one of the edit boxes
  IF CtrlID = %IDC_CURRTEXTBOX THEN
    FUNCTION = CallWindowProc(hOldCurrProc, hWnd, wMsg, wParam, lParam)
  ELSEIF CtrlID = %IDC_EUROTEXTBOX THEN
    FUNCTION = CallWindowProc(hOldEuroProc, hWnd, wMsg, wParam, lParam)
  END IF
END FUNCTION        
Dialog and control metrics
The second programming 'trick' in my code has to do with the metrics of a dialog and its controls. A neat dialog, created on your own machine by trial and error, does not necessary look good on a screen with a different resolution. For instance, the previous version of this very Euro calculator did not fit correctly on my son's XP-computer. In order to avoid those problems in the future, I wrote METRICS.INC, an include file with functions returning the necessary width and/or height (in dialog units) of the various elements of a control. Using these functions makes it easy to calculate dialog/control metrics, given (for instance) a text to display. The metrics file is included in EUROCALC.ZIP. Of course you are free to use it in your own applications as well.

Getting started
When the Euro calculator is being used for the very first time, it checks whether the user's Regional Settings match one of the 12 countries in the Euro Zone. If that is the case, the (obsolete) currency of that country is set as the default and stored in an .INI-file. In a country outside this Zone, the application automatically presents a Conversion Rates list from which the user can choose a 'favorite' default by clicking one of the 12 country flags.

This rates list may be activated at any time (by clicking the country flag in the main dialog) in order to either modify the default setting or to temporarily alter the currency to convert. Checking the "Set default"-checkbox prior to clicking a country flag changes the default setting. Just clicking a flag also changes the currency, but in this case the modification will not be saved to the application's .INI-file.

Screenshot of rate list
The rate list.


Where to download?
   Click here to download the source code for the Euro calculator.
   This source is also available from Power Basic
   Back to homepage

Copyright © 2000-2003: Egbert Zijlema
Failed to execute script '/cgi-bin/hidden.exe?eurocalc': Win32 Error Code = 2