📄 spydlg.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 + -