March 20, 2019
Hot Topics:

Getting Records from the Remote Device

  • December 1, 2004
  • By Nancy Nicolaisen
  • Send Email »
  • More Articles »

Initializing the CRecordListDialog

First, you initialize the dialog's window caption to reflect the name of the database from which you are retrieving records. To do this, first you get a pointer to the CMainFrame object that owns the dialog; then you get a pointer to the CRemoteDBScanView object that owns the list control; and finally, you get the list control itself.

BOOL CRecordListDialog::OnInitDialog()

    //Set dialog title to name of this database

    CMainFrame* pFrame = (CMainFrame*)this->GetParent();
    CRemoteDBScanView* pListView =
    CListCtrl& ListCtrl = pListView->GetListCtrl();

Once again, you query the selected item position, receiving a POSITION value that you decrement, and cast so that you can use it as a list control item index.

    //get currently selected row
    POSITION pos = ListCtrl.GetFirstSelectedItemPosition();

    //pos is a 1-based index, so you must decrement
    int ipos = (int)--pos;

You retrieve the database name by initializing lvitem.iItem with the index of the selected row and lvitem.iSubItem with 0, the index of the list control column that contains the database names.

    //set caption for the DB you are scanning
    LVITEM lvitem;
    CHAR szBuff[124];

    memset( &szBuff, 0x0, sizeof(szBuff));
    lvitem.mask = LVIF_TEXT ;
    //pos is a 1-based index, so you must decrement
    lvitem.iItem      = ipos;
    lvitem.iSubItem   = 0;
    lvitem.pszText    = szBuff;
    lvitem.cchTextMax = sizeof(szBuff);

The database name is returned in szBuff, which was sized so that you could safely catenate the rest of the dialog's caption text.

    strcat(szBuff, " Records" );

You set the string in the dialog's title bar by calling the CWnd base class function, SetWindowText().


Now, you open the selected database using the CEOID value you stored in the database name's item data. You save the database CEOID in a CRecordListDialog public member variable, m_globalCEOID.

    //get the saved CEOID
    m_globalCEOID = (CEOID)ListCtrl.GetItemData(ipos);

You initialize RAPI, and if successful, proceed to open the database.

    //init rapi
    HRESULT hr = CeRapiInit();
    if( hr != ERROR_SUCCESS )
        {return FALSE;}

You looked at this function in depth in the course of the treatment of the CE database API, but if you skipped over those lessons, you can examine it again briefly here.

The parameters to CeOpenDatabase(), in the order shown, are the address of a variable of type CEOID, a pointer to a Unicode string containing the name of the database to open, the index of the SORTORDERSPEC to apply when the database is opened, a flag that tells whether to let the application increment the current position in the database of serial read operations or whether the system should automatically increment the current position, and the handle to a window that can display message boxes for the called function.

In this case, you are opening the database by CEOID value, and so pass NULL for the address of the name string. Also, you are opening the database with the express intent of serially reading through its record set, so you set the fourth parameter to CEDB_AUTOINCREMENT. This means that you won't have to handle the database seek operation except before your first read, when you set the current position to the first database record. The last parameter, m_hWnd, is a CWnd base class member variable that stores this object's window handle.

    //open using  CEOID
    m_globalHDB =
        CeOpenDatabase (&m_globalCEOID, NULL,
                        0,  CEDB_AUTOINCREMENT, m_hWnd);
     if( m_globalHDB == INVALID_HANDLE_VALUE )
     { return FALSE; }

If you are successful, you save the returned database handle in the CRecordListDialog member variable, m_globalHDB. To do any sort of operation on a CE database, you must first explicitly set the "current record" by calling CeSeekDatabase(). The parameters to CeSeekDatabase(), in the order shown, are the handle to the open database, the seek type flag, the offset to which to seek from the flagged database position, and the address of a variable that receives the index of the record to which the seek operation positioned. Notice that when you seek to the beginning of the database, the seek offset is set to 1 rather than to 0.

    //seek to the beginning of the database
    CEOID oid     = 0;
    DWORD dwIndex = 0;
    int iRecIndex = 1;
    oid = CeSeekDatabase (m_globalHDB, CEDB_SEEK_BEGINNING,
                          iRecIndex, &dwIndex);

You read the first record with a call to CeReadRecordProps(). The parameters to this function, in the order shown, are the handle to the open database; a flag that tells the system to dynamically allocate a buffer to hold the record data; the address of a DWORD that receives the count of properties returned for this record; a NULL flag that indicates you want to retrieve all properties for this record; the address of a pointer to the buffer in which CeReadRecordProps() placed the record data; and the address of a DWORD that gives the size in bytes of the record data.

    //get the first record

    // Read all properties for the record. Have the system
    // allocate the buffer containing the data.
    DWORD dwRecSize = 0;
    WORD wProps     = 0;
    PBYTE pRecord   = NULL;

    oid = CeReadRecordProps (m_globalHDB, CEDB_ALLOWREALLOC,
                             &wProps, NULL,
                             &(LPBYTE )pRecord, &dwRecSize);
        {return FALSE;}

If you successfully read the record, you format the record data and display it in the list box, using the CRecordListDialog member function PublishRecord. You insert a blank line in the list control to provide a separation between records, and continue reading until CeReadRecordProps() returns 0, indicating that there are no more records.

    //while more records
    while (oid != 0 )
       //format the record and insert data in the list control
        PublishRecord( oid, wProps, (PCEPROPVAL)pRecord, dwRecSize );
        //add a line between records
        m_RecordListCtrl.InsertString( -1, "" );

       //read the record
        oid = CeReadRecordProps (m_globalHDB, CEDB_ALLOWREALLOC,
                                 &wProps, NULL,
                                 &(LPBYTE )pRecord, &dwRecSize);


When the OnInitDialog() function's work is done, you close the remote database with a call to CloseHandle(), and uninitialize the RAPI subsystem.

    //close db

    //unint rapi

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE

Looking Ahead

In the next lesson, you'll see how to interpret the retrieved records and format them for display on the desktop side of the connection.

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, and entry time data validation.

In addition to writing for Developer.com, she has written several books, including Making Win 32 Applications Mobile.

Page 2 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date