SMSLibX Integration
Into Visual C++ With MFC

Tutorial and Code Examples

Doc. rel. 1.0 - SMSLibX rel. 2.0

Summary

1 Introduction 3

1.1 Foreword 3

1.2 Basic requirements 3

1.2.1 Library registration and GUID 3

2 Creating an SMS application step-by-step 5

2.1 Creating an SMS application 6

2.1.1 Creating application structure 6

2.1.2 Integrating SMSLibX library in your project 13

2.2 Step 1 – A simple application sending SMS messages 16

2.2.1 Sending SMS messages 16

2.3 Step 2 – A complete SMS-based application 18

2.3.1 Enhancing your interface 18

2.3.2 Receiving SMS and other events by a listener 19

2.3.3 Enabling SMSLibX events capture 21

2.3.4 Opening modem communication 22

2.3.5 Sending SMS messages 23

3 Bibliography 25

1  Introduction

1.1  Foreword

This document shows the needed steps to integrate SMSLibX dynamic library into Microsoft Visual C++ environment using MFC. The related theoretical issues are explained by Microsoft COM objects bibliography.

This document refers to SMSLibX version 2.0 and higher.

Integration examples refer to Microsoft Visual C++ from the Visual Studio 6.0 environment.
You can find the whole examples source code into the zip file provided with this tutorial.

1.2  Basic requirements

The following software must be installed on your PC:

·  Visual C++ 6.0 development environment (included in the Visual Studio 6.0 package)

·  SMSLibX software library

Moreover:

·  Connect your PC to a GSM modem/phone compatible with SMSLibX library (via serial cable, USB cable or other connection type).

·  Install modem communication driver (if needed).

·  Insert a SIM card into your modem (please ensure the SIM has credit enough, and note that this example will automatically delete all messages stored into the SIM).

·  Verify the whole installation by running the SMSLibX Test Utility.

1.2.1  Library registration and GUID

SMSLibX installation automatically registers SMSLibX DLL into your system.

The DLL must be registered on your system in order to be used from your development environment.

Moving the DLL file to another path causes its un-registration.

If the DLL is not registered at all - or it’s not correctly registered – then COM support raises a “Not registered interface” error. In this case you have to perform a manual DLL registration.

In order to manually register/unregister the DLL, please use the following commands from shell:

regsvr32 “[SMSLibX installation path]\SMSLibX.dll”

regsvr32 /u “[SMSLibX installation path]\SMSLibX.dll”

As DLL registration succeeds, the following keys are recorded into your system registry:

[HKEY_CLASSES_ROOT\SMSLibX.SMSModem\Clsid]

@="{GUID}"

[HKEY_CLASSES_ROOT\CLSID\{GUID}\InprocServer32]

@="C:\\Programs\\SMSLibX\\SMSLibX.dll"

GUID is the “globally unique identifier” (a string like: C9F52CD3-807D-4797-BC96-EBA197C00114) of the SMSModem interface exported by SMSLibX. In particular, the [HKEY_CLASSES_ROOT\CLSID\{GUID}\ InprocServer32] key contains the whole path of the currently registered library.

2  Creating an SMS application step-by-step

In order to show SMSLibX integration into a Visual C++ project, we'll create step-by-step a dialog-based application.

You can find the whole examples source code into the zip file provided with this tutorial.

The tutorial is

·  In a first step we’ll only create a simple “Send SMS” button.

·  In a second step we’ll implement SMS receival and other features.

Before using his tutorial, please read the paragraph about basic requirements.

2.1  Creating an SMS application

2.1.1  Creating application structure

We'll create a MFC dialog-based application with a button to send SMS.

1.  From File > New > Project menu select MFCAppWizard (exe) item.

Assign the following name to the new project: TestSMSLibX

2.  After confirmation with <OK> button, select a "dialog based" application type:

3.  Press <NEXT>, then select the Automation checkbox (if you forget this operation, your code won’t be able to generate COM objects at runtime!!!):

4.  Press <NEXT> and accept all the remaining defaults suggested by the wizard:

  1. Press <NEXT> :

6.  Press <FINISH> button:

7.  Confirm by pressing <OK>:

8.  Now your application structure is ready. From the ResourceView section of the Workspace window, please double click on the "Dialog" resource identified by the name "IDD_TESTSMSLIBX_DIALOG". Drag the button symbol from the controls toolbar into your dialog box (if the control toolbar is not visible, right click the mouse on the main toolbar and activate the Controls check):

9.  Right-click your new button, then select the Properties menu item:

10.  Replace ID field with “IDC_SEND” and Caption field with "SendSMS":

11.  Right-click the button again, then select the Events... menu item. A code creation wizard will be started:

12.  Select “BN_CLICKED” and “IDC_SEND” items from the available lists, then press the Add Handler button. Input ‘OnSendSMS’ as member function name and press OK.

13.  Now you can access to the newly created source code, by pressing Edit Existing button on the wizard dialog. You'll edit this code section later by inserting the code needed to send an SMS.

14.  As already done with the dialog button, please add a “Static text” control to your dialog and assign a “Send To” value to its Caption property. Then add an “Edit Box” control to your dialog and set its ID property to “IDC_DESTNUM”. This control will be used for SMS destination number input.

2.1.2  Integrating SMSLibX library in your project

1.  Now we’ll use the Class Wizard to generate wrap classes for SMSLibX library. Please select ClassWizard from the View menu – then, from the Automation section, select Add Class > From type library…

2.  Browse the file system in order to find the SMSLibX.dll file installed by SMSLibX installation procedure and press <OK>. Then press <OK> to confirm the creation of all the listes classes.
This operation will create and add the following files to your project: SMSLibX.h and SMSLibX.cpp.

3.  Another file is needed to provide constants and enumerations defined by SMSLibX library: SMSLibXConstants.h (you can find it into the zip file provided with this tutorial).

Please note:

- the SMSLibXConstants.h file is related to SMSLibX 2.0 version

- if you are using an higher version, you must modify this file manually with updated constants values and the right SMSLIBX_VER value

Please copy the SMSLibXConstants.h file into your project source directory and include it into the project through using the “Project > Add To Project > Files …” menu:

4.  Finally, add the following code lines to the TestSmsLibXDlg.cpp include section:

#include "SMSLibXConstants.h"

#include "SMSLibX.h"

2.2  Step 1 – A simple application sending SMS messages

2.2.1  Sending SMS messages

1.  Replace the CTestSMSLibXDlg::OnSendSMS() method with the following code (also available from the zip file):

void CTestSMSLibXDlg::OnSendSMS()

{

CString oper;

char str[128];

memset(str,0,128);

// Instantiate a modem wrapping object and link it

// to the related COM object exported by SMSLibX DLL (SMSLibX.SMSModem)

_SMSModem modem;

if( !modem.CreateDispatch("SMSLibX.SMSModem") ) {

AfxMessageBox("Cannot link to SMSLibX.SMSModem object: SMSLibX library may be not registered!");

return;

}

///////////////////////////////////////////

// PLEASE UPDATE YOUR MODEM SETTINGS HERE

///////////////////////////////////////////

// Modem type (see SMSLibXConstants.h)

long modemType = SMSLibXConstants::GSMModemTypeConstants::gsmModemDummy; // modem simulator

//long modemType = SMSLibXConstants::GSMModemTypeConstants::gsmModemSiemens; // modem Siemens

//long modemType = SMSLibXConstants::GSMModemTypeConstants::gsmModemCustom; // custom modem // ... (other profiles available on SMSLibXConstants.h)

// Modem serial port number (real or virtual) (e.g. 1 for COM1:)

short comPort = 1;

// Use the predefined SMSC number stored on SIM

CString smscNumber = "";

// Enable/disable incoming messages notification (see SMSLibXConstants.h)

long notifyMode = SMSLibXConstants::SMSModemNotificationConstants::smsNotifyNone;

// Require GSM network registration at startup

bool unregisteredMode = false;

// Timeout for modem startup (60 seconds)

short timeout = 60;

///////////////////////////////////////////

// Set hourglass

CWaitCursor wait;

try {

// Enable log trace (SMSLibX.log on Windows users's temporary folder)

oper = "Enabling modem log";

modem.SetLogTrace(true);

// Open modem communication

oper = "Opening modem communication";

modem.OpenComm(modemType, comPort, smscNumber, notifyMode, timeout, unregisteredMode);

// Compose SMS message

oper = "Creating SMS message";

// (a) get recipient from dialog

CString destNumber;

GetDlgItemText(IDC_DESTNUM, destNumber);

// (b) set message text

time_t currentTime;

time( &currentTime );

CTime now( currentTime );

CString msgTxt = "This is a test message from SMSLibX (" + now.Format("%H:%M:%S") + ")";

// Send SMS message

oper = "Sending SMS message";

int msgId = modem.SendTextMessage(destNumber, msgTxt, false);

AfxMessageBox("Message correctly sent to "+destNumber+":\n\n"+"\""+msgTxt+"\"");

} catch (CException* e) {

e->GetErrorMessage(str, 128);

AfxMessageBox("Failure on "+oper+":\n"+str);

e->Delete();

}

// Close modem communication

try{ modem.CloseComm(); }catch(...){;}

// Release link to COM object

modem.ReleaseDispatch();

}

2.  Modify the following values assigned by the previous method, according to your settings:

·  modemType your modem profile (gsmModemDummy is a modem simulator for test purpose)

·  comPort your modem serial port number (real or virtual)

3.  Save and compile the whole code, then run the application.

4.  Now you can send your first SMS message: please use an international format for message recipient (e.g. “+393381234567”).

5.  If you’re using the modem simulator, thet you might get some random errors issued for test purpose, when trying to send a message.

2.3  Step 2 – A complete SMS-based application

2.3.1  Enhancing your interface

This section requires a more skilled C++ developer, able to manage a dialog-based MFC application in an independent way. No further indications will be given here about the development environment. The following part will only explain source code modifications needed to manage asynchronous incoming messages.

Message receival will be implemented through COM events handling. Such issue is well-explained on the provided bibliography ([1], [2]).

Please start from the application created in the previous section and add the following modifications.

1.  From the ResourceView section of the Workspace window, select and modify the "Dialog" resource identified by “IDD_TESTSMSLIBX_DIALOG" name, in such a way that it looks like the following:

Please configure the added controls as follows:

Type / Caption / ID / Description
Button / Open Comm. / IDC_OPEN / Used to init modem communication.
Edit field / - / IDC_DESTNUM / Used to insert recipient phone number.
Button / Send Message / IDC_SEND / Used to send a test SMS to the specified recipient.
List box / Trace events / IDC_TRACEEVENTS / Used to show modem communication status and to trace received messages. Please modify Style properties as follows:
sort: disabled
horizontal scroll: enabled

2.  Add to TestSMSLibXDlg class the code needed to handle asynchronous writing to the "IDC_TRACEEVENTS" list box control and to activate horizontal scrolling when needed:

//SMSLibX - ADD START

static void HandleHScroll(CListBox* lb, LPCTSTR s) {

CClientDC dc(lb);

CFont * f = lb->GetFont();

dc.SelectObject(f);

CSize sz = dc.GetTextExtent(s, _tcslen(s));

sz.cx += 3 * ::GetSystemMetrics(SM_CXBORDER);

if(sz.cx > lb->GetHorizontalExtent()){

int width = sz.cx;

lb->SetHorizontalExtent(width);//activate list box horizontal scrolling

}

}

static CString Now(){

//build message text

time_t currentTime;

time( &currentTime );

CTime now( currentTime );

return now.Format("%H:%M:%S ");

}

void CTestSMSLibXDlg::Trace(const CString& s)

{

#ifdef _DEBUG

afxDump < s < "\n";

afxDump.Flush();

#endif

CString line = Now()+s;

CListBox* lb = (CListBox*) CWnd::FromHandlePermanent(s_traceListHwnd);

lb->AddString(line);//add the line to the end of the list (as the listbox is not ordered)

HandleHScroll(lb,line);//activated, when needed, horizontal scroll

}

//SMSLibX - ADD STOP

2.3.2  Receiving SMS and other events by a listener

1.  Add to TestSMSLibXDlg class header the attributes needed to handle SMSLibX interaction:

//SMSLibX - ADD START

private:

_SMSModem m_modem; //wrapper for the COM object exported by DLL

LPUNKNOWN m_pSink; //pointer to the object implementing, client-side, the handling of events

//generated by "SMSModem" COM object

unsigned long m_advCookie; //events listening "booking" identifier

static HWND s_traceListHwnd; //list box control handle (thread-safe)

//SMSLibX - ADD STOP

2.  Using the ClassWizard, generate – by extending the CCmdTarget class – the new SMSModemSink class to be used to handle events. Enable it to handle ‘Automation’.

This class represents the core of "SMSModem" COM object events handling and must be manually modified as follows:

3.  add to the new class all the listening methods exported by the COM interface __SMSModem. In order to accomplish this, we suggest to act, by Class Wizard, on Automation tabsheet.
The signature of methods to be added can be retrieved from __SMSModem.h header which has been automatically generated at the initial steps of your application creation.

4.  add the following attributes/methods to the SMSModemSink class header:

//SMSLibX - ADD START

private:

CTestSMSLibXDlg* m_owner;//dialog box pointer

// Attributes

public:

void setOwner(CTestSMSLibXDlg* owner){ m_owner=owner;}

//SMSLibX - ADD STOP

5.  now you have to implement the event listener methods for message receival, delivery receipt, new modem status and incoming call. In this example, events are just captured and traced on your dialog:

//SMSLibX - MODIFY START

// This event is raised when modem status changes

void SMSModemSink::NewStatus(long status)

{

const char* stname;

switch(status){

case SMSLibXConstants::SMSModemStatusConstants::smsModemInit: stname = "INIT"; break;

case SMSLibXConstants::SMSModemStatusConstants::smsModemReady: stname = "READY"; break;

case SMSLibXConstants::SMSModemStatusConstants::smsModemClosed: stname = "CLOSED"; break;

default: stname = "UNKNOWN";

}

// Trace event on dialog

CString str("<MODEM-Status> ");

str += stname;

m_owner->Trace(str);

}

// This event is raised when a sent SMS message changes its status

// (only if delivery receipt has been required)

void SMSModemSink::StatusReport(LPDISPATCH FAR* statusRep)

{

_SMSStatusReport rep;

rep.AttachDispatch(*statusRep);

// Trace event on dialog

CString str("<SMS-Status> ");

str += "To: " + _GSMAddress(rep.GetDestination()).GetAddress() + ", ";

str += "Status: "+ rep.GetMessageStatusName() + ",";

str += "Date: "+ COleDateTime(rep.GetLastUpdate()).Format();

m_owner->Trace(str);

rep.DetachDispatch();

}

// This event is raised when an incoming SMS message is received

void SMSModemSink::MessageReceived(LPDISPATCH FAR* message)

{

_SMSDeliver msg;

msg.AttachDispatch(*message);

// Trace event on dialog

CString str("<SMS-Received> ");

str += "From: " + _GSMAddress( msg.GetOriginator() ).GetAddress() +", ";

str += "Body: '" + msg.GetBody() +"'";

m_owner->Trace(str);

msg.DetachDispatch();

}

// This event is raised when an incoming call is received (and automatically rejected)

void SMSModemSink::Ring(LPDISPATCH Originator)

{

_GSMAddress orig;

orig.AttachDispatch(Originator);

// Trace event on dialog

CString str("<CALL-Received> ");

str += "From: " + _GSMAddress( orig ).GetAddress();

m_owner->Trace(str);

orig.DetachDispatch();

}

//SMSLibX - MODIFY STOP

6.  now comes a very important operation: please replace the code section created by Class Wizard, containing the IID_ISMSModemSink variable definition, with the following code: