pizzaorderimp.cpp
来自「VC++串口通信设。本书详细说明讲解了在VC++环境下编写串口通信得过程。值得一」· C++ 代码 · 共 409 行
CPP
409 行
// Get needed include files
#define INITGUID
#include "PizzaOrderImp.h"
#include "Utility.h"
//
// Useful constants
//
const ULONG g_ulMaxBufferLen = 256;
const std::string g_strPizzaMakerHostKey =
"Software\\Que\\PizzaOrderTaker Client\\1.0\\PizzaMaker Host";
// List of base pizza prices
ULONG g_aulPizzaPrices[] =
{
395, // Individual
595, // Small
795 // Large
};
// List of base topping prices
ULONG g_aulToppingPrices[] =
{
50, // Individual
100, // Small
150 // Large
};
// List of topping modifiers (topping prices are influenced by the size of
// the pizza, but some toppings -- like artichokes YECH! -- are twice as
// expensive)
ULONG g_aulToppingMods[] =
{
0, // Not a topping (here to catch errors)
1, // Pepperoni
1, // Sausage
1, // GroundBeef
1, // GreenOlives
1, // ProsciuttiniHam
1, // Pastrami
1, // GreenPeppers
1, // Mushrooms
1, // Onions
1, // Tomatoes
1, // Pesto
1, // JalapenoPeppers
1, // CheddarCheese
1, // FontinaCheese
1, // RicottaCheese
1, // FetaCheese
1, // Pineapple
1, // ExtraCheese
1, // Bacon
1, // Broccoli
1, // GenoaSalami
1, // Zucchini
1, // BlackOlives
1, // Anchovies
2, // ChickenBreast
2, // Shrimp
2 // ArtichokeHearts
};
//
// Constructor and destructor
//
ComPizzaOrderTaker::ComPizzaOrderTaker()
: m_eSize(Individual)
{
VerboseMsg("In PizzaOrderTaker constructor.\n");
}
ComPizzaOrderTaker::~ComPizzaOrderTaker()
{
VerboseMsg("In PizzaOrderTaker destructor.\n");
}
//
// IPizzaOrderTaker interface members
//
STDMETHODIMP
ComPizzaOrderTaker::ResetPizza()
{
VerboseMsg("In ResetPizza.\n");
// Clean out the topping list
m_ToppingList.clear();
// Reset the size to Individual
m_eSize = Individual;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::SetPizzaSize(PizzaSize eNewSize)
{
VerboseMsg("In SetPizzaSize.\n");
// Set the new size
m_eSize = eNewSize;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::GetPizzaSize(PizzaSize* peCurrSize)
{
VerboseMsg("In GetPizzaSize.\n");
// Get the current size
if (peCurrSize)
*peCurrSize = m_eSize;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::AddTopping(Topping eNewTopping,
ToppingSize eNewToppingSize)
{
VerboseMsg("In AddTopping.\n");
// Is this topping already in the list?
if (FindTopping(eNewTopping) != m_ToppingList.end())
return E_FAIL;
// Create a new Topping tuple
CToppingTuple* pTuple = new CToppingTuple;
pTuple->eTopping = eNewTopping;
pTuple->eToppingSize = eNewToppingSize;
// Add the topping to the list
m_ToppingList.push_back(pTuple);
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::RemoveTopping(Topping eRemTopping)
{
VerboseMsg("In RemoveTopping.\n");
// Find the topping tuple
TupleListIter iter = FindTopping(eRemTopping);
if (iter == m_ToppingList.end())
return NOERROR;
// Free the memory for the tuple and remove the list element
m_ToppingList.erase(iter);
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::GetNumToppings(ULONG* pulNumToppings)
{
VerboseMsg("In GetNumToppings.\n");
// Get the current number of toppings
if (pulNumToppings)
*pulNumToppings = m_ToppingList.size();
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::GetTopping(ULONG ulListPos,
Topping* peTopping,
ToppingSize* peToppingSize)
{
VerboseMsg("In GetTopping.\n");
//
// Retrieve the position's tuple
//
// GetTopping() provides position-oriented retrieval because it's easy
// to manipulate and understand. However, since the toppings are actually
// stored in a list, positioned access is slow. Definitely room for
// improvement here.
//
// Note that list positions use first element based access and not zero-based
// access (i.e., the first element is at position 1, not 0)
//
// Validate the list position
if (!ulListPos || ulListPos > m_ToppingList.size())
return E_FAIL;
// Iterate through the list, counting
TupleListIter iter = m_ToppingList.begin();
ULONG ulCurrentElem = 1UL;
do {
// Is this a match?
if (ulCurrentElem == ulListPos) {
*peTopping = (*iter)->eTopping;
*peToppingSize = (*iter)->eToppingSize;
return NOERROR;
}
ulCurrentElem++;
iter++;
} while (iter != m_ToppingList.end());
return E_FAIL;
}
STDMETHODIMP
ComPizzaOrderTaker::GetPizzaPrice(ULONG* pulPrice)
{
VerboseMsg("In GetPizzaPrice.\n");
// Start by setting the base price.
ULONG ulPizzaPrice = g_aulPizzaPrices[m_eSize];
// Now walk through the topping list, adding to the current price
for (TupleListIter iter = m_ToppingList.begin();
iter != m_ToppingList.end();
iter++)
{
// Calculate the topping price
ULONG ulToppingPrice = g_aulToppingPrices[m_eSize] *
g_aulToppingMods[(*iter)->eTopping];
// Based on how much of the pizza is covered with this topping, the
// topping price needs to be scaled
switch ((*iter)->eToppingSize)
{
case FullPizza: break; // Do nothing
case HalfPizza: ulToppingPrice /= 2; break;
case QuarterPizza: ulToppingPrice /= 4; break;
}
// Add the topping priuce to the total
ulPizzaPrice += ulToppingPrice;
}
// And now return the result
*pulPrice = ulPizzaPrice;
return NOERROR;
}
STDMETHODIMP
ComPizzaOrderTaker::OrderPizza(DeliveryInfo* pDeliveryInfo,
CreditCard , // eCreditCardType,
BSTR , // bstrCreditCardNum,
ULONG* pulPrice)
{
HRESULT hResult;
IPizzaLocator* pIPizzaLocator = NULL;
IPizzaMaker* pIPizzaMaker = NULL;
LPOLESTR pszHostname = NULL;
ULONG ulPizzaID = 0;
VerboseMsg("In OrderPizza.\n");
USES_CONVERSION;
// Set the price
GetPizzaPrice(pulPrice);
//
// In a real system, at this point we'd probably go out to another
// server and debit the customer's credit card first. In other words,
// ordering a pizza involves at least two steps: billing the customer
// and then making the pizza. Only the latter part is implemented in
// this example.
//
// What host are we supposed to be looking for our PizzaMaker on?
pszHostname = LoadPizzaMakerHostnameFromRegistry();
// Hook ourselves up to a locator object
COSERVERINFO ServerInfo = { 0, pszHostname, NULL, 0 };
MULTI_QI MultiQI = { &IID_IPizzaLocator, NULL, NOERROR };
hResult = CoCreateInstanceEx(CLSID_PizzaLocator1,
NULL, CLSCTX_SERVER,
&ServerInfo,
1, &MultiQI);
if (FAILED(hResult)) {
// We'll let the client report the error
// ReportError("Could not create a new PizzaLocator object.", hResult);
return hResult;
}
// Free up our hostname string
CoTaskMemFree(pszHostname);
// Just for convenience
pIPizzaLocator = (IPizzaLocator*) MultiQI.pItf;
// Look for any PizzaMaker objects that might be currently running
// on the same machine as the locator
hResult = pIPizzaLocator->Locate(A2OLE("PizzaMaker"),
IID_IPizzaMaker,
(PPVOID) &pIPizzaMaker);
// Clean up some interface pointers...
pIPizzaLocator->Release();
pIPizzaLocator = NULL;
if (FAILED(hResult)) {
// We'll let the client report the error
// ReportError("Could not find a running PizzaMaker object.", hResult);
return hResult;
}
// Create our array of ToppingInfo structures
ULONG ulNumToppings = m_ToppingList.size();
ToppingInfo* pToppingInfo = new ToppingInfo[ulNumToppings];
// ... and fill it in
ULONG ulToppingIndex = 0;
for (TupleListIter iter = m_ToppingList.begin();
iter != m_ToppingList.end();
iter++, ulToppingIndex++)
{
// Copy over the current topping
pToppingInfo[ulToppingIndex].eTopping = (*iter)->eTopping;
pToppingInfo[ulToppingIndex].eToppingSize = (*iter)->eToppingSize;
}
// Tell our cooks to fire up the ovens!
hResult = pIPizzaMaker->MakePizza(m_eSize,
ulNumToppings,
pToppingInfo,
pDeliveryInfo,
&ulPizzaID);
if (FAILED(hResult)) {
// We'll let the client report the error
// ReportError("Error returned from MakePizza() method.", hResult);
pIPizzaMaker->Release();
return hResult;
}
// Free up our topping array
delete [] pToppingInfo;
// Release our interface pointer
pIPizzaMaker->Release();
return NOERROR;
}
ComPizzaOrderTaker::TupleListIter
ComPizzaOrderTaker::FindTopping(Topping eSearchTopping)
{
for (TupleListIter iter = m_ToppingList.begin();
iter != m_ToppingList.end();
iter++)
if ((*iter)->eTopping == eSearchTopping)
return iter;
return iter;
}
LPOLESTR ComPizzaOrderTaker::LoadPizzaMakerHostnameFromRegistry()
{
// Initialize data
HRESULT hResult;
HKEY hKey = 0;
// Open the base application registry key
hResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
g_strPizzaMakerHostKey.c_str(),
0,
KEY_QUERY_VALUE ,
&hKey);
if (hResult)
return NULL;
// Now retrieve the hostname
BYTE achHostname[g_ulMaxBufferLen];
ULONG ulHostnameLen = g_ulMaxBufferLen;
ULONG ulValueType;
hResult = RegQueryValueEx(hKey,
"", // The "Default" value
NULL,
&ulValueType,
achHostname,
&ulHostnameLen);
if (hResult || ulValueType != REG_SZ) {
RegCloseKey(hKey);
return NULL;
}
// Close the subkey
RegCloseKey(hKey);
// Translate the hostname into a Unicode string (caller must free the
// string by calling CoTaskMemFree()
LPOLESTR pszHostname;
AnsiToUnicode((PCHAR) achHostname, &pszHostname);
return pszHostname;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?