|
|
1.1 ! root 1: /*** ! 2: *dspcalc2.cpp ! 3: * ! 4: * Copyright (C) 1993, Microsoft Corporation. All Rights Reserved. ! 5: * Information Contained Herein Is Proprietary and Confidential. ! 6: * ! 7: *Purpose: ! 8: * This module implements the basic user interface and arithmetic ! 9: * functionality of the IDispatch calculator. ! 10: * ! 11: * The implementation of IDispatch is via aggregation with an ! 12: * instance of the "standard" IDispatch implementation, which is ! 13: * initialized with a TypeInfo loaded from the TypeLib that was ! 14: * constructed from the ODL description of the calculator. ! 15: * ! 16: *Implementation Notes: ! 17: * ! 18: *****************************************************************************/ ! 19: ! 20: #include <windows.h> ! 21: #include <ole2.h> ! 22: #if !defined(WIN32) ! 23: #include <olenls.h> ! 24: #endif ! 25: #include <dispatch.h> ! 26: ! 27: #include "resource.h" ! 28: #include "dspcalc2.h" ! 29: ! 30: ! 31: /*** ! 32: *CCalc *CCalc::Create(void) ! 33: *Purpose: ! 34: * Create an instance of the IDispatch calculator, load the ! 35: * TypeInfo that describes the exposed functionality and ! 36: * aggregate with an instance of CStdDispatch that has been ! 37: * initialized with this TypeInfo. ! 38: * ! 39: *Entry: ! 40: * None ! 41: * ! 42: *Exit: ! 43: * return value = CCalc*, NULL if the creation failed. ! 44: * ! 45: ***********************************************************************/ ! 46: CCalc FAR* ! 47: CCalc::Create() ! 48: { ! 49: HRESULT hresult; ! 50: CCalc FAR* pcalc; ! 51: ITypeLib FAR* ptlib; ! 52: ITypeInfo FAR* ptinfo; ! 53: IUnknown FAR* punkStdDisp; ! 54: ! 55: ptlib = NULL; ! 56: ptinfo = NULL; ! 57: ! 58: if((pcalc = new FAR CCalc()) == NULL) ! 59: return NULL; ! 60: ! 61: if((hresult = LoadTypeLib("dspcalc2.tlb", &ptlib)) != NOERROR){ ! 62: MessageBox(NULL, "error loading TypeLib", "dspcalc2", MB_OK); ! 63: goto LError0; ! 64: } ! 65: ! 66: if((hresult = ptlib->GetTypeInfoOfGuid(CLSID_CCalc2, &ptinfo)) != NOERROR){ ! 67: MessageBox(NULL, "error accessing TypeInfo", "dspcalc2", MB_OK); ! 68: goto LError0; ! 69: } ! 70: ! 71: // Create and aggregate with an instance of the default ! 72: // implementation of IDispatch that is initialized with our ! 73: // TypeInfo. ! 74: // ! 75: hresult = CreateStdDispatch( ! 76: pcalc, // controlling unknown ! 77: &pcalc->m_arith, // vtable* to dispatch on ! 78: ptinfo, ! 79: &punkStdDisp); ! 80: ! 81: ! 82: if(hresult != NOERROR) ! 83: goto LError0; ! 84: ! 85: pcalc->m_punkStdDisp = punkStdDisp; ! 86: ! 87: ptinfo->Release(); ! 88: ptlib->Release(); ! 89: ! 90: return pcalc; ! 91: ! 92: LError0:; ! 93: pcalc->Release(); ! 94: if(ptinfo != NULL) ! 95: ptinfo->Release(); ! 96: if(ptlib != NULL) ! 97: ptlib->Release(); ! 98: return NULL; ! 99: } ! 100: ! 101: ! 102: //--------------------------------------------------------------------- ! 103: // IUnknown methods ! 104: //--------------------------------------------------------------------- ! 105: ! 106: ! 107: STDMETHODIMP ! 108: CCalc::QueryInterface(REFIID riid, void FAR* FAR* ppv) ! 109: { ! 110: if(riid == IID_IUnknown){ ! 111: *ppv = this; ! 112: }else ! 113: if(riid == IID_IDispatch){ ! 114: return m_punkStdDisp->QueryInterface(riid, ppv); ! 115: }else ! 116: if(riid == IID_ICalculator){ ! 117: *ppv = &m_arith; ! 118: }else ! 119: return ResultFromScode(E_NOINTERFACE); ! 120: ! 121: AddRef(); ! 122: return NOERROR; ! 123: } ! 124: ! 125: ! 126: STDMETHODIMP_(ULONG) ! 127: CCalc::AddRef() ! 128: { ! 129: return ++m_refs; ! 130: } ! 131: ! 132: ! 133: STDMETHODIMP_(ULONG) ! 134: CCalc::Release() ! 135: { ! 136: if(--m_refs == 0){ ! 137: if(m_punkStdDisp != NULL) ! 138: m_punkStdDisp->Release(); ! 139: PostQuitMessage(0); ! 140: delete this; ! 141: return 0; ! 142: } ! 143: return m_refs; ! 144: } ! 145: ! 146: ! 147: STDMETHODIMP ! 148: CCalc::CArith::QueryInterface(REFIID riid, void FAR* FAR* ppv) ! 149: { ! 150: return m_pcalc->QueryInterface(riid, ppv); ! 151: } ! 152: ! 153: ! 154: STDMETHODIMP_(ULONG) ! 155: CCalc::CArith::AddRef() ! 156: { ! 157: return m_pcalc->AddRef(); ! 158: } ! 159: ! 160: ! 161: STDMETHODIMP_(ULONG) ! 162: CCalc::CArith::Release() ! 163: { ! 164: return m_pcalc->Release(); ! 165: } ! 166: ! 167: ! 168: //--------------------------------------------------------------------- ! 169: // Arithmetic features ! 170: //--------------------------------------------------------------------- ! 171: ! 172: ! 173: STDMETHODIMP_(void) ! 174: CCalc::CArith::Clear() ! 175: { ! 176: m_opnd = 0; ! 177: m_accum = 0; ! 178: m_op = OP_NONE; ! 179: m_state = STATE_LOPND; ! 180: } ! 181: ! 182: STDMETHODIMP_(void) ! 183: CCalc::CArith::put_Accum(long l) ! 184: { ! 185: m_accum = l; ! 186: } ! 187: ! 188: ! 189: STDMETHODIMP_(long) ! 190: CCalc::CArith::get_Accum() ! 191: { ! 192: return m_accum; ! 193: } ! 194: ! 195: ! 196: STDMETHODIMP_(void) ! 197: CCalc::CArith::put_Opnd(long l) ! 198: { ! 199: m_opnd = l; ! 200: } ! 201: ! 202: ! 203: STDMETHODIMP_(long) ! 204: CCalc::CArith::get_Opnd() ! 205: { ! 206: return m_opnd; ! 207: } ! 208: ! 209: ! 210: STDMETHODIMP_(void) ! 211: CCalc::CArith::put_Op(short op) ! 212: { ! 213: m_op = op; ! 214: } ! 215: ! 216: ! 217: STDMETHODIMP_(short) ! 218: CCalc::CArith::get_Op() ! 219: { ! 220: return m_op; ! 221: } ! 222: ! 223: ! 224: STDMETHODIMP_(BOOL) ! 225: CCalc::CArith::Eval() ! 226: { ! 227: if(m_op == OP_NONE) ! 228: return FALSE; ! 229: ! 230: switch(m_op){ ! 231: case OP_PLUS: ! 232: m_accum += m_opnd; ! 233: break; ! 234: case OP_MINUS: ! 235: m_accum -= m_opnd; ! 236: break; ! 237: case OP_MULT: ! 238: m_accum *= m_opnd; ! 239: break; ! 240: case OP_DIV: ! 241: m_accum = (m_opnd == 0) ? 0 : (m_accum / m_opnd); ! 242: break; ! 243: default: ! 244: // ASSERT(UNREACHED); ! 245: return FALSE; ! 246: ! 247: } ! 248: ! 249: m_state = STATE_EVAL; ! 250: ! 251: return TRUE; ! 252: } ! 253: ! 254: ! 255: //--------------------------------------------------------------------- ! 256: // User Interface features ! 257: //--------------------------------------------------------------------- ! 258: ! 259: ! 260: /*** ! 261: *void CCalc::CArith::Display() ! 262: *Purpose: ! 263: * Display the contents of the register currently being edited. ! 264: * ! 265: *Entry: ! 266: * None ! 267: * ! 268: *Exit: ! 269: * None ! 270: * ! 271: ***********************************************************************/ ! 272: STDMETHODIMP_(void) ! 273: CCalc::CArith::Display() ! 274: { ! 275: VARIANT var; ! 276: ! 277: V_VT(&var) = VT_I4; ! 278: V_I4(&var) = (m_state == STATE_ROPND) ? m_opnd : m_accum; ! 279: VariantChangeType(&var, &var, 0, VT_BSTR); ! 280: SetDlgItemText(m_pcalc->m_hwnd, IDC_DISPLAY, V_BSTR(&var)); ! 281: VariantClear(&var); ! 282: } ! 283: ! 284: ! 285: STDMETHODIMP_(BOOL) ! 286: CCalc::CArith::Button(BSTR bstrButton) ! 287: { ! 288: int i, button; ! 289: ! 290: static struct { ! 291: char ch; ! 292: int idc; ! 293: } NEAR rgIdcOfCh[] = { ! 294: { '+', IDC_PLUS } ! 295: , { '-', IDC_MINUS } ! 296: , { '*', IDC_MULT } ! 297: , { '/', IDC_DIV } ! 298: , { 'C', IDC_CLEAR } ! 299: , { 'c', IDC_CLEAR } ! 300: , { '=', IDC_EQUALS } ! 301: , { '0', IDC_ZERO } ! 302: , { '1', IDC_ONE } ! 303: , { '2', IDC_TWO } ! 304: , { '3', IDC_THREE } ! 305: , { '4', IDC_FOUR } ! 306: , { '5', IDC_FIVE } ! 307: , { '6', IDC_SIX } ! 308: , { '7', IDC_SEVEN } ! 309: , { '8', IDC_EIGHT } ! 310: , { '9', IDC_NINE } ! 311: , { -1 , -1 } ! 312: }; ! 313: ! 314: // if the string is more that 1 character long, then we know its wrong. ! 315: if(SysStringLen(bstrButton) > 1) ! 316: return FALSE; ! 317: ! 318: // translate button string into control ID ! 319: for(i = 0;; ++i){ ! 320: if(rgIdcOfCh[i].ch == -1) ! 321: return FALSE; ! 322: if(rgIdcOfCh[i].ch == bstrButton[0]){ ! 323: button = rgIdcOfCh[i].idc; ! 324: break; ! 325: } ! 326: } ! 327: ! 328: return ButtonPush(button); ! 329: } ! 330: ! 331: ! 332: // the following method is internal, and not exposed for programmability ! 333: BOOL ! 334: CCalc::CArith::ButtonPush(int button) ! 335: { ! 336: if(button >= IDC_ZERO && button <= IDC_NINE){ ! 337: ! 338: long lVal = button - IDC_ZERO; ! 339: ! 340: switch(m_state){ ! 341: case STATE_EVAL: ! 342: m_accum = lVal; ! 343: m_state = STATE_LOPND; ! 344: break; ! 345: case STATE_OP: ! 346: m_opnd = lVal; ! 347: m_state = STATE_ROPND; ! 348: break; ! 349: case STATE_LOPND: ! 350: m_accum = (m_accum * 10) + lVal; ! 351: break; ! 352: case STATE_ROPND: ! 353: m_opnd = (m_opnd * 10) + lVal; ! 354: break; ! 355: } ! 356: ! 357: }else if(button >= IDC_PLUS && button <= IDC_DIV){ ! 358: ! 359: if(m_state == STATE_LOPND){ ! 360: m_opnd = m_accum; ! 361: m_state = STATE_OP; ! 362: m_op = button - IDC_PLUS + OP_PLUS; ! 363: } ! 364: ! 365: }else if(button == IDC_EQUALS){ ! 366: ! 367: if(m_state > STATE_LOPND) ! 368: Eval(); ! 369: ! 370: }else if (button == IDC_CLEAR){ ! 371: ! 372: Clear(); ! 373: ! 374: } ! 375: ! 376: SendMessage(m_pcalc->m_hwnd, BM_SETSTATE, 1, 0L); ! 377: SendMessage(m_pcalc->m_hwnd, BM_SETSTATE, 0, 0L); ! 378: ! 379: Display(); ! 380: ! 381: return TRUE; ! 382: } ! 383: ! 384: /*** ! 385: *void CCalc::CArith::Quit() ! 386: *Purpose: ! 387: * ! 388: *Entry: ! 389: * None ! 390: * ! 391: *Exit: ! 392: * None ! 393: * ! 394: ***********************************************************************/ ! 395: STDMETHODIMP_(void) ! 396: CCalc::CArith::Quit() ! 397: { ! 398: PostQuitMessage(0); ! 399: } ! 400: ! 401: ! 402: //--------------------------------------------------------------------- ! 403: // The CCalc Class Factory ! 404: //--------------------------------------------------------------------- ! 405: ! 406: ! 407: IClassFactory FAR* ! 408: CCalcCF::Create() ! 409: { ! 410: return new FAR CCalcCF(); ! 411: } ! 412: ! 413: ! 414: STDMETHODIMP ! 415: CCalcCF::QueryInterface(REFIID riid, void FAR* FAR* ppv) ! 416: { ! 417: if(riid == IID_IUnknown || riid == IID_IClassFactory){ ! 418: AddRef(); ! 419: *ppv = this; ! 420: return NOERROR; ! 421: } ! 422: return ResultFromScode(E_NOINTERFACE); ! 423: } ! 424: ! 425: ! 426: STDMETHODIMP_(ULONG) ! 427: CCalcCF::AddRef() ! 428: { ! 429: return ++m_refs; ! 430: } ! 431: ! 432: ! 433: STDMETHODIMP_(ULONG) ! 434: CCalcCF::Release() ! 435: { ! 436: if(--m_refs == 0){ ! 437: delete this; ! 438: return 0; ! 439: } ! 440: return m_refs; ! 441: } ! 442: ! 443: ! 444: STDMETHODIMP ! 445: CCalcCF::CreateInstance( ! 446: IUnknown FAR* punkOuter, ! 447: REFIID riid, ! 448: void FAR* FAR* ppv) ! 449: { ! 450: extern CCalc FAR* g_pcalc; ! 451: ! 452: return g_pcalc->QueryInterface(riid, ppv); ! 453: } ! 454: ! 455: ! 456: STDMETHODIMP ! 457: CCalcCF::LockServer(BOOL fLock) ! 458: { ! 459: return NOERROR; ! 460: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.