Praveen Katiyar' Blog

Learning along the way . . . .

Packing a array inside a VARIANT (VC++ 6.0) (Series 2 of N)

This is the second post about variant, in this post I I am going to explain, how an array of strings can be packed inside a VARIANT variable.

Packing  a array of string inside a Variant

int  PackVariantWithStringArray(short nCnt, VARIANT * pVar )
{
    USES_CONVERSION ;

    //Initialize the VARIANT (Type is SAFEARRAY of BSTRs)
    VariantInit(pVar);
    pVar->vt = VT_ARRAY | VT_BSTR;

    // Define a safe array of nCnt Item and Starting index as 0
    SAFEARRAYBOUND safeBounds = { nCnt, 0};
   
    //Create the Safe Array passing it the bounds
    SAFEARRAY* pSafeArray = SafeArrayCreate(VT_BSTR, 1, &safeBounds);

    //Get a pointer, actually increments the array’s lock count)
    BSTR* bstrArray = NULL;
    SafeArrayAccessData(pSafeArray, (void**)&bstrArray);
    for ( int i = 0 ; i < nCnt ; i++ )
    {
        CString strTmp ;
        strTmp.Format ( _T("This is Item %2d"), i );
        bstrArray [i] = strTmp.AllocSysString () ;
    }

    //done wth populating, Decrement the array’s lock count
    SafeArrayUnaccessData(pSafeArray);

    //Assign our VARIANT out param with the array   
    pVar->parray = pSafeArray ;
    return nCnt ;
}

as it can be seen from the above code, it involves following steps.

  1. Allocating the desired temporary buffer space to hold the array of bytes, and filling that array with values one need to return.
  2. creating a safe array of the desired (VT_BSTR) type.
  3. copying the temporary buffer to the safe array of the variant.
  4. free the memory allocated for temporary buffer. (avoid memory leaks).

Fetching a array of strings from a variant.

TCHAR ** UnPackVariantWithStringArray(short nCnt, VARIANT var )
{
    TCHAR **pBuffer = (TCHAR **) calloc ( nCnt, sizeof (INT)) ; 

    USES_CONVERSION ;
    SAFEARRAY* pSafeArray  = var.parray ;
    //pointer to array data, actually increments the lock count
    BSTR* bstrArray = NULL ;
    SafeArrayAccessData ( pSafeArray, (void**)&bstrArray);
    for ( int i = 0 ; i < nCnt ; i++ )
    {
        LPTSTR szTmp = OLE2T ( bstrArray [i] ) ;
        int nLen = _tcslen ( szTmp );
        pBuffer [i]= (TCHAR *) calloc ( nLen, sizeof ( TCHAR));
        _tcscpy ( pBuffer [i], szTmp);
    }
   
    //Done wth populating, Decrement the array’s lock count
    SafeArrayUnaccessData(pSafeArray);
    return pBuffer ;
}

these conversion is useful in middleware scenario. in the next article I will explain how to pack array of structure inside a variant.

Advertisements

July 18, 2013 Posted by | CodeProject, MFC, Win32 | , , | Leave a comment

Packing a array inside a VARIANT (VC++ 6.0) (Series 1 of N)

VARIANTs are versatile data types, they can hold any type of value, apart from that they can hold array of different types. In this post I am going to explain how can you pack a array of bytes, inside a variant variable.

Packing  a array of simple types inside a Variant

Packing  a array of bytes

int GetVariantWithByteBuffer (int nBufferSize, VARIANT FAR* pVar)
{

    /* here size of buffer desired (nBufferSize) has been passed to the function, which can be determined before hand. */

/* Creating a temporary buffer to hold the values one need to return and filling that buffer. fill buffer, this buffer can be filled some other ways too, reading from a file or reading from some hardware or whatever  here it has been filled from values 1 – 255*/

     BYTE *pBuffer = (BYTE *) calloc ( nBufferSize, sizeof (BYTE))
     for ( int i = 0 ;  i < nBufferSize; i++ ) pBuffer [i] = ( i + 1 ) % 256 ; 

     /* Creating a variant to return, which can hold the safe array of bytes .*/

     SAFEARRAY FAR* psa ;
     psa = SafeArrayCreateVector (VT_UI1, 0, nBufferSize); 
      if(psa == NULL)    return –1 ;  
      
     /* Copying the temporary buffer to the variant to return */

     VariantInit ( pVar ) ;

     pVar->parray = psa;
     pVar->vt = VT_ARRAY | VT_UI1 ; 
     memcpy ( pVar->parray->pvData , pBuffer, nBufferSize * sizeof (BYTE) ) ;  

    /* free the temporary buffer */

    free ( pBuffer ) ;

    /* return the number of elements  this variant hold. */
    return nBufferSize;

}

as it can be seen from the above code, it involves following steps.

  1. Allocating the desired temporary buffer space to hold the array of bytes, and filling that array with values one need to return.
  2. creating a safe array of the desired (VT_UI1) type.
  3. copying the temporary buffer to the safe array of the variant.
  4. free the memory allocated for temporary buffer. (avoid memory leaks).

Fetching a array of bytes from a variant.

BYTE * GetByteBufferFromVariant (int nBufferSize, VARIANT var )
{

    /* here size of buffer desired (nBufferSize) has been passed to the function, which can help us determine the size of the buffer required. */

    BYTE *pBuffer = (BYTE *) calloc ( nBufferSize, sizeof (BYTE)) ;  
    memcpy ( pBuffer, var.parray->pvData, nBufferSize * sizeof (BYTE) ) ;  
    return pBuffer ;

}

In  a similar fashion array of some other simple types can be  packed in a variant. the following table describes the data types for different simple types.

S.N. Data Type Value of vt
1 BYTE VT_ARRAY | VT_UI1
2 SHORT (2 byte signed integer ) VT_ARRAY | VT_I2
3 USHORT (2 byte unsigned integer ) VT_ARRAY | VT_UI2
4 INT (4 byte signed integer ) VT_ARRAY | VT_I4
5 UINT (4 byte unsigned integer ) VT_ARRAY | VT_UI4
6 FLOAT ( 4 byte float value) VT_ARRAY|VT_R4
7 DOUBLE (8 byte double value) VT_ARRAY|VT_R8

 

using the table above one can pack array of above defined types, to variant, these conversion is useful in middleware scenario. in the next article I will explain how to pack array of strings and array of structure inside a variant.

July 17, 2013 Posted by | CodeProject, MFC, Win32 | , , | Leave a comment

Creating a status Bar in a Dialog Box ( VC++, MFC)

Normally in MFC Applications one can not create a status bar by default, this article shows you how status bar can be created in a dialog box.

Create a Dialog based application, using MFC AppWizard,

compile and make sure that every thing is working fine.

Open “resource.h”

define two identifiers in the file ”resource.h”, for two panes, these identifier will be used to identify two panes in the status bar you are going to create.

#define ID_INDICATOR_PANE             106
#define ID_INDICATOR_TIME             107

define an array of indicators in  DialogBox Source file, let say if you need to create two panes, you need  to define two values as shown below.

static UINT BASED_CODE indicators[] =
{
    ID_INDICATOR_PANE,
    ID_INDICATOR_TIME
};

Now make the necessary modifications in the Dialog Box’s InitDialog function.

BOOL CMyStatusBarDialogDlg::OnInitDialog()
{
//    rudimentary stuff
    CDialog::OnInitDialog();

// Set the icon for this dialog. 
    SetIcon(m_hIcon, TRUE);        // Set big icon
    SetIcon(m_hIcon, FALSE);       // Set small icon

// Here is what you need, to create a status bar
m_StatusBar.Create(this);     //Create status bar
m_StatusBar.SetIndicators(indicators,2);

//    Find the Size of Dialog box

CRect rect;                                       
GetClientRect(&rect);        

//    Size the two panes
m_StatusBar.SetPaneInfo(0,ID_INDICATOR_PANE, SBPS_NORMAL, rect.Width()-100);     
m_StatusBar.SetPaneInfo(1,ID_INDICATOR_TIME, SBPS_STRETCH ,0);

//    This is where we actually draw it RepositionBars( AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, ID_INDICATOR_TIME ) ;

    // Timer is Set to Update the Time on the status Bar.   
    SetTimer(100,1000,NULL);

    return TRUE;  // return TRUE  unless . . . .
}

Implement the Message WM_TIMER to update time

Implement the WM_TIMER message handler to update the current time on the pane of the status bar.

void CStatusBarDialogDlg::OnTimer(UINT nIDEvent)
{
    // TODO: Add your message handler code here 

    if ( nIDEvent==STATUS_TIMEER )
    {
        CTime t1 ;
        t1 = CTime::GetCurrentTime();
        m_StatusBar.SetPaneText(1,t1.Format("%H:%M:%S"));
    }
    CDialog::OnTimer(nIDEvent);
}

build and execute, and voila you are done.

June 29, 2013 Posted by | CodeProject, GUI, MFC | , , | Leave a comment