Trying to append text to an edit control inside a dialog box. I can't get _tcscat_s to append correctly. It crashes and says something about the buffer being too small or something about a null terminated string.
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { return DialogBox( hInstance, MAKEINTRESOURCE( IDD_MAIN ), NULL, DlgProc ); } BOOL CALLBACK DlgProc( HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam ) { switch( Message ) { case WM_INITDIALOG: OpenAndReadFile( hwnd ); return TRUE; case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDSTART: EndDialog( hwnd, IDSTART ); break; case IDQUIT: EndDialog( hwnd, IDQUIT ); break; } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; default: return FALSE; } return TRUE; } BOOL OpenAndReadFile( const HWND &hwnd ) { // Open the file HANDLE hFile; hFile = CreateFile( TEXT( "sites.txt" ), // file to open GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // default security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL ); // no attr. template if ( hFile == INVALID_HANDLE_VALUE ) { SetDlgItemText( hwnd, IDC_OUTPUT, TEXT( "Error: File could not be opened\r\n" ) ); return FALSE; } else SetDlgItemText( hwnd, IDC_OUTPUT, TEXT( "sites.txt opened\r\n" ) ); AppendText( hwnd, TEXT("TEXT") ); // Read data from file const DWORD BUFFERSIZE = GetFileSize( hFile, NULL ); char *ReadBuffer = new char [BUFFERSIZE](); DWORD dwBytesRead = 0; // read one character less than the buffer size to save room for the // terminate NULL character. //if ( FALSE == ReadFile( hFile, ReadBuffer, BUFFERSIZE - 1, &dwBytesRead, NULL ) ) { } return TRUE; } void AppendText( const HWND &hwnd, TCHAR *newText ) { // get size to determine buffer size int outLength = GetWindowTextLength( GetDlgItem( hwnd, IDC_OUTPUT ) ); // create buffer to hold current text in edit control TCHAR * buf = ( TCHAR * ) GlobalAlloc( GPTR, outLength + 1 ); // get existing text from edit control and put into buffer GetDlgItemText( hwnd, IDC_OUTPUT, buf, outLength + 1 ); // append the newText to the buffer _tcscat_s( buf, outLength + 1, newText ); // Set the text in the dialog SetDlgItemText( hwnd, IDC_OUTPUT, buf ); }
解决方案
GetWindowTextLength() returns the number of TCHAR elements in the text, but GlobalAlloc() expects a byte count instead. If you are compiling for Unicode, TCHAR is 2 bytes, not 1 byte, but you are not taking that into account. You are also not allocating the buffer large enough to hold both the existing text and the new text being appended. You are also leaking the memory that you allocate.
Try this:
void AppendText( const HWND &hwnd, TCHAR *newText ) { // get edit control from dialog HWND hwndOutput = GetDlgItem( hwnd, IDC_OUTPUT ); // get new length to determine buffer size int outLength = GetWindowTextLength( hwndOutput ) + lstrlen(newText) + 1; // create buffer to hold current and new text TCHAR * buf = ( TCHAR * ) GlobalAlloc( GPTR, outLength * sizeof(TCHAR) ); if (!buf) return; // get existing text from edit control and put into buffer GetWindowText( hwndOutput, buf, outLength ); // append the newText to the buffer _tcscat_s( buf, outLength, newText ); // Set the text in the edit control SetWindowText( hwndOutput, buf ); // free the buffer GlobalFree( buf ); }
Alternatively:
#include <vector> void AppendText( const HWND &hwnd, TCHAR *newText ) { // get edit control from dialog HWND hwndOutput = GetDlgItem( hwnd, IDC_OUTPUT ); // get new length to determine buffer size int outLength = GetWindowTextLength( hwndOutput ) + lstrlen(newText) + 1; // create buffer to hold current and new text std::vector<TCHAR> buf( outLength ); TCHAR *pbuf = &buf[0]; // get existing text from edit control and put into buffer GetWindowText( hwndOutput, pbuf, outLength ); // append the newText to the buffer _tcscat_s( pbuf, outLength, newText ); // Set the text in the edit control SetWindowText( hwndOutput, pbuf ); }
With that said, getting the window's current text into memory, appending to it, and then replacing the window's text is a very inefficient way to append text to an edit control. Use the EM_REPLACESEL message instead:
void AppendText( const HWND &hwnd, TCHAR *newText )
{
// get edit control from dialog
HWND hwndOutput = GetDlgItem( hwnd, IDC_OUTPUT );
// get the current selection
DWORD StartPos, EndPos;
SendMessage( hwndOutput, EM_GETSEL, reinterpret_cast<WPARAM>(&StartPos), reinterpret_cast<WPARAM>(&EndPos) );
// move the caret to the end of the text
int outLength = GetWindowTextLength( hwndOutput );
SendMessage( hwndOutput, EM_SETSEL, outLength, outLength );
// insert the text at the new caret position
SendMessage( hwndOutput, EM_REPLACESEL, TRUE, reinterpret_cast<LPARAM>(newText) );
// restore the previous selection
SendMessage( hwndOutput, EM_SETSEL, StartPos, EndPos );
}