home *** CD-ROM | disk | FTP | other *** search
/ Dan Appleman's Visual Bas…s Guide to the Win32 API / Dan.Applmans.Visual.Basic.5.0.Programmers.Guide.To.The.Win32.API.1997.Ziff-Davis.Press.CD / VB5PG32.mdf / vbpg32 / apigid32 / vbintf.cpp < prev   
Encoding:
C/C++ Source or Header  |  1996-02-11  |  11.3 KB  |  417 lines

  1. /***********************************************************************
  2.    File vbintf.cpp
  3.  
  4.    APIgid32 VB Interface demonstration file for Visual Basic Programmer's Guide to Win32 API
  5.  
  6.    Written By Daniel Appleman
  7.    Copyright (c) 1995 by Desaware - All rights reserved
  8.  
  9.       You have a royalty-free right to use, modify, reproduce and distribute
  10.     this file (and/or any modified versions) in any way you find useful,
  11.     provided that you agree that Desaware and Ziff-Davis Press has no warranty, 
  12.     obligation or liability for its contents, and that you 
  13.     include an acknowledgement identifying those portions of
  14.     the code that were authored by Desaware. You are also required
  15.     to change the name of the file before distributing modified
  16.     versions of these files. 
  17.  
  18.    This file is provided "As-Is". No support is provided for the contents
  19.    or use of this file by Ziff-Davis Press, Daniel Appleman or Desaware.
  20.  
  21.    Refer to the Ziff-Davis Visual Basic Programmer's Guide to the
  22.    Win32 API for further information.
  23.  
  24.  
  25.  
  26. ************************************************************************/
  27.  
  28. #include "stdafx.h"
  29. #include "apigid32.h"
  30.  
  31. #ifdef _DEBUG
  32. #undef THIS_FILE
  33. static char BASED_CODE THIS_FILE[] = __FILE__;
  34. #endif
  35.  
  36.  
  37. char tbuf[80];    // Temporary character buffer
  38.  
  39. STDAPI_(VOID) fToString(double d, char *t)
  40. {
  41.    int x;
  42.    static int decimalvar, signvar;
  43.    char *buffer;
  44.    buffer = _fcvt(d,5,&decimalvar, &signvar);
  45.    if(signvar) *t++ = '-';
  46.    for(x=0; x<decimalvar && *buffer; x++) *t++ = *buffer++;
  47.    if(*buffer) *t++ = '.';
  48.    while(*buffer) *t++ = *buffer++;
  49.    *t = '\0';
  50. }
  51.  
  52.  
  53. /* These function demonstrates passing numeric variables by value, and
  54.    returning numeric variables.  The MessageBox statement in each
  55.    routine shows the value of the variable received.
  56. */
  57.  
  58. STDAPI_(short) ReceivesInteger(short x)
  59. {
  60.     
  61.    _itoa(x, tbuf, 10);   /* Place value in temporary buffer */
  62.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesInteger", MB_OK);
  63.    return(x);
  64. }
  65.  
  66. STDAPI_(BYTE) ReceivesBytes(BYTE a, BYTE b)
  67. {
  68.     
  69.    tbuf[0] = a;
  70.    tbuf[1] = b;
  71.    tbuf[2] = '\0';
  72.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesBytes", MB_OK);
  73.    return('x');
  74. }
  75.  
  76.  
  77. STDAPI_(long) ReceivesLong(long y)
  78. {
  79.    _ltoa(y, tbuf, 10);   /* Place value in temporary buffer */
  80.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesLong", MB_OK);
  81.    return(y);
  82. }
  83.  
  84. STDAPI_(float) ReceivesSingle(float f)
  85. {
  86.    fToString((double)f, tbuf);   /* Place value in temporary buffer */
  87.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesSingle", MB_OK);
  88.    return(f);
  89. }
  90.  
  91. STDAPI_(double) ReceivesDouble(double d)
  92. {
  93.    fToString(d, tbuf);   /* Place value in temporary buffer */
  94.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesDouble", MB_OK);
  95.    return(d);
  96. }
  97.  
  98. /* These functions demonstrate passing numeric variables by reference.
  99.    Note how the DLL function can modify the variable used by VB.
  100.    These particular examples are defined as VOID to be used by SUB
  101.    declarations in VB.  One could just as easily had these return
  102.    results as done in the examples above.
  103. */
  104.  
  105. STDAPI_(VOID) Add5ToInteger(short FAR *x)
  106. {
  107.    *x = (*x) + 5;
  108. }
  109.  
  110. STDAPI_(VOID) Add5ToLong(long FAR *y)
  111. {
  112.    *y = (*y) + 5;
  113. }
  114.  
  115. STDAPI_(VOID) Add5ToSingle(float FAR *f)
  116. {
  117.    *f = (*f) + 5;
  118. }
  119.  
  120. STDAPI_(VOID) Add5ToDouble(double FAR *d)
  121. {
  122.    *d = (*d) + 5;
  123. }
  124.  
  125.  
  126. /* This example shows passing a currency variable by value, and returning
  127.    a currency value */
  128.  
  129. STDAPI_(currency) ReceivesCurrency(currency curr)
  130. {
  131.    double tres = 0;
  132.    double factor = 1;
  133.    double tval;
  134.    short x;
  135.  
  136.    /* This currency variable is in base 10 with 4 digits to the right of
  137.       the decimal point */
  138.  
  139.    /* This conversion (for display purposes) involves a loss of precision
  140.       and does not handle negative numbers */
  141.    for(x=0; x<8; x++) { /* Convert the currency into a double data type */
  142.       tval = (double)((WORD)curr.cbuf[x]);
  143.       tres+= tval*factor;
  144.       factor *=256;
  145.       }
  146.    tres/=10000;   /* Number is fixed 4 digit precision, so we divide to
  147.                      obtain the actual value */
  148.    fToString(tres, tbuf);
  149.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesCurrency", MB_OK);
  150.      
  151.    return(curr);
  152. }
  153.  
  154.  
  155.  
  156. /* This example is call by reference. */
  157. STDAPI_(void) AddPennyToCurrency(currency FAR *curptr)
  158. {
  159.    short x;
  160.    WORD temp, toadd;
  161.  
  162.    /* This currency variable is in base 10 with 4 digits to the right of
  163.       the decimal point */
  164.  
  165.    /* Now you can use whatever math routines you have to maniuplate this
  166.       buffer - consider this trivial 'add penny' algorithm */
  167.    toadd = 100;   /* 1 penny in this scale */
  168.    for(x=0; x<8 && toadd; x++) {
  169.       temp = curptr->cbuf[x];
  170.       temp+=toadd;
  171.       if(temp>=256) {
  172.          temp-=256;  toadd=1; /* Need to continue with carry */
  173.          }
  174.       else toadd=0;  /* Finished with the addition */
  175.       curptr->cbuf[x] = (char)temp;
  176.       }
  177. }
  178.  
  179. /* Method used for most API calls.  VB passes a null terminated string
  180. */
  181. STDAPI_(VOID) ReceivesString(LPSTR tptr)
  182. {
  183.    /* Warning - it's not a copy despite the byval part in the declaration */
  184.    MessageBox(GetFocus(), (LPSTR)tptr, (LPSTR)"ReceivesString", MB_OK);
  185. }
  186.  
  187. /* This example shows how a string can be modified - as long as you don't
  188.    go beyond the space allocated */
  189.  
  190. STDAPI_(VOID) ChangesString(LPSTR tptr)
  191. {
  192.    /* Warning on overwriting null!!! */
  193.    if (*tptr) *tptr = '!';
  194. }
  195.  
  196. /* This example shows how you can pass Visual Basic strings to a DLL,
  197.    but the DLL must be linked with VBAPI.LIB - part of the VB control
  198.    development kit.
  199. */
  200.  
  201. STDAPI_(VOID) ReceivesVBString(BSTR *sptr)
  202. {
  203.    LPSTR tptr;
  204.    WORD vbstrlen;
  205.    WORD x;
  206.    if(!sptr) {
  207.            MessageBox(GetFocus(), "Invalid pointer as parameter", "ReceivesVBString", MB_OK);
  208.         return;
  209.         }
  210.     // We can actually pass *sptr directly to the MessageBox function, but this shows some
  211.     // extra manipulation we can do.
  212.     vbstrlen = SysStringByteLen(*sptr); /* Get length of VB string */
  213.     tptr = (LPSTR)*sptr;
  214.     for(x=0; x<vbstrlen && x<sizeof(tbuf)-1; x++)
  215.         tbuf[x] = *tptr++;
  216.        tbuf[x] = '\0';   /* Null terminate the string */
  217.        /* Remember - VB strings can contain NULLs */
  218.        MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesVBString", MB_OK);
  219. }
  220.  
  221. /* This example shows how you can change a string that was passed as
  222.    a parameter in a DLL.
  223.    No length restrictions apply when using this technique (other than
  224.    the usual VB string length limits
  225. */
  226. STDAPI_(VOID) ChangesVBString(BSTR *sptr)
  227. {
  228.    if(!sptr) return;    // Should never happen - just being paranoid
  229.    if(*sptr) SysFreeString(*sptr);
  230.    *sptr = SysAllocString((OLECHAR *)"Any Length Ok");
  231. }
  232.  
  233. /* This example shows how you can return a VB string from a DLL. */
  234. STDAPI_(BSTR) ReturnsVBString()
  235. {
  236.     char *a = "This string is created in the DLL";
  237.    return(SysAllocString((OLECHAR *)a));
  238. }
  239.  
  240.  
  241. /* Call by reference only */
  242. STDAPI_(VOID) ReceivesUserType(usertype FAR *u)
  243. {
  244.    wsprintf((LPSTR)tbuf, (LPSTR)"usertype contains %d %d %d %d",
  245.             u->a, u->b, u->c, u->d);
  246.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesUserType", MB_OK);
  247. }
  248.  
  249. /* VB strings in a user defined type can be accessed.  If not initialized,
  250.    they may be null (though I have never actually seen this),
  251.    in which case the DLL can create the string - otherwise
  252.    the DLL should use VBSetHlstr().
  253. */
  254. STDAPI_(VOID) AddUserString(usertype FAR *u)
  255. {
  256.     if(!u->hs) {
  257.       /* Documentation suggests that this case may be possible */
  258.       u->hs = SysAllocString((OLECHAR *)"New string here!");
  259.       }
  260.    else {
  261.       MessageBox(GetFocus(), (LPSTR)u->hs, (LPSTR)"Existing string is:", MB_OK);
  262.       SysFreeString(u->hs);
  263.       u->hs = SysAllocString((OLECHAR *)"Replaced string");
  264.       }
  265. }
  266.  
  267. STDAPI_(usertype) ReturnUserType()
  268. {
  269.     usertype u;
  270.     u.a = 1; u.b = 3; u.c = 5; u.d = 7;
  271.     u.hs = NULL;
  272.     return(u);
  273. }
  274.  
  275.  
  276.  
  277. /* Array of integers - Be careful not to exceed the limit of the array!
  278.    This technique can be used on all numeric data types.
  279.    Note the special calling sequence in the VB example.
  280.    It will not work on strings.
  281. */
  282.  
  283. STDAPI_(VOID) ReceivesIntArray(short FAR *iptr)
  284. {
  285.    wsprintf((LPSTR)tbuf, (LPSTR)"1st 4 entries are %d %d %d %d",
  286.             *(iptr), *(iptr+1), *(iptr+2), *(iptr+3));
  287.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesIntArray", MB_OK);
  288.    (*iptr)++;    // Increment the int array for to verify the by reference features (that way you
  289.                    // can tell if you are using a temporary copy
  290. }
  291.  
  292.  
  293.  
  294.  
  295.  
  296. STDAPI_(short) ReceivesVBArray(SAFEARRAY **lpsa)
  297. {
  298.     SAFEARRAY *psa;
  299.     short *pdata;
  300.     
  301.     if(!lpsa) return(-1);
  302.     psa = *lpsa;
  303.     if(!psa) return(-1);
  304.     pdata = (short *)psa->pvData;
  305.     
  306.    wsprintf((LPSTR)tbuf, (LPSTR)"Array of %d dimensions, %ld bytes per element\nFlags: %x, First int entry is %d",
  307.                 psa->cDims, psa->cbElements, psa->fFeatures, *pdata);
  308.             
  309.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesVBArray", MB_OK);
  310.    (*pdata)++;
  311.    return(0);
  312. }
  313.  
  314.  
  315.  
  316.  
  317.  
  318. STDAPI_(short) ReceivesVariantByVal(VARIANTARG vr)
  319. {
  320.    short res;
  321.  
  322.    res = vr.vt;
  323.  
  324.    wsprintf((LPSTR)tbuf, (LPSTR)"Variant Type %d", res);
  325.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesVariantByVal", MB_OK);
  326.    return(0);
  327. }
  328.  
  329.  
  330. STDAPI_(VARIANTARG) ReceivesVariant(VARIANTARG *vr)
  331. {
  332.    short res;
  333.    long l = 12345678;
  334.  
  335.    res = vr->vt;
  336.  
  337.    wsprintf((LPSTR)tbuf, (LPSTR)"Variant Type %d", res);
  338.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ReceivesVariantByVal", MB_OK);
  339.    VariantClear(vr);
  340.    vr->vt = VT_I4;
  341.    vr->lVal = l;
  342.    return(*vr);
  343. }
  344.  
  345.  
  346. STDAPI_(double) UsesDate(double d)
  347. {
  348.    fToString(d, tbuf);   /* Place value in temporary buffer */
  349.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"Date as float", MB_OK);
  350.    return(d+1);
  351. }
  352.  
  353. STDAPI_(VOID) ReceivesObject(LPUNKNOWN lpv)
  354. {
  355.     HRESULT hr;
  356.     LPDISPATCH lpd;
  357.     ITypeInfo *lti;
  358.     BSTR bst, bst2;
  359.     hr = lpv->QueryInterface(IID_IDispatch, (LPVOID FAR *)&lpd);
  360.     if(SUCCEEDED(hr) && lpd) {
  361.         hr = lpd->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, <i);
  362.         if(SUCCEEDED(hr) && lti) {
  363.             hr = lti->GetDocumentation(MEMBERID_NIL, &bst, NULL, NULL, NULL);
  364.             if(SUCCEEDED(hr)) {
  365.                 bst2 = SysAllocStringByteLen(NULL, SysStringLen(bst));
  366.                 wcstombs((LPSTR)bst2,(LPWSTR)bst,SysStringLen(bst));
  367.                 MessageBox(GetFocus(), (LPSTR)bst2, "First Type", MB_OK);
  368.                 SysFreeString(bst);
  369.                 SysFreeString(bst2);
  370.                 }
  371.             lti->Release();
  372.             }
  373.         lpd->Release();
  374.         }
  375.     return;
  376. }
  377.  
  378.  
  379. STDAPI_(LPUNKNOWN) ReceivesObject2(LPUNKNOWN lpv)
  380. {
  381.     lpv->AddRef();
  382.     return(lpv);
  383. }
  384.  
  385. STDAPI_(VOID) ChangesObject(LPUNKNOWN lpv1, LPUNKNOWN *lpv2)
  386. {
  387.     lpv1->AddRef();
  388.     (*lpv2)->Release();
  389.     *lpv2 = lpv1;
  390. }
  391.  
  392. STDAPI_(LONG) ShowAddress(LPVOID lp)
  393. {
  394.     wsprintf((LPSTR)tbuf, (LPSTR)"Received address %.8lx", lp);
  395.    MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"ShowAddress", MB_OK);
  396.     return((LONG)lp);
  397. }
  398.  
  399. STDAPI_(VOID) DumpValues(LPVOID lp, short cnt)
  400. {
  401.     char t2buf[10];
  402.     short x;
  403.     LPBYTE lpb = (LPBYTE)lp;
  404.     tbuf[0] = '\0';
  405.     for (x=0;x<cnt;x++) {
  406.         wsprintf((LPSTR)t2buf,"%.2x ", *(lpb + x));
  407.         lstrcat(tbuf, t2buf);
  408.         }
  409.     MessageBox(GetFocus(), (LPSTR)tbuf, (LPSTR)"Data View", MB_OK);
  410. }
  411.  
  412. STDAPI_(VOID) ChangeValues(LPBYTE lp, LPBYTE newval, short cnt)
  413. {
  414.     short x;
  415.     for (x=0; x<cnt; x++) *lp++ = *newval++;
  416. }
  417.