DvdKite

Hi all !!

Finally after so many test I've successfully menaged how to create an "ATL Active X control for smart devices" in order to read an RFID tag with a compact flash Reader connected in the slot of my pocketpc 2003.

Now, for testing the application (the reading process)on ppc I've displayed on the screen the obtained value (char [514]) in the ONDRAW method... and it correctly display on the screen all my step point and the final result!

Now, that I've correctly realized the reading process, I need that the ActiveX dll work without diplay anything on the screen but simply return the " patiente ID " (read from the RFID tag) to an html page (the place where the activex is called....

How can I, for example, put from the ATL ActiveX a char into an input box

How can I return a Value from the Active X and put it in an input box or field(in a html page obliviously)

Please help me !

I really need it very soon and I'm sure it's easy!! :-)

Thanks!

Every comment is appreciated!

Dvdkite



Re: Smart Devices VB and C# Projects How to receive a value (char) in an html page from an ActiveX ATL control (PPc2003)

Christopher Fairbairn

Hi,

DvdKite wrote:
Finally after so many test I've successfully menaged how to create an "ATL Active X control for smart devices" in order to read an RFID tag with a compact flash Reader connected in the slot of my pocketpc 2003.

Congratulations on getting this far, by the sounds of it you have got all the really hard bits completed.

DvdKite wrote:
How can I, for example, put from the ATL ActiveX a char into an input box

How can I return a Value from the Active X and put it in an input box or field(in a html page obliviously)

Perhaps the easiest way is to have your ActiveX control expose a property (and or event). You can then use a little bit of javascript within your HTML document to read the current value of the property exposed by your activex control.

To add a property to your ActiveX control within the class view window (accessable via the View, Class View menu item) you should see an entry called 'abcLib' (where abc is replaced with whatever you named your project). If you expand this part of the tree, you should see a further entry called '_abc'. If you right click on this you can select 'Add Property...' from the Add submenu.

This will bring up a wizard dialog which allows you to create a property which should be accessable via Javascript etc. For a string propery (such as an RFID Tag ID), you should select BSTR for the property's type.

If you select the radio button which selects "Get/Set methods" as the implementation method, you should see that the following methods have been added to your project (for a property called 'SampleProperty'). It's then simply a matter of adding your getter/setter code to flesh out it's implementation.

Code Snippet

BSTR CABCCtrl::GetSampleProperty(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

CString strResult;

// TODO: Add your dispatch handler code here

return strResult.AllocSysString();

}

void CABCCtrl::SetSampleProperty(LPCTSTR newVal)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: Add your property handler code here

SetModifiedFlag();

}

Having your ActiveX control expose an event, allows your activex control to notify the javascript running within your HTML document of changes immedatly, rather than requiring the javascript to continually poll your property for changes.

A lot of this process is discussed in the following how to guide on MSDN available on http://msdn2.microsoft.com/en-us/library/aa454894.aspx

Hope this helps,

Christopher Fairbairn






Re: Smart Devices VB and C# Projects How to receive a value (char) in an html page from an ActiveX ATL control (PPc2003)

DvdKite

Hi Christopher,

As always many thanks for your answer! :-)

Christopher Fairbairn wrote:

To add a property to your ActiveX control within the class view window (accessable via the View, Class View menu item) you should see an entry called 'abcLib' (where abc is replaced with whatever you named your project). If you expand this part of the tree, you should see a further entry called '_abc'. If you right click on this you can select 'Add Property...' from the Add submenu.

I've done what you've suggested but I can't see the "_abc" option in my three:

To create my ATL control I've used the "Hello Word" ATL sample from the msdn, and then I've inserted all my other methods for the READER / Tag Rfid communications. So the name of the project is ATLAXcontrol and I've found the ATLAXcontrolLib, but inside the three there's not another ATLAXcontrol , but only the samplecontrol and it hasn't the option "Add property"...

What should I suppose to do now

Am I doing something wrong

Should I try to insert manually this (I need only the GET) code (below) into the "ATLAXcontrol.idl" Or where

Christopher Fairbairn wrote:

Code Snippet

BSTR CABCCtrl::GetSampleProperty(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

CString strResult;

// TODO: Add your dispatch handler code here

return strResult.AllocSysString();

}

void CABCCtrl::SetSampleProperty(LPCTSTR newVal)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: Add your property handler code here

SetModifiedFlag();

}

Another questions!

At the moment My Active X is launched from the onDraw method from the sampleControl.h, inside it I call my methods from other cpp files and you can see it in the RED PART of this code (that is the only parts I've inserted into this automatically generated code):

Code Block

// samplecontrol.h : Declaration of the Csamplecontrol
#pragma once
#include <atlctl.h>
#include "ATLAXcontrol.h"
#include "comm.h"
#include "std_readwrite.h"
#include "stdafx.h"
#include "resourceppc.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif


// Csamplecontrol
class ATL_NO_VTABLE Csamplecontrol :
public CComObjectRootEx<CComSingleThreadModel>,
public IDispatchImpl<Isamplecontrol, &IID_Isamplecontrol, &LIBID_ATLAXcontrolLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IPersistStreamInitImpl<Csamplecontrol>,
public IOleControlImpl<Csamplecontrol>,
public IOleObjectImpl<Csamplecontrol>,
public IOleInPlaceActiveObjectImpl<Csamplecontrol>,
public IViewObjectExImpl<Csamplecontrol>,
public IOleInPlaceObjectWindowlessImpl<Csamplecontrol>,
public ISupportErrorInfo,
public IPersistStorageImpl<Csamplecontrol>,
public ISpecifyPropertyPagesImpl<Csamplecontrol>,
public IQuickActivateImpl<Csamplecontrol>,
#ifndef _WIN32_WCE
public IDataObjectImpl<Csamplecontrol>,
#endif
public IProvideClassInfo2Impl<&CLSID_samplecontrol, NULL, &LIBID_ATLAXcontrolLib>,
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
public IObjectSafetyImpl<Csamplecontrol, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
#endif
public CComCoClass<Csamplecontrol, &CLSID_samplecontrol>,
public CComControl<Csamplecontrol>

{
public:

char* prova;

Csamplecontrol()
{
}

DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
OLEMISC_CANTLINKINSIDE |
OLEMISC_INSIDEOUT |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST
)

#ifndef _CE_DCOM
DECLARE_REGISTRY_RESOURCEID(IDR_SAMPLECONTROL)
#endif


BEGIN_COM_MAP(Csamplecontrol)
COM_INTERFACE_ENTRY(Isamplecontrol)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IViewObjectEx)
COM_INTERFACE_ENTRY(IViewObject2)
COM_INTERFACE_ENTRY(IViewObject)
COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceObject)
COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
COM_INTERFACE_ENTRY(IOleControl)
COM_INTERFACE_ENTRY(IOleObject)
COM_INTERFACE_ENTRY(IPersistStreamInit)
COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
COM_INTERFACE_ENTRY(IQuickActivate)
COM_INTERFACE_ENTRY(IPersistStorage)
#ifndef _WIN32_WCE
COM_INTERFACE_ENTRY(IDataObject)
#endif
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
#endif
END_COM_MAP()

BEGIN_PROP_MAP(Csamplecontrol)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
// Example entries
// PROP_ENTRY("Property Description", dispid, clsid)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()


BEGIN_MSG_MAP(Csamplecontrol)
CHAIN_MSG_MAP(CComControl<Csamplecontrol>)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
{
static const IID* arr[] =
{
&IID_Isamplecontrol,
};

for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i], riid))
return S_OK;
}
return S_FALSE;
}

// IViewObjectEx
DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// Isamplecontrol
public:
HRESULT OnDraw(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;
// Set Clip region to the rectangle specified by di.prcBounds
HRGN hRgnOld = NULL;

if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
hRgnOld = NULL;
bool bSelectOldRgn = false;

HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);

if (hRgnNew != NULL)
{
bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
}

Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
char* bufferID;

if (OpenComm()) // OpenComm is in Comm.cpp
printf("\n\n OpenComm OK da samplecontrol.h !");
else
printf("\n\n OpenComm FALLITA da samplecontrol.h !");


bufferID = DoASCIIReadWrite();
// this is in another cpp file and shoud return a char

CloseComm(); // it is in Comm.cpp
printf("\n\n LETTURA TAG OK! (s%)",bufferID); // here it doesn't display the bufferID, but only " (s) " Don't know why!
LPCTSTR pszText = _T("Ciao mondo"); // the first test :-)
#ifndef _WIN32_WCE
TextOut(di.hdcDraw,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
pszText,
lstrlen(pszText));
#else
ExtTextOut(di.hdcDraw,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
ETO_OPAQUE,
NULL,
pszText,
ATL::lstrlen(pszText),
NULL);
#endif

if (bSelectOldRgn)
SelectClipRgn(di.hdcDraw, hRgnOld);

prova = "Prova";

return S_OK;
}

char* provaChiamata()
{
return "Ciao";
}

DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()
{
return S_OK;
}

void FinalRelease()
{
}
};

OBJECT_ENTRY_AUTO(__uuidof(samplecontrol), Csamplecontrol)


So the question is : How can I made available the BufferID for the get method ( the one that we want to implement within the Add Property option ) I mean ... Do I have to create a globar variable BufferID where Can i do it in the samplecontrol.h

Many thanks again,

:-) Dvdkite





Re: Smart Devices VB and C# Projects How to receive a value (char) in an html page from an ActiveX ATL control (PPc2003)

DvdKite

Hi Christopher!!!

Finally I've made it with a friend!

I've used the "ADD PROPERTY" in "ISampleControl"

Now, in my test, I'm able to access to the property with the GET method, from the javascript in the html page. Now Iim able to get a BSTR.

The problem in that I receive from the RFID tag a CHAR*..

So now the FINAL QUESTION :-) is :

How can I convert a CAHR* to a BSTR

Thanks!!!!

Dvdkite





Re: Smart Devices VB and C# Projects How to receive a value (char) in an html page from an ActiveX ATL control (PPc2003)

Christopher Fairbairn

Hi Dvdkite,

This is great news, you must be very nearly getting to the completion of your project.

To convert from a CHAR* to a BSTR, you need to split the task down into two steps. Below is a small example of one approach you may like to utilise:

Code Block

char * pszMyRFIDTag = "0123456789ABCDEF";

// Step 1: char* to wchar*

WCHAR szBuffer[2048];

mbstowcs(szBuffer, pszMyRFIDTag, strlen(pszMyRFIDTag) + 1);

// Step 2: wchar* to BSTR

BSTR bstr = SysAllocString(szBuffer);

// As an example, display the bstr tot he user

MessageBox(GetForegroundWindow(), bstr, L"My BSTR Value", MB_OK);

The multibyte string to wide char string (mbstowcs) function converts between ANSI and UTF16. You can find documentation for this function on MSDN at http://msdn2.microsoft.com/en-us/library/k1f9b8cy(VS.80).aspx

To create a BSTR we can use the Win32 API called SysAllocString.

A BSTR is basically the combination of a C style string (i.e. NULL terminated) and PASCAL style string (i.e. a length field before the string data). The BSTR poiner returned by SysAllocString is offset into this datastructure just after the length field, so the strings are still compatible with APIs which expect WCHAR * arguments.

You can find documentation onf SysAllocString on MSDN at http://msdn2.microsoft.com/en-us/library/ms221458.aspx. Typically if you call SysAllocString, you would also need to call SysFreeString (http://msdn2.microsoft.com/en-us/library/ms221481.aspx) at some stage. In your scenario you should not need to do this, since it is the callers (i.e. the javascript interpreter's) responsibility to free the string returned by your COM object.

Hope this helps,

Christopher Fairbairn






Re: Smart Devices VB and C# Projects How to receive a value (char) in an html page from an ActiveX ATL control (PPc2003)

DvdKite

GREAT!!!!!!!!!!!!!!!!

Your 2 steps was perfect!

VS rebuillt the solution succesfully at the first try!!! :-)

Now for test I'm able to get the Id from the property directly from the javascript on the html page and I'm able to visualize it in a alert message...

About the next step:

This mean that now I can filter my patience list with the ID obtained from the RFID tag and have only the medical prescriptions of the person associated with that ID!

Now I'll work on it!!

Many thanks again and I'll have other questions I'll post it here!

Dvdkite