⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spydlg.cpp

📁 VC++串口通信设。本书详细说明讲解了在VC++环境下编写串口通信得过程。值得一看
💻 CPP
字号:
// Get needed include files
#include "Resource.h"
#include "Utility.h"
#include "TopUtil.h"
#include "SpyDlg.h"
#include "AttachDlg.h"
#include "PizzaNotify.h"


BEGIN_MESSAGE_MAP(CSpyDialog, CDialog)
   ON_BN_CLICKED(IDC_EXIT, OnExit)
   ON_NOTIFY    (NM_CLICK, IDC_PIZZA_LIST, OnListClick)
END_MESSAGE_MAP()


//
// Convenience structure
//
struct PizzaInfo
{
   PizzaSize  ePizzaSize;
   ULONG      ulNumToppings;
};


//
// CSpyDialog methods
//

// Constructor
CSpyDialog::CSpyDialog(CString& strHostname)

     : CDialog(IDD_MGRCLIENT_DIALOG),
       m_strHostname(strHostname),
       m_pIPizzaMaker(NULL),
       m_dwAdviseCookie(0)
{ }


void CSpyDialog::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
   DDX_Control(pDX, IDC_PIZZA_LIST,    m_PizzaList);
   DDX_Control(pDX, IDC_TOPPING_LIST,  m_ToppingList);
   DDX_Control(pDX, IDC_TXT_HOSTNAME,  m_Hostname);
}


BOOL CSpyDialog::OnInitDialog()
{
   CDialog::OnInitDialog();

   // Load the columns up into the Pizza list
   m_PizzaList.InsertColumn(1, "ID",         LVCFMT_LEFT, 35,  0);
   m_PizzaList.InsertColumn(2, "Cust. Name", LVCFMT_LEFT, 150, 1);
   m_PizzaList.InsertColumn(3, "Address",    LVCFMT_LEFT, 200, 2);
   m_PizzaList.InsertColumn(4, "Phone",      LVCFMT_LEFT, 100, 3);

   // Hook up with our server
   if (!AttachToHost())
      EndDialog(IDC_EXIT);

   return TRUE;
}


BOOL CSpyDialog::AttachToHost()
{
   HRESULT hResult;

   // Connect to the server
   m_pIPizzaMaker = ConnectToPizzaMaker(m_strHostname);
   if (!m_pIPizzaMaker)
      return FALSE;

   // Create the sink object
   TRACE("About to CreateInstance.\n");
   CComObject<ComPizzaNotifySink>* pMgrSink;
	CComObject<ComPizzaNotifySink>::CreateInstance(&pMgrSink);
   pMgrSink->SetSpyInstance(this);

   // Register ourself with the server
   TRACE("About to Advise.\n");
   hResult = AtlAdvise(m_pIPizzaMaker,
                       pMgrSink->GetUnknown(),
                       IID_IPizzaNotifySink,
                       &m_dwAdviseCookie);
   if (FAILED(hResult)) {
      ReportError("Could not connect sink.", hResult);
      m_pIPizzaMaker->Release();
      m_pIPizzaMaker = NULL;
      return FALSE;
   }

   // Set the hostname text
   if (m_strHostname == "")
      m_Hostname.SetWindowText("< Local machine >");
   else
      m_Hostname.SetWindowText(m_strHostname);

   return TRUE;
}


IPizzaMaker* CSpyDialog::ConnectToPizzaMaker(CString& strHostname)
{
   HRESULT        hResult;
   IPizzaLocator* pIPizzaLocator = NULL;
   IPizzaMaker*   pIPizzaMaker = NULL;
   BSTR           bstrHostname = NULL;
   ULONG          ulPizzaID = 0;
   VerboseMsg("In ConnectToPizzaMaker.\n");

   USES_CONVERSION;

   // Translate the hostname into Unicode
   if (strHostname != "")
      bstrHostname = strHostname.AllocSysString();

   // Hook ourselves up to a locator object
   COSERVERINFO  ServerInfo = { 0, bstrHostname, NULL, 0 };
   MULTI_QI      MultiQI    = { &IID_IPizzaLocator, NULL, NOERROR };

   hResult = CoCreateInstanceEx(CLSID_PizzaLocator1,
                                NULL, CLSCTX_SERVER,
                                &ServerInfo,
                                1, &MultiQI);
   if (FAILED(hResult)) {
      ReportError("Could not create a new PizzaLocator object.", hResult);
      SysFreeString(bstrHostname);
      return NULL;
   }

   // 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;

   // Were we able to find a running server, or do we have to start our own?
   if (!pIPizzaMaker) {

      // Create the remote PizzaMaker object
      ServerInfo.dwReserved1 = 0;
      ServerInfo.pwszName    = bstrHostname;
      ServerInfo.pAuthInfo   = NULL;
      ServerInfo.dwReserved2 = 0;

      MultiQI.pIID           = &IID_IPizzaMaker;
      MultiQI.pItf           = NULL;
      MultiQI.hr             = NOERROR;

      hResult = CoCreateInstanceEx(CLSID_PizzaMaker1,
                                   NULL, CLSCTX_SERVER,
                                   &ServerInfo,
                                   1, &MultiQI);
      if (FAILED(hResult)) {
         ReportError("Could not create a new COM PizzaMaker object.", hResult);
         SysFreeString(bstrHostname);
         return NULL;
      }

      // Set the interface pointer
      pIPizzaMaker = (IPizzaMaker*) MultiQI.pItf;
   }

   // Free up our hostname string
   SysFreeString(bstrHostname);

   return pIPizzaMaker;
}


HRESULT CSpyDialog::OnNewPizzaRequest(ULONG          ulPizzaID,
                                          PizzaSize      ePizzaSize,
                                          ULONG          ulNumToppings,
                                          ToppingInfo    ToppingInfoArray[],
                                          DeliveryInfo*  pDeliveryInfo)
{
   // Copy out the delivery info
   CString strCustName((LPCWSTR) pDeliveryInfo->bstrCustName);
   CString strAddress((LPCWSTR) pDeliveryInfo->bstrAddress);
   CString strPhone((LPCWSTR) pDeliveryInfo->bstrPhone);

   // Copy over our topping array -- We'll reserve the first part of the
   // array for the pizza size and number of toppings attributes
   BYTE* pByteBuffer = new BYTE[sizeof(PizzaInfo) + (ulNumToppings * sizeof(ToppingInfo))];

   // Blast in the pizza size and number of toppings 
   ((PizzaInfo*) pByteBuffer)->ePizzaSize = ePizzaSize;
   ((PizzaInfo*) pByteBuffer)->ulNumToppings = ulNumToppings;

   // And now copy over the topping array
   memcpy(pByteBuffer + sizeof(PizzaInfo), ToppingInfoArray, (ulNumToppings * sizeof(ToppingInfo)));

   // Insert the new row into the table
   ULONG ulThisItem = m_PizzaList.InsertItem(LVIF_TEXT | LVIF_PARAM, 0, ULongToStr(ulPizzaID), 0, 0, 0, (LONG) pByteBuffer);
   m_PizzaList.SetItem(ulThisItem, 1, LVIF_TEXT, strCustName, 0, 0, 0, 0);
   m_PizzaList.SetItem(ulThisItem, 2, LVIF_TEXT, strAddress, 0, 0, 0, 0);
   m_PizzaList.SetItem(ulThisItem, 3, LVIF_TEXT, strPhone, 0, 0, 0, 0);

   return NOERROR;
}


HRESULT CSpyDialog::OnPizzaComplete(ULONG  ulPizzaID)
{
   ULONG ulNumItems = m_PizzaList.GetItemCount();

   // Loop through all of our items, looking for the right one
   for (ULONG ulLoop = 0; ulLoop < ulNumItems; ulLoop++) {

      // Is this the item to remove?
      if (m_PizzaList.GetItemText(ulLoop, 0) == ULongToStr(ulPizzaID)) {

         // Looks like it 
         RemovePizzaEntry(ulLoop);
         return NOERROR;
      }
   }

   return S_FALSE;
}


void CSpyDialog::OnListClick()
{
   //
   // Thanks to Jeff Prosise for providing the hit testing
   // technique used by this method. This technique appears 
   // in Jeff's book "Programming Windows 95 with MFC,"
   // (Microsoft Press, 1996).
   //
   DWORD dwPos = ::GetMessagePos();
   CPoint point((int) LOWORD(dwPos), (int) HIWORD(dwPos));
   m_PizzaList.ScreenToClient(&point);

   LONG lSelectionIndex = m_PizzaList.HitTest(point);
   if (lSelectionIndex != -1) {

      // Retrieve the selected item
      LV_ITEM ItemInfo;
      ItemInfo.iItem = lSelectionIndex;
      ItemInfo.iSubItem = 0;
      ItemInfo.mask = LVIF_PARAM;
      m_PizzaList.GetItem(&ItemInfo);

      // Set the pizza size text
      PizzaInfo* pPizzaInfo = (PizzaInfo*) ItemInfo.lParam;
      CString strSizeText("Size: ");
      switch(pPizzaInfo->ePizzaSize)
      {
         case Individual: strSizeText += "Individual"; break;
         case Small:      strSizeText += "Small";      break;
         case Large:      strSizeText += "Large";      break;
      }
      CStatic* pSizeTextWnd = (CStatic*) GetDlgItem(IDC_TXT_PIZZASIZE);
      pSizeTextWnd->SetWindowText(strSizeText);

      // Clear out the listbox
      CListBox* pToppingListWnd = (CListBox*) GetDlgItem(IDC_TOPPING_LIST);
      pToppingListWnd->ResetContent();

      // Display the selected item's pizza toppings
      CString strTopping;
      for (ULONG ulLoop = 0; ulLoop < pPizzaInfo->ulNumToppings; ulLoop++) {
         ToppingInfo* pCurrTopping = (ToppingInfo*) ((PCHAR) pPizzaInfo + sizeof(PizzaInfo) + (ulLoop * sizeof(ToppingInfo)));
         strTopping = ToppingUtil::ToppingEnumToStr(pCurrTopping->eTopping);
         switch(pCurrTopping->eToppingSize)
         {
            case HalfPizza:    strTopping += "   (On Half)";     break;
            case QuarterPizza: strTopping += "   (On Quarter)";  break;
         }
         pToppingListWnd->InsertString(0, strTopping);
      }
   }
}


void CSpyDialog::OnExit()
{
   // Clear out any outstanding pizza entries
   ULONG ulNumItems = m_PizzaList.GetItemCount();
   for (ULONG ulLoop = 0; ulLoop < ulNumItems; ulLoop++)
      RemovePizzaEntry(0);

   // Unhook our notify sink
   if (m_dwAdviseCookie) {

      TRACE("About to Unadvise.\n");
		AtlUnadvise(m_pIPizzaMaker,
                  IID_IPizzaNotifySink,
                  m_dwAdviseCookie);
   }

   // Release our server pointer
   if (m_pIPizzaMaker) {
      m_pIPizzaMaker->Release();
      m_pIPizzaMaker = NULL;
   }

   // ... and we're out of here!
   EndDialog(IDC_EXIT);
}


void CSpyDialog::RemovePizzaEntry(ULONG ulItemIndex)
{
   // We need to get at the user-param so that we can free up
   // our topping info
   LV_ITEM ItemInfo;
   ItemInfo.iItem = ulItemIndex;
   ItemInfo.iSubItem = 0;
   ItemInfo.mask = LVIF_STATE | LVIF_PARAM;
   m_PizzaList.GetItem(&ItemInfo);
   delete [] (BYTE*) (ItemInfo.lParam);

   // And now remove the item
   m_PizzaList.DeleteItem(ulItemIndex);

   // If the completed pizza also happens to correspond to the
   // currently selected entry, clear out all of the displayed
   // pizza info.
   if (ItemInfo.state & LVIS_SELECTED || !m_PizzaList.GetItemCount()) {

      // First the size label
      CStatic* pSizeTextWnd = (CStatic*) GetDlgItem(IDC_TXT_PIZZASIZE);
      pSizeTextWnd->SetWindowText("Size: < None Selected >");

      // ... and then the listbox
      CListBox* pToppingListWnd = (CListBox*) GetDlgItem(IDC_TOPPING_LIST);
      pToppingListWnd->ResetContent();
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -