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