CRichEditCtrl::GetLine funtion is not working for Charaters < 4 - c++

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

Related

Pass PByte to a DLL from vb..net

I having troubles to calling a function inside a C DLL (dont know if C or C++)
Basically, I m trying to make a wrapper for the SDK DLL of Gigabyte RGB Fusion API.
I m working in VB.NET with Visual Studio 2013 (if you answer in C# is good too)
Declaring functions with DLLImport
for Ex. This function works fine.
C++
int dllexp_GetMaxDivision(void)
VB.NET
<DllImport("GLedApi.dll", SetLastError:=False, callingConvention:=CallingConvention.Cdecl)> _
Public Shared Function dllexp_GetMaxDivision() As UInt32
EndFunction
calling dllexp_GetMaxDivision works like a charm. The trouble starts when i pass parameters:
DWORD dllexp_GetLedLayout(PBYTE bytArray, int arySize)
Parameters
Name / Type / Description
bytArray / Output / Pointer to a buffer that receives the LED layout on motherboard. The values of the elements in the array are as follows:
Value Meaning
0(NA) No implement LED
1(A_LED) Analog LED
2(D_LED_TYPE1) Digital LED Type 1
3(D_LED_TYPE2) Digital LED Type 2
arySize / Input / Size, in byte of the buffer indicated by bytArray. This value must be a dllexp_GetMaxDivision return value.
DWORD dllexp_SetLedData(PBYTE bytArray, int arySize)
Parameters
Name / Type / Description
bytArray / Input / Pointer to a byte array converted from the LEDSETTING
structure array.
arySize / Input / Size, in bytes, of the buffer indicated by bytArray.
typedef struct _LEDSETTING {
BYTE Reserve0;
BYTE LedMode;
BYTE MaxBrightness;
BYTE MinBrightness;
DWORD dwColor;
WORD wTime0;
WORD wTime1;
WORD wTime2;
BYTE CtrlVal0;
BYTE CtrlVal1;
} LEDSETTING, *PLEDSETTING
This is what I try. I dont get to test with dllexp_SetLedData yet, so I will focus in dllexp_GetLedLayout
<DllImport("GLedApi.dll", setLastError:=False, CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function dllexp_GetLedLayout(ByRef bytArray As IntPtr, arySize As Int32) As UInt32
End Function
Tried with a byte array, but didn't work. And This:
Dim Param(iMaxDivs - 1) As Byte
For A As Integer = 0 To iMaxDivs - 1
Param(A) = CByte(0)
Next
Dim Tama As Integer = Marshal.SizeOf(Param(0)) * Param.Length
Dim buffer As IntPtr = Marshal.AllocHGlobal(Tama)
Marshal.Copy(Param, 0, buffer, Param.Length)
resp2 = GLed.dllexp_GetLedLayout(buffer, Param.Length)
Marshal.Copy(buffer, Param, 0, Param.Length) '<===== AccessViolationException
Marshal.FreeHGlobal(buffer)
The line of code that retrieve the buffer to the array throw an exception:
'System.AccessViolationException' en mscorlib.dll Attempted to read or
write protected memory. This is often an indication that other memory
is corrupt.
In some other tests, i had PinvokeImbalance sort of... , I guess it was a type mismatch.
The weird thing is that sometimes, the code doesnt throw an exception and proceed, but return the zero-filled array. even when the buffer contains data.
I also try with AllocCoTaskMem but the process crash...,
Can somebody please point me in the right way to do this??
Thanks!

Spurious '\r' added by CRichEditCtrl::GetLine() when called on single-character lines?

I tried using CRichEditCtrl::GetLine() to retrieve the text of a given line of a rich-edit control in an MFC application built with VS2015 in Unicode mode, and running on Windows 10.
I wrote this helper function:
CString GetLine(CRichEditCtrl& richEdit, const int lineNum)
{
int lineLength = richEdit.LineLength(richEdit.LineIndex(lineNum));
if (lineLength == 0)
{
// Empty line
return CString();
}
const int kMinBufferLength = sizeof(int) / sizeof(wchar_t);
const int bufferLength = max(kMinBufferLength, lineLength);
CString line;
wchar_t* buffer = line.GetBuffer(bufferLength);
lineLength = richEdit.GetLine(lineNum, buffer, bufferLength);
line.ReleaseBuffer(lineLength);
return line;
}
This code works fine, except for lines containing only one character. In this case, CRichEditCtrl::GetLine() returns 2 (instead of the expected 1), and the output buffer contains the correct character, followed by a \r.
Why is that? Why is the \r added only for single-character lines and not for lines containing more characters?
I was able to fix that adding a special case if like this:
// Code inserted after the richEdit.GetLine() call, before the line.ReleaseBuffer() call:
// *** Special Case ***
// It seems that when there's only one character (e.g. 'C') in the line,
// CRichEditCtrl::GetLine() returns 2, and appends a '\r' after
// the read character in the output buffer.
if ((lineLength == 2) && (buffer[1] == L'\r'))
{
// Chop off the spurious '\r'
lineLength = 1;
}
However, it's not clear to me the reason for this special-case behavior.
P.S: The CRichEditCtrl::GetLine() MFC code that is invoked is:
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);
}
So this seems just a tiny wrapper around the EM_GETLINE message.
The MSDN doc for EM_GETLINE states that "the return value is the number of TCHARs copied" (in my case, the wchar_ts). For one-character lines the return value is two, instead of the expected one. So, sounds like the rich-edit control is actually returning the single character followed by a spurious \r in this special case.
For lines containing more than one characters, the returned value is the actual number of characters, as expected (I tried with simple English/ASCII characters, to avoid complications of Unicode surrogate pairs and other stuff).
I got it to work without special-casing by using the other overload of CRichEditCtrl::GetLine():
*(int*) buffer = lineLength;
lineLength = richEdit.GetLine(lineNum, buffer);
The reference for EM_GETLINE says that you have to write the size of the buffer into the buffer, while this actually is the number of characters you request.
The reference for the macro Edit_GetLine() which sends EM_GETLINE has it correct:
cchMax The maximum number of characters to be copied to the buffer.
The macro writes the cchMax parameter to the buffer before calling SendMessage() which is exactly the same as my code above.
I also think that the condition in the 3-parameter overload of CRichEditCtrl::GetLine() which causes an exception if you request less than 2 characters, is incorrect.
The return value is zero (0) if the line is not valid.
If the line is empty it makes sense to return 1 and '\r' in the buffer. That would mean that '\r' is always returned when the line number is valid.
The function reference says that the buffer should be at least 4 bytes long, because a WORD is written to the buffer before being passed to SendMessage.
sizeof(nMaxLength) in the ENSURE function is the size of an int or WORD.
CRichEditCtrl::GetLine
CRichEditCtrl::GetLineCount has some code.

Visual Studio 2008 WriteFile

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!!!

Reading double from dialog edit control

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.

Registry problem - deleting key/values with C++

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.