|
|
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993
/***
*dspcalc2.cpp
*
* Copyright (C) 1993, Microsoft Corporation. All Rights Reserved.
* Information Contained Herein Is Proprietary and Confidential.
*
*Purpose:
* This module implements the basic user interface and arithmetic
* functionality of the IDispatch calculator.
*
* The implementation of IDispatch is via aggregation with an
* instance of the "standard" IDispatch implementation, which is
* initialized with a TypeInfo loaded from the TypeLib that was
* constructed from the ODL description of the calculator.
*
*Implementation Notes:
*
*****************************************************************************/
#include <windows.h>
#include <ole2.h>
#if !defined(WIN32)
#include <olenls.h>
#endif
#include <dispatch.h>
#include "resource.h"
#include "dspcalc2.h"
/***
*CCalc *CCalc::Create(void)
*Purpose:
* Create an instance of the IDispatch calculator, load the
* TypeInfo that describes the exposed functionality and
* aggregate with an instance of CStdDispatch that has been
* initialized with this TypeInfo.
*
*Entry:
* None
*
*Exit:
* return value = CCalc*, NULL if the creation failed.
*
***********************************************************************/
CCalc FAR*
CCalc::Create()
{
HRESULT hresult;
CCalc FAR* pcalc;
ITypeLib FAR* ptlib;
ITypeInfo FAR* ptinfo;
IUnknown FAR* punkStdDisp;
ptlib = NULL;
ptinfo = NULL;
if((pcalc = new FAR CCalc()) == NULL)
return NULL;
if((hresult = LoadTypeLib("dspcalc2.tlb", &ptlib)) != NOERROR){
MessageBox(NULL, "error loading TypeLib", "dspcalc2", MB_OK);
goto LError0;
}
if((hresult = ptlib->GetTypeInfoOfGuid(CLSID_CCalc2, &ptinfo)) != NOERROR){
MessageBox(NULL, "error accessing TypeInfo", "dspcalc2", MB_OK);
goto LError0;
}
// Create and aggregate with an instance of the default
// implementation of IDispatch that is initialized with our
// TypeInfo.
//
hresult = CreateStdDispatch(
pcalc, // controlling unknown
&pcalc->m_arith, // vtable* to dispatch on
ptinfo,
&punkStdDisp);
if(hresult != NOERROR)
goto LError0;
pcalc->m_punkStdDisp = punkStdDisp;
ptinfo->Release();
ptlib->Release();
return pcalc;
LError0:;
pcalc->Release();
if(ptinfo != NULL)
ptinfo->Release();
if(ptlib != NULL)
ptlib->Release();
return NULL;
}
//---------------------------------------------------------------------
// IUnknown methods
//---------------------------------------------------------------------
STDMETHODIMP
CCalc::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
if(riid == IID_IUnknown){
*ppv = this;
}else
if(riid == IID_IDispatch){
return m_punkStdDisp->QueryInterface(riid, ppv);
}else
if(riid == IID_ICalculator){
*ppv = &m_arith;
}else
return ResultFromScode(E_NOINTERFACE);
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG)
CCalc::AddRef()
{
return ++m_refs;
}
STDMETHODIMP_(ULONG)
CCalc::Release()
{
if(--m_refs == 0){
if(m_punkStdDisp != NULL)
m_punkStdDisp->Release();
PostQuitMessage(0);
delete this;
return 0;
}
return m_refs;
}
STDMETHODIMP
CCalc::CArith::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
return m_pcalc->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)
CCalc::CArith::AddRef()
{
return m_pcalc->AddRef();
}
STDMETHODIMP_(ULONG)
CCalc::CArith::Release()
{
return m_pcalc->Release();
}
//---------------------------------------------------------------------
// Arithmetic features
//---------------------------------------------------------------------
STDMETHODIMP_(void)
CCalc::CArith::Clear()
{
m_opnd = 0;
m_accum = 0;
m_op = OP_NONE;
m_state = STATE_LOPND;
}
STDMETHODIMP_(void)
CCalc::CArith::put_Accum(long l)
{
m_accum = l;
}
STDMETHODIMP_(long)
CCalc::CArith::get_Accum()
{
return m_accum;
}
STDMETHODIMP_(void)
CCalc::CArith::put_Opnd(long l)
{
m_opnd = l;
}
STDMETHODIMP_(long)
CCalc::CArith::get_Opnd()
{
return m_opnd;
}
STDMETHODIMP_(void)
CCalc::CArith::put_Op(short op)
{
m_op = op;
}
STDMETHODIMP_(short)
CCalc::CArith::get_Op()
{
return m_op;
}
STDMETHODIMP_(BOOL)
CCalc::CArith::Eval()
{
if(m_op == OP_NONE)
return FALSE;
switch(m_op){
case OP_PLUS:
m_accum += m_opnd;
break;
case OP_MINUS:
m_accum -= m_opnd;
break;
case OP_MULT:
m_accum *= m_opnd;
break;
case OP_DIV:
m_accum = (m_opnd == 0) ? 0 : (m_accum / m_opnd);
break;
default:
// ASSERT(UNREACHED);
return FALSE;
}
m_state = STATE_EVAL;
return TRUE;
}
//---------------------------------------------------------------------
// User Interface features
//---------------------------------------------------------------------
/***
*void CCalc::CArith::Display()
*Purpose:
* Display the contents of the register currently being edited.
*
*Entry:
* None
*
*Exit:
* None
*
***********************************************************************/
STDMETHODIMP_(void)
CCalc::CArith::Display()
{
VARIANT var;
V_VT(&var) = VT_I4;
V_I4(&var) = (m_state == STATE_ROPND) ? m_opnd : m_accum;
VariantChangeType(&var, &var, 0, VT_BSTR);
SetDlgItemText(m_pcalc->m_hwnd, IDC_DISPLAY, V_BSTR(&var));
VariantClear(&var);
}
STDMETHODIMP_(BOOL)
CCalc::CArith::Button(BSTR bstrButton)
{
int i, button;
static struct {
char ch;
int idc;
} NEAR rgIdcOfCh[] = {
{ '+', IDC_PLUS }
, { '-', IDC_MINUS }
, { '*', IDC_MULT }
, { '/', IDC_DIV }
, { 'C', IDC_CLEAR }
, { 'c', IDC_CLEAR }
, { '=', IDC_EQUALS }
, { '0', IDC_ZERO }
, { '1', IDC_ONE }
, { '2', IDC_TWO }
, { '3', IDC_THREE }
, { '4', IDC_FOUR }
, { '5', IDC_FIVE }
, { '6', IDC_SIX }
, { '7', IDC_SEVEN }
, { '8', IDC_EIGHT }
, { '9', IDC_NINE }
, { -1 , -1 }
};
// if the string is more that 1 character long, then we know its wrong.
if(SysStringLen(bstrButton) > 1)
return FALSE;
// translate button string into control ID
for(i = 0;; ++i){
if(rgIdcOfCh[i].ch == -1)
return FALSE;
if(rgIdcOfCh[i].ch == bstrButton[0]){
button = rgIdcOfCh[i].idc;
break;
}
}
return ButtonPush(button);
}
// the following method is internal, and not exposed for programmability
BOOL
CCalc::CArith::ButtonPush(int button)
{
if(button >= IDC_ZERO && button <= IDC_NINE){
long lVal = button - IDC_ZERO;
switch(m_state){
case STATE_EVAL:
m_accum = lVal;
m_state = STATE_LOPND;
break;
case STATE_OP:
m_opnd = lVal;
m_state = STATE_ROPND;
break;
case STATE_LOPND:
m_accum = (m_accum * 10) + lVal;
break;
case STATE_ROPND:
m_opnd = (m_opnd * 10) + lVal;
break;
}
}else if(button >= IDC_PLUS && button <= IDC_DIV){
if(m_state == STATE_LOPND){
m_opnd = m_accum;
m_state = STATE_OP;
m_op = button - IDC_PLUS + OP_PLUS;
}
}else if(button == IDC_EQUALS){
if(m_state > STATE_LOPND)
Eval();
}else if (button == IDC_CLEAR){
Clear();
}
SendMessage(m_pcalc->m_hwnd, BM_SETSTATE, 1, 0L);
SendMessage(m_pcalc->m_hwnd, BM_SETSTATE, 0, 0L);
Display();
return TRUE;
}
/***
*void CCalc::CArith::Quit()
*Purpose:
*
*Entry:
* None
*
*Exit:
* None
*
***********************************************************************/
STDMETHODIMP_(void)
CCalc::CArith::Quit()
{
PostQuitMessage(0);
}
//---------------------------------------------------------------------
// The CCalc Class Factory
//---------------------------------------------------------------------
IClassFactory FAR*
CCalcCF::Create()
{
return new FAR CCalcCF();
}
STDMETHODIMP
CCalcCF::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
if(riid == IID_IUnknown || riid == IID_IClassFactory){
AddRef();
*ppv = this;
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG)
CCalcCF::AddRef()
{
return ++m_refs;
}
STDMETHODIMP_(ULONG)
CCalcCF::Release()
{
if(--m_refs == 0){
delete this;
return 0;
}
return m_refs;
}
STDMETHODIMP
CCalcCF::CreateInstance(
IUnknown FAR* punkOuter,
REFIID riid,
void FAR* FAR* ppv)
{
extern CCalc FAR* g_pcalc;
return g_pcalc->QueryInterface(riid, ppv);
}
STDMETHODIMP
CCalcCF::LockServer(BOOL fLock)
{
return NOERROR;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.