|
|
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.