Problem in Next Line in Edit Box in Win32C++ - c++

I'm having a problem where in displaying my output. Whenever I display the output instead of having multiple lines of output i only got single line output.
Here is my Current code:
int TextLength = GetWindowTextLength(GetEditControl) + 1;
TCHAR Text[100000];
GetWindowText(GetEditControl, Text, TextLength);
if(TextLength > 1) {
vector <string> filelist;
string path;
path = Text;
path = stripPath(path);
filelist = GetPath(path);
stringstream buffer;
copy(filelist.begin()+1, filelist.end(),ostream_iterator<string>(buffer, "\n"));
SetWindowText(EditShow,buffer.str().c_str());
for(unsigned i=0;i<=99999;i++)
{
Text[i]='\0';
}
} else
{
MessageBox(NULL, "No Text", "Error", MB_OK | MB_ICONERROR);
}
this is the property of the Edit box
EditShow = CreateWindowEx(0, TEXT("Edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL ,
60, 70, 400, 150,
GetWindow, (HMENU)ID_EDITSHOW, NULL, 0);

Try specifying "\r\n" to separate the strings instead of just "\n".

Related

Create derived control at runtime cause assertion

I am trying to create a control at run-time, but it causes assertion, and I don't know what's causing it. The control I am using is the Tree ComboBox Control from this link: https://www.codeproject.com/Articles/187762/Tree-ComboBox-Control
I added the code to register the class as follow:
CTreeComboBox::CTreeComboBox()
...
{
...
RegisterWindowClass();
}
CTreeComboBox::~CTreeComboBox()
{
m_BrushAlert.DeleteObject();
}
BOOL CTreeComboBox::RegisterWindowClass()
{
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if (!(::GetClassInfo(hInst, _T("TreeComboBox"), &wndcls)))
{
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = _T("TreeComboBox");
if (!AfxRegisterClass(&wndcls))
{
AfxThrowResourceException();
return FALSE;
}
}
return TRUE;
}
I tried to create the control at run-time using the following code in the test program:
BOOL CTestComboBoxDlg::OnInitDialog()
{
...
m_ComboBox2.CreateEx(WS_EX_CLIENTEDGE, _T("TreeComboBox"), _T(""), WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
CRect(0, 0, 100, 50), this, 100000, NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
I also tried creating the control using a button click event thinking that I should let the GUI finish initializing, but the same error occur:
void CTestComboBoxDlg::OnBnClickedButton1()
{
m_ComboBox2.CreateEx(WS_EX_CLIENTEDGE, _T("TreeComboBox"), _T(""), WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
CRect(0, 0, 100, 50), this, 100000, NULL);
}
When I run the program, it stopped at the file dbgrptt.cpp at the following line:
__try
{
if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0)
{
/* use only 'safe' functions -- must not assert in here! */
_ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
OutputDebugStringA("Second Chance Assertion Failed: File ");
OutputDebugStringA(szFile ? szFile : "<file unknown>");
OutputDebugStringA(", Line ");
OutputDebugStringA(szLineMessage);
OutputDebugStringA("\n");
It stop here===> _CrtDbgBreak();
retval=-1;
__leave;
}
The program run fine if I create the control manually using the Visual Studio GUI editor, so I am not sure what's wrong. Can you help me figure out how to create this control at run-time?
Note: change the statement: TRACE1(_T("Item selected: %s\n"), GetItemText(hItem)); to TRACE(_T("Item selected: %s\n"), GetItemText(hItem)); in the file ComboTreeCtrlExt.cpp if you if you want to run the code and are using MFC
To answer my own question. Move the following code from the CTreeComboBox::PreSubclassWindow() to the CTreeComboBox::OnCreate()
CRect rect(0, 0, 0, 0);
DWORD dwStyle = WS_POPUP | WS_BORDER;
CWnd* pWnd = &m_Tree;
pWnd->CreateEx(0, WC_TREEVIEW, NULL, dwStyle, rect, GetParent(), 0, NULL);
m_Tree.Init(this);
GetClientRect(rect);
SetDroppedWidth(rect.Width());
SetDroppedHeight(m_nDroppedHeight);
dwStyle = CBS_DROPDOWNLIST & GetStyle();
ASSERT(CBS_DROPDOWNLIST == dwStyle);

C++ How to replace new lines when pasting a text to the Edit control?

I've got a simple chat program. I use "CreateWindow" function for the typing box:
chat_handle_11 = CreateWindow("EDIT", "", WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_EX_CONTROLPARENT, 226, 447, 424, 23, hWnd, NULL, NULL, NULL);
SendMessage(chat_handle_11, EM_LIMITTEXT, ChatTextLimitInBox, 0L);
When I paste any text containing new line characters (using the right mouse click or ctrl+v), for example:
Test line 1 text
Test line 2 text
Test line 3 text
Only the first line is pasted to the typing window:
Test line 1 text
I'd like to change the text on-paste, to ignore new line characters:
Test line 1 text Test line 2 text Test line 3 text
I tried to handle the WM_PASTE message, unfortunately it didn't work:
switch (message)
{
case WM_PASTE:
{
MessageBox(NULL, "pasting", "pasting", MB_YESNO | MB_ICONQUESTION);
break;
}
...
The MessageBox was never shown. Is WM_PASTE the correct message in this case?
Additionally, I tried to add "ES_MULTILINE" to the CreateWindow, but then, when I attempt to paste the text containing multiple lines, no text is pasted at all, I can only hear the "beep" sound.
I know I could remove new lines by detecting for clipboard changes and then overwrite it, but this solution would "invade" users clipboard, so I don't want to use it.
I would be very appreciate any help.
Thanks to #RbMm for help. I was able to fix the problem.
I didn't use the subclass for the Edit Control and I tried to handle the WM_PASTE message in the parent window.
Fixed code:
chat_handle_11 = CreateWindow("EDIT", "", WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_EX_CONTROLPARENT, 226, 447, 424, 23, hWnd, NULL, NULL, NULL);
SendMessage(chat_handle_11, EM_LIMITTEXT, ChatTextLimitInBox, 0L);
SetWindowSubclass(chat_handle_11, EditBoxForPasteFixes, 0, 0);
Then the new CALLBACK:
LRESULT CALLBACK EditBoxForPasteFixes(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR) {
switch (uMsg) {
case WM_PASTE:
{
try {
wstring ClipboardText = GetClipboardText();
find_and_replace_ws(ClipboardText, L"\r\n", L" ");
find_and_replace_ws(ClipboardText, L"\r", L" ");
find_and_replace_ws(ClipboardText, L"\n", L" ");
//We don't need to SETSEL, so we keep original position for pasting
//SendMessage(handle, EM_SETSEL, WPARAM(0), LPARAM(-1));
SendMessageW(handle, EM_REPLACESEL, WPARAM(TRUE), LPARAM(ClipboardText.c_str()));
}
catch (...) {
return FALSE;
}
return TRUE;
break;
}
/*case WM_LBUTTONDOWN:
//std::wcout << handle << L" click\n"; //click event works
break;*/
case WM_NCDESTROY:
{
RemoveWindowSubclass(handle, EditBoxForPasteFixes, 0);
// fall through
}
default:
{
return DefSubclassProc(handle, uMsg, wParam, lParam);
}
}
return 0;
}
And GetClipboardText function:
std::wstring GetClipboardText()
{
bool Failed = false;
std::wstring ReturnText = L"";
// Try opening the clipboard
if (!OpenClipboard(nullptr)) {
Failed = true;
}
// Get handle of clipboard object for ANSI text
if (!Failed) {
//HANDLE hData = GetClipboardData(CF_TEXT);
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == nullptr) {
Failed = true;
}
// Lock the handle to get the actual text pointer
if (!Failed) {
wchar_t * pszText = static_cast<wchar_t*>(GlobalLock(hData));
if (pszText == nullptr) {
Failed = true;
}
if (!Failed) {
std::wstring text(pszText);
ReturnText = text;
}
// Release the lock
GlobalUnlock(hData);
}
// Release the clipboard
CloseClipboard();
}
return ReturnText;
}
For find_and_replace_ws I use the boost function, but can be replaced by anything else:
void find_and_replace_ws(wstring& source, wstring const& find, wstring const& replace)
{
boost::replace_all(source, find, replace);
/*for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;)
{
source.replace(i, find.length(), replace);
i += replace.length() - find.length() + 1;
}*/
}
Not a perfect code, I know, but enough for my needs :)

MFC SDI Create button dynamically

I am trying to create a button dynamically. I have read some other resource and make the following code:
BEGIN_MESSAGE_MAP(Cdynamic_button_sdiView, CView)
// Standard printing commands
ON_BN_CLICKED(MYBUTTONID, OnMyBN_Click)
END_MESSAGE_MAP()
void Cdynamic_button_sdiView::OnInitialUpdate()
{
CView::OnInitialUpdate();
m_Button.Create(_T("Rearrange"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 128, 32), this, MYBUTTONID); // here will create a button
}
I can make a button successfully when I start the MFC application. The problem is that when I try to open a new document by clicking:
I get an error and my app crashed at m_Button.Create(_T("Rearrange"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 128, 32), this, MYBUTTONID);
I solved the problem with the following code:
Cdynamic_button_sdiView::Cdynamic_button_sdiView()
{
// TODO: add construction code here
m_Button = NULL;
}
Cdynamic_button_sdiView::~Cdynamic_button_sdiView()
{
if (m_Button != NULL)
delete m_Button;
}
void Cdynamic_button_sdiView::OnInitialUpdate()
{
CView::OnInitialUpdate();
if (m_Button != NULL)
delete m_Button;
m_Button = new CButton;
m_Button->Create(_T("Rearrange"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 128, 32), this, MYBUTTONID); // here will create a button
}
May be the problem is I should not re-create the window inside the OnInitialUpdate()

Getline with WinApi - Using WOFSTREAM / WIFSTREAM - C++ / WIN32

I am using Windows 10 (Visual Studio 2015).
Alright I just want to start off by saying is that I am using an edit box for the user to write a directory,appname,comboboxname then having wofstream output the directory,appname,comboboxname into a .txt file.
My problem is that some directories have spaces so when wifstream reads those spaces then cuts off the directory to early and stores the cut off version into one of the wchar_t variables.
What I need for the program to do (I am not sure if its possible) is output line by line.
Example:
C:\Program Files (x86)\Minecraft
MinecraftLauncher
Minecraft
Then use getline to read the whole line including the spaces, store that line into a variable and then get the next line. (But it also can't grab any extra white spaces that aren't in the directory otherwise it won't work) you guys probably know how directories work lol)
So you guys don't have to look that hard, I want this to occur in the case IDB_CLICK_ME.
Here is my code currently, something I am tinkering with before I decide to add it to my main application:
This is where I am trying to read the file (without whitespaces)
case WM_CREATE:
{
wchar_t testData[20] = L"Hai";
CreateWindow(L"button", L"CLICK ME", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 5, 5, 200, 25, hwnd, (HMENU)IDB_CLICK_ME, NULL, NULL);
comboBox = CreateWindow(L"combobox", L" ", WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST, 5, 50, 100, 100, hwnd, (HMENU)4, NULL, NULL);
hProgramName = CreateWindow(L"edit", L"Program Name", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 100, 200, 25, hwnd, NULL, NULL, NULL);
hProgramDirectory = CreateWindow(L"edit", L"Program Directory", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 130, 200, 25, hwnd, NULL, NULL, NULL);
hProgramNameComboBox = CreateWindow(L"edit", L"Name listed in ComboBox", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 160, 200, 25, hwnd, NULL, NULL, NULL);
std::wifstream myfile;
myfile.open("LaunchLocations.txt");
myfile >> std::noskipws >> gameLaunchtest.directory;
myfile >> std::noskipws >> gameLaunchtest.AppName;
myfile >> std::noskipws >> gameLaunchtest.ComboBoxName;
This is where I am writing it, so far this works correctly
ComboBox_AddString(comboBox, gameLaunchtest.directory);
break;
case WM_COMMAND:
switch (LOWORD(wparam))
{
case IDB_CLICK_ME:
GetWindowText(hProgramDirectory, gameLaunchtest.directory, MAX_PATH);
GetWindowText(hProgramName, gameLaunchtest.AppName, MAX_PATH);
GetWindowText(hProgramNameComboBox, gameLaunchtest.ComboBoxName, MAX_PATH);
wofstream launchLocations;
launchLocations.open("LaunchLocations.txt");
launchLocations << gameLaunchtest.directory << endl;
launchLocations << gameLaunchtest.AppName << endl;
launchLocations << gameLaunchtest.ComboBoxName << endl;
launchLocations.close();
So the way I fixed my problem (I was told by some very helper member that I must use the wifstream getline instead of the string getline)
std::wifstream myfile;
while (myfile.getline(test[number].directory, 100))
{
myfile.getline(test[number].AppName, 100);
myfile.getline(test[number].ComboBoxName, 100);
test[number].ID;
ComboBox_AddString(comboBox, test[number].ComboBoxName);
number++;
test[number].ID = test[number].ID + 1;

C++ why setWindowText doesn't display any text?

I have code as below, and my question is why in the cell A[0][0] setWindowText put nothing?
if(LOWORD( wParam ) == 104){
int td;
int td_width=80;
int tr = 0;
int tr_height=20;
for (tr=0;tr<2;tr++) {
for (td=0;td<10;td++) {
HWND A[tr][td];
A[tr][td] = CreateWindowEx( 0, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL,
td*td_width, tr*tr_height+50, td_width+1, tr_height+1, hwnd, NULL, hInstance, NULL );
}
SetWindowText(A[0][0], "MK" );
}
}
You're defining A[tr][td] inside the inner most loop. This restricts its scope to just that loop. In other words, on each iteration, you're creating a brand new array and assigning just one of its elements.
It's a little surprising that this even compiles. I guess you have another A array defined somewhere else, and that's the one you're referencing in the SetWindowText call.
As Peter said, you are declaring your array in the wrong spot. But more than that, you are also declaring the array as fixed-length but using run-time values to specify its bounds. That will not work, and should not even compile. A fixed-length array's bounds must be known at compile-time, not at run-time.
Try this instead:
if (LOWORD(wParam) == 104)
{
const int td_width = 80;
const int tr_height = 20;
HWND A[2][10];
for (int tr = 0; tr < 2; ++tr)
{
for (int td = 0; td < 10; ++td)
{
A[tr][td] = CreateWindowEx( 0, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, td*td_width, tr*tr_height+50, td_width+1, tr_height+1, hwnd, NULL, hInstance, NULL );
}
}
SetWindowText(A[0][0], TEXT("MK") );
}