As you are probably aware, CA-Clipper codes can readily be recompiled in Xharbour into a W32 executable. In my scenario, I have a complex processing engine originally written in CA-Clipper 5.2e which can then be called within my Delphi applications
I had earlier used CA-Clipper 5.2e +Fivewin to create a W16 executable which was then called via winexec() from my Delphi Application. Being 16-bits meant that NTVDM was called automatically by Windows. What I wanted was a true W32 executable which will not require the usage of NTVDM.
There are 2 scenarios involved
1) Automatic processing without user input
2) Need for user input before automatic processing takes place
For Scenario 1, all I needed was to recompiled in Xharbour to transform my 5.2e CA-Clipper Codes into a 32-bit true windows application. It is that easy :-)
For Scenario 2, I needed user to input a parameter. Problem is that XHarbour does not have a simple Window Dialog function such as Delphi's InputQuery. So what's the solution ?
The Solution
1) Use Visual xHarbour (VXH) to create a windows form with
a) label control named MessageLabel
b) edit control named InputValueEdit
c) button control named OKBtn
d) button control named CancelBtn
2) Saved the Windows Form as
//MsgGetForm.prg
GLOBAL EXTERNAL Application
GLOBAL cMessage
GLOBAL cCaption
GLOBAL cInputValue
#include "vxh.ch"
#include "MsgGetForm.xfm"
//---------------------------------------- End of system code ----------------------------------------//
//----------------------------------------------------------------------------------------------------//
METHOD CancelBtn_OnClick( Sender ) CLASS MsgGetForm
::close()
RETURN Self
//----------------------------------------------------------------------------------------------------//
METHOD MsggetForm_Form_OnActivate( Sender ) CLASS MsgGetForm
::MessageLabel:caption:=cMessage
::caption:=cCaption
::InputValueEdit:caption:=cInputValue
RETURN Self
//----------------------------------------------------------------------------------------------------//
METHOD OKBtn_OnClick( Sender ) CLASS MsgGetForm
cInputValue:= ::InputValueEdit:Caption
::close()
RETURN Self
MsgGet_XFM.prg (automatically generated by VXH)
#include "vxh.ch"
//---------------------------------------- End of system code ----------------------------------------//
//------------------------------------------------------------------------------------------------------------------------------------
CLASS __MsgGet INHERIT Application
// Components declaration
// Controls declaration
METHOD Init() CONSTRUCTOR
// Event declaration
ENDCLASS
METHOD Init( oParent ) CLASS __MsgGet
::Super:Init( oParent )
// Populate Components
// Properties declaration
::Create()
// Populate Children
RETURN Self
//MsgGetForm.xfm (text definition based on the window form created with VHB)
//---------------------------------------------------------------------------------------------------------------------------------
//
CLASS MsgGetForm INHERIT WinForm
// Components declaration
// Controls declaration
DATA MessageLabel EXPORTED
DATA InputValueEdit EXPORTED
DATA OKBtn EXPORTED
DATA CancelBtn EXPORTED
METHOD Init() CONSTRUCTOR
// Event declaration
METHOD MsggetForm_Form_OnActivate()
METHOD OKBtn_OnClick()
METHOD CancelBtn_OnClick()
ENDCLASS
METHOD Init( oParent ) CLASS MsgGetForm
::Super:Init( oParent )
::EventHandler[ "OnActivate" ] := "MsggetForm_Form_OnActivate"
// Populate Components
// Properties declaration
::Left := 10
::Top := 10
::Width := 534
::Height := 139
::Name := "MsgGetForm"
::Caption := "MsgGetFormCaption"
::ClipChildren := .T.
::ClipSiblings := .T.
::Create()
// Populate Children
WITH OBJECT ( ::MessageLabel := LABEL( Self ) )
:Left := 41
:Top := 8
:Width := 160
:Height := 16
:Name := "MessageLabel"
:Caption := "MessageLabel"
:Border := .F.
:ClipChildren := .T.
:ClipSiblings := .T.
:TabStop := .F.
:Create()
END //MessageLabel
WITH OBJECT ( ::InputValueEdit := EDIT( Self ) )
:Left := 41
:Top := 32
:Width := 445
:Height := 22
:Name := "InputValueEdit"
:ClientEdge := .T.
:Border := .F.
:ClipSiblings := .T.
:Create()
END //InputValueEdit
WITH OBJECT ( ::OKBtn := BUTTON( Self ) )
:Left := 178
:Top := 61
:Width := 77
:Height := 30
:Name := "OKBtn"
:Caption := "&OK"
:Border := .F.
:ClipChildren := .T.
:ClipSiblings := .T.
:EventHandler[ "OnClick" ] := "OKBtn_OnClick"
:Create()
END //OKBtn
WITH OBJECT ( ::CancelBtn := BUTTON( Self ) )
:Left := 268
:Top := 62
:Width := 79
:Height := 31
:Name := "CancelBtn"
:Caption := "&Cancel"
:Border := .F.
:ClipChildren := .T.
:ClipSiblings := .T.
:EventHandler[ "OnClick" ] := "CancelBtn_OnClick"
:Create()
END //CancelBtn
::Show()
RETURN Self
2) Next, I added a wrapper function MsgGet() function in my Main.prg
// function in msggetform.prg
FUNCTION MsgGet(cFormCaption,cFormMessage,cFormInputValue)
// GLOBALs in MsgGetForm.prg
cMessage:=cFormMessage
cCaption:=cFormCaption
cInputValue:=cFormInputValue
__MsgGet( NIL ):Run( MsgGetForm( NIL ), HB_aParams() )
RETURN cInputValue
3) In the calling prg
cRetVal:=MsgGet('Create Data','Input No. of Working Days', @mNo_of_days)
That's it !
What is my wish list for the xHarbour people ? Provide a standard windows function as part of xHarbour :-)
Comments from David A. Smith , comp.lang.xHarbour
Some options are:
1) make a DLL of your "scenario" code, and call it as an unloadable library. (Not sure if there are limitations on collecting user input in a DLL.)
2) call your "scenario" code via OLE / xBScript
3) do it the way you have been doing it, just translate / recompile.
No comments:
Post a Comment