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