I'm currently working on a program (for fun, this is not an assignment) that has multiple functions. I have never used Win32 prior to yesterday and so I am rather new. I used TheForger's tutorials to get started. Right now, I have a dialog form with four edit boxes on it, charge1, charge2, charge3, and distance between particles. I am getting this information and plugging it into the formula to solve for the amount of force between the particles.
When I get to the part where I am getting the data from the edit box, I am receiving 0.
Here is my current code:
case ID_SOLVE:
{
ZeroMemory(coulombDisplay, sizeof(coulombDisplay));
GetDlgItemText(g_hCoulombs, IDC_DISTANCE, value1, 10);
coulombsDistance = atof(value1);
GetDlgItemText(g_hCoulombs, IDC_CHARGE1, value2, 10);
coulombsStrength1Base = atof(value2);
GetDlgItemText(g_hCoulombs, IDC_CHARGE2, value3, 10);
coulombsStrength2Base = atof(value3);
if(coulombsDistance == 0.0)
{
MessageBox(NULL, "WHAT", "WHAT", MB_OK | MB_ICONEXCLAMATION);
DestroyWindow(g_hCoulombs);
}
coulombsResult = (coulombsStrength1Base * coulombsStrength2Base);
coulombsResult /= (pow(coulombsDistance, 2));
coulombsResult *= kConstant;
sprintf(coulombDisplay, "%g", coulombsResult);
SendDlgItemMessage(g_hCoulombs, IDC_FORCE, WM_SETTEXT, 0, (LPARAM)(LPCSTR)coulombDisplay);
}
break;
value1, value2, value3, and coulombDisplay are all char[] that have been zero'd
coulombsResult, coulombsDistance, coulombsStrength1Base, coulombsStrength2Base are all doubles
The MessageBox stating "WHAT" is popping up each and every time that I run the program. I am using the multi-byte character set of VC++ 2010.
Any help would be greatly appreciated.
STATUS_ACCESS_DENIED has a good point. If you look at the documentation for atof you'll see that a error condition will result in 0.0 being returned. I'd recommend writing to a log file or something to see what the data is going into the atof function. I'm wondering if your allocated char buffer is big enough.
Try GetDlgItemTextA instead of GetDlgItemText to make sure you're getting back 8-bit characters and not 16-bit characters. A 16-bit character will usually have a zero in the upper half, and will be interpreted as an empty 8-bit string.
Related
name of this topic is probably incorrect, but I haven't idea how to name this issue.
Something about background, I am programming one game, which 3d surface is divided to chunks. I thought out a saving mechanism, in which all chunk objects with their properties are saved in compressed form to unordered map, which is then serialized to file, so parts of world can be loaded and saved effectively regarding current needs.
Of course, when loading, file is loaded, deserialized to unordered map and strings are converted to chunks objects in real time.
That is a plann, but with hard problems with realization.
I tried all possible searches, but without result. during my play with tests, I wrote a small test script like this:
#include <iostream>
#include <fstream>
#include <sstream>
int main()
{
std::ifstream reader("output.dat", std::ios::binary);
std::string data;
reader>>data;
reader.close();
std::cout<<data.size()<<std::endl;
std::stringstream ss;
ss.str(data);
unsigned char id_prefix=0, zone_prefix=1;
while (ss.peek()!=EOF)
{
unsigned char type;
ss>>type;
if (type==id_prefix)
{
unsigned char tempx, tempy, tempz;
unsigned short tempid;
if (!(ss>>tempx)) std::cout<<"reading of x failed."<<std::endl;
if (!(ss>>tempy)) std::cout<<"Reading of y failed"<<std::endl;
if (!(ss>>tempz)) std::cout<<"Reading of z failed."<<std::endl;
if (!(ss>>tempid)) std::cout<<"Reading of id failed, position is "+std::to_string(ss.tellg())+", values are "+std::to_string(type)+" "+std::to_string(tempx)+" "+std::to_string(tempy)+" "+std::to_string(tempz)<<std::endl;
std::cout<<(int)tempx<<" "<<(int)tempy<<" "<<(int)tempz<<" "<<(int)tempid<<std::endl;
}
else if (type==zone_prefix)
{
unsigned char tempx, tempy, tempz;
unsigned int tempzone;
ss>>tempx;
ss>>tempy;
ss>>tempz;
ss>>tempzone;
std::cout<<(int)tempx<<" "<<(int)tempy<<" "<<(int)tempz<<" "<<(int)tempzone<<std::endl;
}
}
}
Output.dat is a file with one experimental decompressed chunk to reproduce parsing process in the game.
You can download it from:
https://www.dropbox.com/s/mljsb0t6gvfedc5/output.dat?dl=1
if you want, it have about 160 kb in size. And here is a first problem.
It is probably only my stupidity, but I thought that when I use std::ios::binary to open ifstream, and then extract its content to string, it will load whole file, but it loaded only first 46 bytes.
That is first problem, next in the game, I used other system to load data which worked, but then stringstream processing as can be seen in lower part of code failed too around this position.
I guess there are problems also with data, as you can see, format is uchar type (indicates whether following bytes refer to id or zone), coordinates (each as uchar), and ushort in case of id, uint in case of zone.
But when I looked into the file with my own created binary editor, it showed id as one byte only, not two as I expected from short value. Saving was done also with stringstream, in form:
unsigned short tempid=3; //example value
ss<
and in result file this was represented as a 51 (in one byte), what is ascii code for 3, so I am little confused, or little more than little.
Can you please help me with this? I am using Mingw g++ 4.9.3 on win7 64-bit.
Thanks much!
Edit from 1.1.2017
Now whole file is read in stringstream, but extraction of values still fails.
When >> extraction reads to the next whitespace, how is it with extraction to unsigned short for example?
I was playing with code bit, trying to change for example unsigned short tempid to unsigned char tempid.
And output does not make sense to me.
In short version, bytes like:
0;1;0;0;51
were read as type 0, x 1, y 0, z 0 and id 3 what is correct, even I don't understand why 51 is here instead of a 3.
Writing to the stream before seemed as:
unsigned short idtowrite=3;
ss<<idtowrite;
But when I changed unsigned short tempid to unsigned char tempid, it read it as type 0, x 1, y 0, z 0 and id 51, what is not correct, but I expect it from writed file.
I wouldn't solve it if it read correctly through full stream, but for some reason until 0;8;0;0;51 all is correct, and from 0;9;0;0;51, which is next to it fails, with x readed as 0, y as 0 and z as 51 and EOF is set.
I am thinking if reading haven't missed a byte, but I don't see a reason to do it.
Can you please recommend me some effective and working way how to store values in stringstream?
Thanks in advance!
std::ios::binary only has the effect of suppressing end-of-line conversion (so that e.g. \r\n in file is not converted to just \n in memory). It is certainly correct to supply this when dealing with binary files.
However, >> is still a formatted input function, which skips leading whitespace, terminates at whitespace and so on.
If you want to actually read the file as binary data, you must use the read function on the stream object.
In visual studio 2015, When I am trying to write less than 4 characters in Rich Text Box, it gives exception (below is the attachment)
After doing Debugging, we came to know that Ensure() is causing the Exception:
int CRichEditCtrl::GetLine(_In_ int nIndex, _Out_writes_to_(nMaxLength, return) LPTSTR lpszBuffer, _In_ int nMaxLength) const
{
ASSERT(::IsWindow(m_hWnd));
ENSURE(sizeof(nMaxLength)<=nMaxLength*sizeof(TCHAR)&&nMaxLength>0);
*(LPINT)lpszBuffer = nMaxLength;
return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
}
When we are giving less that 4 characters in Rich Text Box,
sizeof(nMaxLength)<=nMaxLength*sizeof(TCHAR)
in this case sizeof(nMaxLength) = 4 and nMaxLength*sizeof(TCHAR) = 3
So, 3<4 is causing the Exception.
Now, I need help in which way Shall I give less than 4 charcters in a Rich Text Box, so that this function works and doesnt gives an Exception.
Sure it works.
This function GETs a line. You have to offer a buffer, large enough to fir the contents. The smallest buffer you are allowed to pass to the message is the size of an integer (4 bytes).
The size of the that you receive is returned by the function.
This code always work for any length
CString strTemp;
nMinLength = min(nLineLength,sizeof(int));
int iLen = m_ItemTextCtrl.GetLine(k, strtemp.GetBuffer(nMinLength), nLineLength);
strTetmp.ReleaseBuffer(iLen);
Passing data to the RTF control is done by streaming in data or using WM_SETTEXT or SetWindowText
Im using VS2008 for compiling and developing my application. Im required to take Adc input and serial print it through RS232 in a WinCE6 OS over some termianl like putty or hyperterminal. The problem is when I use the WriteFile function it gives me the following error.
Error 3 error C2440: '=' : cannot convert from 'double' to 'char [32]' c:\Users\Sohan\Downloads\uartdemo\uartdemo\src\main.c 137 Sohan_1
I want to take the input from ADC channel and then after converting it to voltage i have to transmitt. I have tried using a constant char string and it works but when i take the input from the channel and then try it doesnt work.
HANDLE portHandle;
DWORD noOfBytesRead = 0;
DWORD bytesTransmitted = 0;
DWORD firstChoice = 0;
BOOL retVal = FALSE;
char c="hello";
char transmit2Buffer[BUFFER_SIZE] = "7.8888v";
char volt[BUFFER_SIZE];
WriteFile(portHandle, transmit2Buffer, strlen(transmit2Buffer), &bytesTransmitted, NULL);
WriteFile(portHandle, volt, strlen(volt), &bytesTransmitted, NULL);
the first write function works but the second doesnt. variable volt will keep on changing so how should i write it.please help..
After searching i have got an answer for my question.
this worked for me..
You can use sprintf() as you have done to convert a double to a string, but I would actually recommend using _snprintf() instead simply because sprintf() has no regard for the fact that strings are fixed length devices in memory and will overflow if you don't watch it. _snprintf() allows you to specify the length of the out string, just be sure to specify the size as one less than the actual allocated memory block, because _snprintf() does not store the terminating null character if it has to cut the output short.
An example us using _snprintf() is:
void ToString(char * outStr, int length, double val)
{
_snprintf(outStr,length,"%f",val);
}
Got this answer on some website!!!
I am asking for information to save onto the database like their username and stuff, you can use up to 10 characters perfectly fine, the wstring holds it and I can use it how I like, but if a user were to type 11 characters it would all of a sudden say "Error reading characters of strings".
At first I thought I didn't have a big enough space for GetWindowText so I pumped that up, I didn't know if you can change the wstring capacity so that is why I am asking here.
Why is wstring only working with 10 or less characters? Thanks!
case WM_COMMAND: {
switch (LOWORD(wParam))
{
case IDB_REGISTERACCOUNT: {
std::wstringstream SQLStatementStream;
std::wstring SQLUsername;
std::wstring SQLPassword;
//Get user information than store in wide Strings
GetWindowText(hUserNameRegister, &SQLUsername[0], 50);
GetWindowText(hPasswordRegister, &SQLPassword[0], 50);
std::wstring SQLStatement = SQLStatementStream.str();
break;
}
}
break;
}
Your code is essentially saying, "I am giving you the address of the first character of this string, start writing to it indiscriminately." This is going to be a bad time. What you need to do is first allocate an actual buffer to use to store the result, then if you wanted in the wstring, you can use the wstring's '=' operator to do the proper assignment.
something like:
WCHAR temp[50];
GetWindowText(hUserNameRegister, temp, 50);
SQLUsername = temp
You write past the end of your string. This causes undefined behaviour.
Only use &x[0] on a standard library string when you are in read-only mode, or if you are writing but not going to change the length of the string.
You should have written:
wchar_t SQLUsername[50] = {};
GetWindowTextW(hUserNameRegister, SQLUsername, 50);
Then you can convert to wstring if you wanted with std::wstring wsSQLUsername = SQLUsername; - however your code never actually uses your wstrings before they go out of scope so perhaps you have some other misconceptions too.
The following piece of code seems to unreliably execute and after and undeterministic time it will fail with error code 234 at the RegEnumValue function.
I have not written this code, I am merely trying to debug it. I know there is an issue with doing RegEnumValue and then deleting keys in the while loop.
I am trying to figure out first, why it is throwing this 234 error at seemingly random points, as in, it is never after a consistent number of loop iterations or anything like that.
From what I have seen it fails to fill its name buffer, but this buffer is by no means too small for its purpose, so I don't understand how it could fail??
Could someone please advice on getting rid of this 234 error thrown by the RegEnumValue funciton?
HKEY key;
DWORD dw;
int idx;
char name[8192];
DWORD namesize=4096;
std::string m_path = "SOFTWARE\\Company\\Server 4.0";
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,m_path.c_str(),0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS)
{
bool error=false;
idx=0;
long result;
long delresult;
while (true)
{
result = RegEnumValue(key,idx,(char*)name,&namesize,NULL,NULL,NULL,NULL);
if (result == ERROR_SUCCESS && !error){
delresult = RegDeleteValue(key,name);
if (delresult != ERROR_SUCCESS)
error = true;
idx++;
}
else
{
break;
}
}
RegCloseKey(key);
}
There are some errors in your code:
The 4-th parameter of RegEnumValue (the namesize) is in-out parameter. So you have to reset namesize to sizeof(name)/sizeof(name[0]) (in case of the usage char type it is just sizeof(name)) inside the while loop before every call of RegEnumValue. It's the main error in your program.
If you don't want to have ERROR_MORE_DATA error any time you have the buffer having 32,767 characters. It is the maximum size of name the the regitry value (see documentation of RegEnumValue).
It is not good to use KEY_ALL_ACCESS in the RegOpenKeyEx. I'll recomend you to change it to KEY_QUERY_VALUE | KEY_SET_VALUE. It is not a real error, but depends on your environment it could be.
It if better to use UNICODE version of all this functions to speed-up a little the code.
UPDATED: Only small comment about the usage of the UNICODE version. Intern Windows work with UNICODE characters. So usage of non-Unicode version of RegEnumValue si more slow because at the evry call a new UICODE memeory block will be allocated and converted to ANSI/Multi-byte. Moreover if you will has a value name written in a language which can't be converted in you Windows ANSI code page (Chinese, Japanese and so on) and some characters will be replaced to '?' (see WC_DEFAULTCHAR flag of WideCharToMultiByte), then it can be that the function RegDeleteValue will fail with the error code like "the value with the name is not exist".
just change the value of your fourth parameter i.e namesize from 4096 to 8192 .Always MakeSure that it should be always equal to buffer size.
The answer is at the bottom of that page:
http://msdn.microsoft.com/en-us/library/ms724865(VS.85).aspx
Please read the answer of "ERROR_MORE_DATA: lpData too small, or lpValueName too small?" question.