Microsoft KB Archive/118420

{|
 * width="100%"|

PRB: Problem Using -1 with Double or Float Field Variable

 * }

Q118420

1.50 WINDOWS kbprg kbprb -- The information in this article applies to: - The Microsoft Foundation Classes (MFC), included with: Microsoft Visual C++ for Windows, version 1.5 -- SYMPTOMS ======== If an edit control is mapped to a double or float field variable using DDX and RFX functions, a value of -1 for the variable is changed to NULL when a CRecordView moves past the record. To see how this works, perform the follow steps: 1. Use the Enroll sample that ships with Visual C++, version 1.5. 2. Add a field called "Fee" to the SECTION Table using Access, version 1.1. 3. Set the field to the Access data type of "Number". 4. Enter the data "1", "0", and "-1" into some records in the Fee field of the SECTION table. 5. Map a CRecordset double field variable, "m_Fee", to the column. 6. Add the label "Fee:" to ENROLL.RC and an edit-control box for "Fee:". 7. Map the m_Fee variable to the edit control. 8. Build the project and run it. 9. Move through the records. When the record with a -1 value for the fee appears, move to the next record and then back again. You will see that the -1 has been replaced with a NULL value. The edit control is empty. CAUSE ===== The Microsoft Foundation Classes need some way of determining whether a field value is NULL (no value). Because a double variable always has some value, MFC has defined what it calls "pseudo-null" values. If a variable contains a pseudo-null value, it is basically considered NULL. In the file AFXDB.H, you can see what the pseudo-null values are: #define AFX_RFX_INT_PSEUDO_NULL (0x7EE4) #define AFX_RFX_LONG_PSEUDO_NULL (0x4a4d4120L) #define AFX_RFX_BYTE_PSEUDO_NULL 255 #define AFX_RFX_SINGLE_PSEUDO_NULL (-1.0) #define AFX_RFX_DOUBLE_PSEUDO_NULL (-1.0) #define AFX_RFX_BOOL_PSEUDO_NULL 2 #define AFX_RFX_DATE_PSEUDO_NULL CTime(0) You can see that a value of -1.0 in a double or float field variable means that the field is to have a NULL value. This is not the only item that the database code uses for determining whether a field is NULL. A NULL flag is also used for each field variable, which indicates whether it contains a NULL value. The fundamental problem is in the code for "RFX_Double" and "RFX_Float" functions where the MarkForUpdate case is handled. Here is the code for RFX_Double: case CFieldExchange::MarkForUpdate: if (value == AFX_RFX_DOUBLE_PSEUDO_NULL) pFX->m_prs->SetFieldFlags(nField, AFX_SQL_FIELD_FLAG_NULL, pFX->m_nFieldType); else pFX->m_prs->ClearFieldFlags(nField, AFX_SQL_FIELD_FLAG_NULL, pFX->m_nFieldType); goto LDefault; The problem is that the code simply checks the value of the double field variable and sets the NULL flag if its value is -1 (the pseudo-null value). The MarkForUpdate code is executed every time a CRecordView moves off of a record. Here is some of the code in CRecordView::OnMove: if (pSet->CanUpdate) { pSet->Edit; if (!UpdateData) return FALSE; pSet->Update; } RESOLUTION ========== There are two possible workarounds. The value of the pseudo-null value can be changed to something that a user of the application is not expected to type into the edit control. So, in the case of RFX_Double, "AFX_RFX_DOUBLE_PSEUDO_NULL" can be changed in AFXDB.H to something like the following: #define AFX_RFX_DOUBLE_PSEUDO_NULL (-9.123e19) It would be uncommon for a user to type this. If you decide to fix the problem this way, you need to rebuild the MFC library using the information in the README.TXT file in the \MSVC\MFC\SRC directory. Another way to work around this problem is to copy the code for RFX_Double into the .CPP file where your CRecordset class implementation code is. Change the function name to "RFX_NewDouble" or whatever you want to call it. Then, delete the "MarkForUpdate" case statement shown above. You can also remove the "LDefault:" label, which is used by the goto statement at the end of the MarkForUpdate case. Once you have created this new RFX_NewDouble function, you need to replace the call to RFX_Double in your CRecordset's DoFieldExchange function with RFX_NewDouble. MORE INFORMATION ================ Beginning with Visual C++ for Windows version 1.51 and Visual C++ 32-bit Edition version 2.0, the definitions of AFX_RFX_SINGLE_PSEUDO_NULL and AFX_RFX_DOUBLE_PSEUDO_NULL use a value of -9.123e19 instead of -1.0. Additional reference words: 1.50 2.50 ODBC no32bit noupdate KBCategory: kbprg kbprb KBSubcategory: MfcDatabase

Keywords : kb16bitonly kbDatabase kbMFC kbODBC kbVC

Issue type :

Technology : kbAudDeveloper kbMFC