Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
180
Добавлен:
24.05.2014
Размер:
26 Мб
Скачать
☆

620 Project 5 CREATING A COM COMPONENT USING ATL

FIGURE 19-12

 

Y

L

F

A

 

E

 

T

 

The Add Method WizardM

 

FIGURE 19-13 The Add Reference dialog box

6. Click on Finish to create the method.

Open CardCheck.h from the Solution Explorer window. You will find the following code:

Team-Fly®

IMPLEMENTING COM USING ATL

Chapter 19

621

 

 

 

 

__interface ICardCheck : IDispatch

{

[propget, id(1), helpstring(“property CardType”)] HRESULT CardType([out, retval] BSTR* pVal);

[propput, id(1), helpstring(“property CardType”)] HRESULT CardType([in] BSTR newVal);

[id(2), helpstring(“method Validate”)] HRESULT Validate([in] BSTR bstrCardNo, [out,retval]

VARIANT* vRetVal);

};

As you see, a pair of Put and Get methods have been added to the class for the CardType property. These methods are used to set the value of the CardType property and retrieve the stored value, respectively. The validate method declaration, which accepts one input type parameter and one return type parameter, is added. This is the method wherein you will code for the Luhn algorithm.

For storing the state data of the property CardType, you will need to add a variable to the class. State data is the data relevant to a particular instance of a component. To add a private variable bstrCardType in the header file, use the following code:

class ATL_NO_VTABLE CCardCheck : public ICardCheck

{

private:

BSTR bstrCardType;

public:

CCardCheck()

{

}

………

……….

};

Use the following code to implement the property’s Get and Put methods:

STDMETHODIMP CCardCheck::get_CardType(BSTR* pVal)

{

// TODO: Add your implementation code here

622 Project 5 CREATING A COM COMPONENT USING ATL

*pVal=SysAllocString(bstrCardType); return S_OK;

}

STDMETHODIMP CCardCheck::put_CardType(BSTR newVal)

{

// TODO: Add your implementation code here bstrCardType=SysAllocString(newVal); return S_OK;

}

Next, you will add code to implement the Luhn algorithm in the validate function (the skeleton for the function has been added by the wizard):

1.First, you need to convert the BSTR value to char *. This is done by allocating the required bytes of memory to the char * type variable, and then copying the BSTR value into the newly created variable using the

WideCharToMultiByte method.

NOTE

Wide characters are used to store Unicode characters. In the following code, the wcslen method is a wide character version of the old strlen function:

int len = wcslen(bstrCardNo);

char * pszNumber = new char[len+1];

int last =

WideCharToMultiByte(CP_ACP,0,bstrCardNo,len,pszNumber,len,0,0);

pszNumber[last] = 0;

In the preceding code, the first parameter to the WideChartoMultiByte function, CP_ACP, specifies that the ANSI character set is to be used. The second parameter is a flag, which specifies how the function should handle characters that have no equivalent in the target character set. 0 here means that the default character will be used. The third parameter, bstrCardNo, is the source string, and the fourth parameter, len, is

IMPLEMENTING COM USING ATL

Chapter 19

623

 

 

 

 

the length of the string. The target string and its size are the fifth and sixth parameters, pszNumber and len, respectively.

2.Similarly, convert the card type into char * from BSTR.

3.After converting the strings, you can check if the card type is a Visa card. If it is, then check whether the number of digits is 13 or 16. If it is either, then check if the starting digit is 4. Similar checks are done to Master Card and Amex cards. If all the prior conditions are met, then check to see if it is a Luhn number:

for(i = 0, nSum = 0; i < 16; i += 2)

//for each alternative numbers starting from left

{

//Convert from char to integer by subtracting the ASCII for 0 //and double the number

int nDigit = (pszNumber[i] - 48) * 2;

//If the number has a single digit

if(nDigit < 10) {nSum=nSum + nDigit;

}

//If the number has two digits extract each of the digits and add them else

{

nSum =nSum + nDigit/10; nSum = nSum + nDigit%10;

}

//Now add the unchanged numbers nSum=nSum + (pszNumber[i+1]-48);

}

//return the results nSum=nSum%10;

CComVariant p(nSum); *bRetVal=(VARIANT)p;

624 Project 5 CREATING A COM COMPONENT USING ATL

Check if the sum is divisible by 10. If the remainder is 0, then the number is a Luhn number; otherwise it is not. In the preceding code the remainder will be returned. If it is 0, it is a valid credit card number.

Here is the complete method:

STDMETHODIMP CCardCheck::Validate(BSTR bstrCardNo, VARIANT* vRetVal)

{

// TODO: Add your implementation code here int i;

int nSum;

//Convert the card number from BSTR to char * int len = wcslen(bstrCardNo);

char * pszCardNo = new char[len+1]; int last =

WideCharToMultiByte(CP_ACP,0,bstrCardNo,len,pszCardNo,len,0,0);

pszCardNo[last] = 0;

//Convert the card type from BSTR to char * len = wcslen(bstrCardType);

char *pszCardType=new char[len+1]; last =

WideCharToMultiByte(CP_ACP,0,bstrCardType,len,pszCardType,len,0,0);

pszCardType[last] = 0;

CString s(pszCardType);

//Check if one of the accepted card types if(s.CompareNoCase(“VISA”)!=0 && s.CompareNoCase(“MASTER”)!=0 && s.CompareNoCase(“AMEX”)!=0)

{

CComVariant n(1); *vRetVal=(VARIANT)n;

return S_OK;

}

//Check if the card number Is valid for Visa if(s.CompareNoCase(“VISA”)==0)

{

if(strlen(pszCardNo)!=13 && strlen(pszCardNo)!=16)

IMPLEMENTING COM USING ATL

Chapter 19

625

 

 

 

 

{

CComVariant n(1);

*vRetVal=(VARIANT)n;

return S_OK;

}

if(pszCardNo[0]!=’4’)

{

CComVariant n(1); *vRetVal=(VARIANT)n; return S_OK;

}

}

//Check if the card number is valid for Master if(s.CompareNoCase(“MASTER”)==0)

{

if(strlen(pszCardNo)!=16)

{

CComVariant n(1);

*vRetVal=(VARIANT)n;

return S_OK;

}

if(pszCardNo[0] != ‘5’)

{

CComVariant n(1); *vRetVal=(VARIANT)n; return S_OK;

}

if(pszCardNo< ‘1’ || pszCardNo> ‘6’)

{

CComVariant n(1); *vRetVal=(VARIANT)n; return S_OK;

}

}

//Check if the number is valid for Amex

626 Project 5 CREATING A COM COMPONENT USING ATL

if(s.CompareNoCase(“AMEX”)==0)

{

if(strlen(pszCardNo)!=15)

{

CComVariant n(1);

*vRetVal=(VARIANT)n;

return S_OK;

}

if(pszCardNo[0]!=’3’)

{

CComVariant n(1);

*vRetVal=(VARIANT)n;

return S_OK;

}

if(pszCardNo!=’4’ && pszCardNo!= ‘7’)

{

CComVariant n(1); *vRetVal=(VARIANT)n; return S_OK;

}

}

//Check if the card number is a valid Luhn number for(i = 0, nSum = 0; i < 16; i += 2)

{

int nDigit = (pszCardNo[i] - 48) * 2; if(nDigit < 10)

{

nSum=nSum + nDigit;

}

else

{

nSum =nSum + nDigit/10; nSum = nSum + nDigit%10;

}

nSum=nSum + (pszCardNo[i+1]-48);

}

nSum=nSum%10;

IMPLEMENTING COM USING ATL

Chapter 19

627

 

 

 

 

CComVariant p(nSum);

*vRetVal=(VARIANT)p;

return S_OK;

}

Testing the Component

In this section, you will test this component using a Visual Basic .NET application. This exercise also demonstrates how once a COM component has been created, what language it has been created in becomes irrelevant.

1.Close the current project and create a new Visual Basic project.

2.Select the Windows Application project type.

3.Add a button control to the default form. From the Project menu, select Add Reference to open the Add Reference dialog box, shown in Figure 19-14. Select the COM tab and double-click on LuhnChecker 1.0 Type Library.

FIGURE 19-14 Internet Services Manager

628 Project 5 CREATING A COM COMPONENT USING ATL

4. Add the following code to the Click event of the button on the form:

private Sub Button1_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs)

Handles Button1.Click

 

 

Dim card As New LuhnChecker.CCardCheck()

 

 

Dim n As Integer

 

 

card.CardType = “Visa”

 

 

n = card.Validate(“4477460020208002”)

‘ the number to

check

 

 

 

If (n = 0) Then

 

 

MsgBox(“Valid Number”)

 

 

Else

 

MsgBox(“Invalid Number”)

End If

End Sub

Next, you will test the component by hosting it on an ASP page. To accomplish this, you will require two files. The first is an HTML file with a form on which the credit card number can be entered and the card type can be selected. Name the file default.htm.

The following is the HTML code for it:

<html>

<head>

<title>Art Shop Checkout</title>

<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1”> </head>

<body bgcolor=”#FFFFFF” text=”#000000”>

<form name=”Checkout” method=”post” action=”checkCard.asp”> <p>Please Enter your Credit Card details</p>

<p>Number:

<input type=”text” name=”cardno”>

</p>

<p>Card Type:

<select name=”cardtype”> <option>VISA</option>

IMPLEMENTING COM USING ATL

Chapter 19

629

 

 

 

 

<option>MASTER</option>

<option>AMEX</option>

</select>

</p>

<p>Your Date of Birth(mm/dd/yyyy): <input type=”text” name=”dob”>

</p>

<p>

<input type=”submit” name=”Submit” value=”Submit”>

</p>

</p>

</form>

</body>

</html>

Data entered through this page will be received by an ASP page, which creates an instance of your component and validates the credit card number entered. Create a file named cardCheck.asp and enter the following code:

<html>

<body>

<%

Dim card dim n

Set card = Server.CreateObject(“LuhnChecker.CardCheck”) card.cardType=request.form(“cardtype”) n=card.Validate(request.form(“cardno”))

if n <> 0 then

response.write “Invalid card number. Please recheck” else

response.write “Thank you for shopping at the Art Shop” end if

%>

</body>

</html>