📄 dde_stuf.cpp
字号:
Construct (aName);
}
C_DDE_Item::C_DDE_Item (const char* aName, float& rData)
{
pTheData = new float[1];
*(float*)pTheData = rData;
TheDataType = DDT_float;
Construct (aName);
}
C_DDE_Item::C_DDE_Item (const char* aName, double& rData)
{
pTheData = new double[1];
*(double*)pTheData = rData;
TheDataType = DDT_double;
Construct (aName);
}
C_DDE_Item::C_DDE_Item (const char* aName, long double& rData)
{
pTheData = new long double[1];
*(long double*)pTheData = rData;
TheDataType = DDT_long_double;
Construct (aName);
}
C_DDE_Item::C_DDE_Item (const char* aName, char& rData)
{
pTheData = new char[1];
*(char*)pTheData = rData;
TheDataType = DDT_char;
Construct (aName);
}
C_DDE_Item::C_DDE_Item (const char* aName, char* pData, int aSize)
{
pTheData = new char[aSize]; // Allocate lots of space for a string
strcpy ((char*)pTheData, pData); // Copy the string data in
TheDataType = DDT_string;
Construct (aName);
}
//-------------------------------------------------------------------------------------
// Function: Construct
// This function contains the code which is common to all the overloaded versions
// of the constructor. It is called by each of them.
void C_DDE_Item::Construct (const char* aName)
{
ItemName = new char[strlen (aName) + 1]; // Allocate space for, and save,
strcpy (ItemName, aName); // the item's DDE name
idInstance = 0L; // We have no instance handle yet
AdviseLinked = false; // No advise links have been set up
DataChanged = false; // Flag will show when data changes
DDE_Reading = false; // Set the flags which indicate
DDE_Writing = false; // that data is being read or written
User_Reading = false; // by either the DDE or user thread
User_Writing = false; // to all false, as nobody's doing so
}
//-------------------------------------------------------------------------------------
// Destructor: ~C_DDE_DataItem
// This destructor just frees the memory which was used by the data item object.
C_DDE_Item::~C_DDE_Item (void)
{
delete [] ItemName;
delete [] pTheData;
}
//-------------------------------------------------------------------------------------
// Function: Register
// Each DDE item must be registered with the DDEML system, and this registration
// must take place within the DDE thread, not the user-code thread. This func-
// tion is called from within the DDE thread, and it does the registration.
void C_DDE_Item::Register (DWORD aInstance, HSZ aTopic)
{
// Save instance handle and create DDE string handle for the name of this item
idInstance = aInstance;
hszItem = DdeCreateStringHandle (idInstance, ItemName, CP_DDESERV);
if (hszItem == 0L) DDE_CheckForError (idInstance);
hszTopic = aTopic; // Save handle of this item's topic
#ifdef MT_DEBUG_MODE
TakeDebugNote ("Registering item \"%s\", instance %08X, handle %08X\n",
ItemName, idInstance, (int)hszItem);
#endif
}
//-------------------------------------------------------------------------------------
// Function: StringToData
// This function uses the pointer to the data item to change that data in response
// to a DDE message with new data. The data is delivered as a string by the
// DDE server which owns this data item. The transfer is protected from being
// corrupted by simultaneous reads and writes in the user's and DDE threads.
void C_DDE_Item::StringToData (const char* aString)
{
// Check if user code is reading or writing the data; if so, wait until it's done
while ((User_Writing == true) || (User_Reading == true))
Sleep (0);
// Set a flag indicating that the DDE thread is writing data so the user's code
// won't read or change it as it's being written by this function
DDE_Writing = true;
switch (TheDataType)
{
case DDT_int:
sscanf (aString, "%d", pTheData);
break;
case DDT_uint:
sscanf (aString, "%d", pTheData);
break;
case DDT_long:
sscanf (aString, "%ld", pTheData);
break;
case DDT_ulong:
sscanf (aString, "%ld", pTheData);
break;
case DDT_float:
sscanf (aString, "%f", pTheData);
break;
case DDT_double:
sscanf (aString, "%lf", pTheData);
break;
case DDT_long_double:
sscanf (aString, "%Lf", pTheData);
break;
case DDT_char:
sscanf (aString, "%c", pTheData);
break;
case DDT_string:
sscanf (aString, "%s", pTheData);
break;
};
// OK, we're done reading the data; the user's thread may read or write it now
DDE_Writing = false;
}
//-------------------------------------------------------------------------------------
// Function: DataToString
// This function returns a pointer to a string which has just been filled with
// the data in this data item, properly formatted.
const char* C_DDE_Item::DataToString (void)
{
static char ReturnString[256]; // Holds string returned by function
// Check if the user's code is writing the data. If so, wait until it's done
while (User_Writing == true)
Sleep (0);
// Set a flag indicating that the DDE thread is reading data so the user's code
// won't change it as it's being read by this function
DDE_Reading = true;
switch (TheDataType)
{
case DDT_int:
sprintf (ReturnString, "%d", *(int *)pTheData);
break;
case DDT_uint:
sprintf (ReturnString, "%u", *(unsigned int*)pTheData);
break;
case DDT_long:
sprintf (ReturnString, "%ld", *(long*)pTheData);
break;
case DDT_ulong:
sprintf (ReturnString, "%lu", *(unsigned long*)pTheData);
break;
case DDT_float:
sprintf (ReturnString, "%f", *(float*)pTheData);
break;
case DDT_double:
sprintf (ReturnString, "%lf", *(double*)pTheData);
break;
case DDT_long_double:
sprintf (ReturnString, "%Lf", *(long double*)pTheData);
break;
case DDT_char:
sprintf (ReturnString, "%c", *(char*)pTheData);
break;
case DDT_string:
sprintf (ReturnString, "%s", (char*)pTheData);
break;
default:
sprintf (ReturnString, "DDE Data Error");
break;
};
DDE_Reading = false;
return ReturnString; // Return a pointer to the string
}
//-------------------------------------------------------------------------------------
// Function: SetValue
// This function is called to perform a thread-safe transfer of the user's data
// (in the user's thread) to the copy kept by the DDE item and accessed by the
// DDE thread. Thread safety requires that the user thread wait until the DDE
// thread has finished before changing the data, so these functions will refuse
// to set the data if the DDE thread is currently using it. If they successfully
// write the data, the return value is true; otherwise it's false.
bool C_DDE_Item::SetValue (int aData)
{
// If DDE thread is using the data or type is wrong, don't allow it to be written
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_int))
return false;
User_Writing = true; // DDE isn't using the data so set a flag
*(int*)pTheData = aData; // to indicate that this thread is, then
User_Writing = false; // change the data and clear the in-use
DataChanged = true; // flag and set data-changed flag so the
return true; // DDE thread is allowed to use the data
}
bool C_DDE_Item::SetValue (unsigned int aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_uint))
return false;
User_Writing = true;
*(unsigned int*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (long aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_long))
return false;
User_Writing = true;
*(long*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (unsigned long aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_ulong))
return false;
User_Writing = true;
*(unsigned long*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (float aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_float))
return false;
User_Writing = true;
*(float*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (double aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_double))
return false;
User_Writing = true;
*(double*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (long double aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true)
|| (TheDataType != DDT_long_double)) return false;
User_Writing = true;
*(long double*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (char aData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_char))
return false;
User_Writing = true;
*(char*)pTheData = aData;
User_Writing = false;
DataChanged = true;
return true;
}
bool C_DDE_Item::SetValue (const char* pData)
{
if ((DDE_Reading == true) || (DDE_Writing == true) || (TheDataType != DDT_string))
return false;
User_Writing = true;
strcpy ((char*)pTheData, pData);
User_Writing = false;
DataChanged = true;
return true;
}
//-------------------------------------------------------------------------------------
// Function: GetValue
// This function performs a thread-safe transfer of the item data from the copy
// kept by the DDE item and accessed by the DDE thread, to the copy kept by the
// user's program. If the DDE thread is currently reading the data, there is no
// problem because both threads can simultaneously read the data; but if the DDE
// thread is currently writing the data, this function refuses to read it and
// returns false.
bool C_DDE_Item::GetValue (int& rData)
{
// If DDE thread is currently writing the data we can't read it yet
if ((DDE_Writing == true) || (TheDataType != DDT_int)) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -