how to change editcontrol with function? - c++

hello guys I was plc programmer just trying to start C++ programmer
I am trying to convert to this code to function
m_file.Open(posText[7], CStdioFile::modeRead);
m_file.ReadString(posValue[7]);
UpdateData(TRUE);
dlg.s_PostionZ2 = posValue[7];
UpdateData(FALSE);
m_file.Close();
and this my function but it didn't work
void mainDial::opeFile(CString path, CString value, CString location)
{
slaveDialog dlg;
m_file.Open(path, CStdioFile::modeRead);
m_file.ReadString(value);
AfxMessageBox(location);
UpdateData(TRUE);
location = value;
UpdateData(FALSE);
m_file.Close();
}
what I am trying to do is just open a file and save to value and change location value
the problem is the location is in the other dialog (SlaveDialog dlg;)
it is ok by just simply enter dlg.S_position
but if I want it to do with using a function to pass the location like this
opeFile(posText[0], posValue[0], _T("dlg.s_PostionX1"));
or
opeFile(posText[0], posValue[0], dlg.s_PostionX1);
it didn't work both way so how can I change to my function work
thank you for reading

what I am trying to do is just open a file and save to value and change location value
You are passing in the function's output parameters by value, so they make copies of the caller's values. Any changes the function makes to the parameters is done to the copies and not reflected back to the caller.
To do what you want, you need to pass in the output parameters by reference instead, eg:
void mainDial::opeFile(CString path, CString& value, CString& location)

Related

static LPTSTR variable loses value after function execution

I'm writing C++ dll on Visual studio 2013. My dll should read parameters from ini file. So, I've created a function for this purpose (ReadConnectionSettings()). My static variable serverIP gets value properly during the function working, however once the function complete running the variable (serverIP) loses its value. What seems to be the problem?
static LPTSTR serverIP = _TEXT("");
void ReadConnectionSettings()
{
TCHAR url[256];
GetPrivateProfileString(_T("Connection"), _T("Url"), _T(""), url, 256, NameOfIniFile);
serverIP = url;
}
You are pointing the pointer serverIP at stack memory url.
This goes out of scope when the function exits, so your pointer is left pointing to junk.
What you could do is make serverIP a buffer instead, and copy the URL into it. Then it would persist.
That is:
static TCHAR serverIP[256] = _TEXT("");
Then:
_tcsnccpy(serverIP, url, 255);
Or as #DavidOtano suggested, you could keep your existing serverIP pointer, and use:
serverIP = _tcsdup(url);
But if you do this, you're dynamically allocating memory, so will need to remember to call:
free(serverIP);
when you no longer need it, to avoid a memory leak.
You're setting the static pointer variable to point at a local variable that does not exist anymore after the function has returned.
A good way to return a string from a function in a Windows program, is to return a std::wstring.
Try that.
Regarding LPTSTR and _TEXT, you only need this if you intend to support MFC in DLLs in Windows 9x. Is that the case? If not, just ditch that Microsoft silliness.
The code fixed according to above advice (off the cuff, untouched by compiler's hands):
auto connection_settings()
-> std::wstring
{
std::wstring url( 256, L'#' );
auto const n = GetPrivateProfileString( L"Connection", L"Url", L"", &url[0], url.size(), NameOfIniFile );
url.resize( n );
return url;
}
One nice property of this code is that it no longer modifies a global variable.

How to assign a filename with a pointer one?

I do have a function that I have created with a pointer as an argument.
That argument will be used to save at the end an image.
Every time when I would like to call that function with the desired parameter, I want that the saved image file would be with the specified name. I show you how:
void SaveImage(IplImage *img)
{
...
cvSaveImage("C:/img.png", img);
...
}
when calling the function: SaveImage(image1), I want to have an image on my C:/ whose name is image.png
Can you help me with that?
Apparently, you can't answer this question with the only answer that is actually viable, because you get downvoted...
So, I'll rephrase my answer:
You need to pass two variables to SaveImage:
void SaveImage(const char *name, IplImage *img)
{
...
cvSameImage(name, img);
}
Then your calling code will have to produce the correct name, such as:
SaveImage("c:\image.png", image);
SaveImage("c:\other.png", other);
Now, of course, if all you actually want is a unique name, rather than one that reflects the name of the variable in your code, then there are plenty of other possibilities, such as using a formatted string that contains a serial number, a random number, tmpnam() or other similar schemes.

storing to a map inside a function

I'm trying to write a function that will input information into a map from a text file. My main code goes as follows:
int main(){
typedef map<int,student*> record;
record allstudents;
fileinput("inputtest.txt",allstudents);
//rest of code....
}
where the function 'fileinput' is defined as:
void fileinput(string datafile, record map){
fstream file1(datafile);
if(!file1.good()){
//error code
}
//Pulls information from file
student* S1= new physics(name,ID); //creates a new pointer
//(*S1).printinfo(); //Can print info if required for de-bug
map[ID]=S1; //store to map
entries++; //counts entries read in
}
cout<<"Import complete. "<<entries<<" new students entered."<<endl;
}
When I run this piece of code from a test file, it will read in the data and output it fine if I uncomment (*S1).printinfo(); and will correctly count the number of students that have been read in. However when I come back to my main function and output what is now stored in allstudents there appears to be nothing there?
Why is this occurring and does anybody know the way around this problem? I've cut a lot of code out to try and make it easier to read but if you need to see the rest I can always edit this.
Thanks.
This is because you are passing in map by value. Change the signature of the function to
void fileinput(string datafile, record &map)
Short explanation: when you pass by value, a copy of the argument (map) is made. Inside your function you perform modifications to that copy, but these modifications are lost when the function returns and the copy goes out of scope. They do not automatically propagate back to the "source" object.
For a detailed explanation, see Pass by Reference / Value in C++.
You are passing the map by value, so the function makes it's own copy and your original remains unchanged. Try passing by reference:
void fileinput(string datafile, record& map) { ... }
^ reference!

.wav Player : mmioOpen API

I am trying to make an audio player that plays .wav files. I wrote a function ReadWaveFile(CString szFilename) for reading the wave data of the file into the WAVEHDR structure. In this function
BOOL CWavePlay::ReadWaveFile(CString szFilename)
{
hmmio = mmioOpen((LPTSTR)&szFilename,NULL,MMIO_READ);
ASSERT(hmmio); //error here: hmmio=0x00000000
if(hmmio==0)
return FALSE;
....
}
mmioOpen is always returning 0 whenever I pass a filepath to this function for opening the specified file. And what baffles me is when i pass the filepath explicitly in mmioOpen API the code works; i.e., a valid handle is returned.
can some body explain why is this happening??
What will happen when you say
MessageBox(NULL,(LPTSTR)&szFilename,"Foo",MB_ICONINFORMATION);
When passing strings to system functions you will need to pick up the pointer to the raw string. For example, if you want to use an std::string object to build your path you will need to say
mmioOpen(filename.c_str(),NULL,MMIO_READ);
Your cast assumes from CString* to LPTSTR assumes that a CString is binary compatible with a LPTSRT which is not the case. When you write LPCTSTR on szFilename you will invoke a cast operator defined on CStrings that converts it to apropriate format. Did you tried just
hmmio = mmioOpen((LPCTSTR)szFilename,NULL,MMIO_READ);
The last cast does not do anything real here so it should be enough.

Why does the original CString get overwritten when passing a copy to the DrawText function with the DT_MODIFYSTRING option?

I've already found a workaround to this problem, but was just wondering if anyone knew what was actually happening to cause the problem I was seeing. My guess is that it has something to do with mutability of strings, but I thought the CString object accounted for that in the copy constructor.
The following code causes mFileName to be overwritten:
class File {
public:
...
CString GetFilename() {return mFileName;}
private:
CString mFileName;
};
class FileContainer {
private: File* mFile;
public:
FileContainer() {
mFile = new File("C:\temp.txt");
}
GetFilename(CString& fileName) {
fileName = mFile->GetFileName();
}
}
void UpdateText() {
FileContainer fileCnt;
CString filePath(L"");
this->fileCnt.GetFilename(filePath);
...
::DrawText(hDC, filePath, -1, &destRect, DT_PATH_ELLIPSIS | DT_MODIFYSTRING | DT_CALCRECT);
}
What happens is that the first time UpdateText is called, GetFilename returns C:\temp.txt. Assuming that the bounding rect caused the text to be truncated to "...\temp.txt" on the first call, "...\temp.txt" is what is returned from GetFilename on the second call to UpdateText.
Even more perplexing is that this didn't cause mFileName to be changed:
void UpdateText() {
FileContainer fileCnt;
CString filePath(L"");
this->fileCnt->GetFilename(filePath);
filePath = L"TEST";
}
GetFilename always returned C:\temp.txt. So it would seem that the DrawText function is somehow finding the original CString and modifying it. But how?
UPDATE: I figured I'd throw another odd chunk of code that also causes mFileName to be overwritten:
class File {
public:
...
CString GetFilename() {return CString(mFileName);}
private:
CString mFileName;
};
That seems like it should create a new object and return that new object. Yet, somehow, DrawText still overwrites mFileName.
If I change the code to the following, I don't have any issues:
class File {
public:
...
CString GetFilename() {return CString(mFileName.GetBuffer());}
private:
CString mFileName;
};
The only thing that seems to solve the problem is to construct a new CString the way I showed in the workaround. What is DrawText doing when I pass the DT_MODIFYSTRING option?
First, note that CString can be used as a raw string pointer in two ways:
operator LPCSTR - gives a pointer which should never be modified.
GetBuffer - gives a pointer to memory specifically for the purpose of modifying the string.
Now, DrawText is declared to accept a LPCSTR. So when you pass a CString object directly as in your code, it implicitly uses operator LPCSTR to give the function what it says it wants, a constant string pointer.
However, DT_MODIFYSTRING says that DrawText can modify the string it was given. So internally, DrawText must be throwing away the constness of the pointer and modifying the string anyway.
This combination is a bad thing. But the fault is mainly in the implmentation of DrawText which is violating its own declaration.
As for why this modifies other CString objects: Apparently when a CString object is copied, it delays copying the internal string memory until something tries to modify the string through a CString member function. But until that happens, the operator LPCSTR of each CString object would still point to the same shared internal memory. This is normally fine, as long as any code using it is obeying the rules of const-correctness. However, as we've already seen, DrawText with DT_MODIFYSTRING is not playing by the rules. Thus, it is overwriting memory shared by multiple CString objects.
So to fix this problem, you either need to stop using DT_MODIFYSTRING if you don't actually need the modified text. Or else you need to pass the string to DrawText using filePath.GetBuffer() and then call filePath.ReleaseBuffer() afterwards.
Well there are some discrepancies in the code that you posted:
In 'class File':
GetFileName() {return mFileName;}
There is no return type here? Also in the FileContainer class you define the stored 'File' object as a pointer, but in the GetFileName function you access it as if it was not a pointer?
File* mFile;
...
mFile.GetFileName();
As far as why this is happening well right now I can't really tell. Another work around however would be to change the GetFileName function to return a const ref, this should ensure that the returned value can never be changed.
const CString& GetFileName() { return mFileName; }