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 + -
显示快捷键?