C++SendMessage循环停止并结束
C++ SendMessage loop stop and end of line
这是我的难题。我有一个程序,它使用SendMessage
从聊天程序中获取文本。现在,当我在Visual Basic中这样做时,我只是将SendMessage
放在一个循环中,每当聊天更新时,我的输出也会更新。
C++
的情况并非如此。当我把SendMessage
放在一个循环中时,它将永远循环。说聊天有点像:
苹果
香蕉
Cheerios
现在假设我运行程序,它会找到文本并开始循环。现在在Visual Basic中,它会一直循环,直到它达到Cheerios
,然后它会停止并等待,直到聊天中有人键入其他内容。
使用C++
,它将输出:
苹果
香蕉
干杯
苹果
香蕉
Cheerios
。。。
并一直走下去。有办法阻止这种情况吗?我一直在思考EOF
的术语,但这无济于事,因为一旦它到达最后一行,它就会脱离循环,不会拾取人们在聊天中键入的任何其他内容。
以下是获取文本的代码部分。现在并不是说我有一个循环,直到我将bLoop
设置为True
才会结束。
cout << " + found RichEdit20W window at: " << hwndRichEdit20W << endl << endl;
cout << "- get text " << endl;
bool bLoop = false;
int textLen = (int)SendMessage(hwndRichEdit20W, WM_GETTEXTLENGTH, 0, 0);
while (bLoop == false)
{
const int MAXSIZE = 32678;
wchar_t szBuf[MAXSIZE];
SendMessage(hwndRichEdit20W, WM_GETTEXT, (WPARAM)textLen, (LPARAM)szBuf);
wcout << szBuf;
}
谢谢你的帮助!
VB代码更新
这就是我在VB程序中的操作方法。这是一个游戏机,而不是聊天窗口,但它应该是相同的概念,对吧?
注意Do While PARENThwnd <> IntPtr.Zero
句柄从不为0,因此它将是一个无限循环。
Private Sub bwConsole_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwConsole.DoWork
Dim PARENThwnd As IntPtr
Dim CHILDhwnd As IntPtr
PARENThwnd = FindWindow(Nothing, "ET Console")
If PARENThwnd = IntPtr.Zero Then
txtConsole.Text = "ET Console is not availble."
Else
Do While PARENThwnd <> IntPtr.Zero
CHILDhwnd = GetDlgItem(PARENThwnd, 100)
Dim Handle As IntPtr = Marshal.AllocHGlobal(32767)
Dim NumText As Integer = CInt(SendMessage(CType(CHILDhwnd, IntPtr), WM_GETTEXT, CType(32767 Marshal.SystemDefaultCharSize, IntPtr), Handle))
Dim Text As String = Marshal.PtrToStringAuto(Handle)
txtConsole.Text = Text
Marshal.FreeHGlobal(Handle)
txtConsole.SelectionStart = txtConsole.TextLength
txtConsole.ScrollToCaret()
rtxtDefinition.Text = ""
Call GetDefinitions(txtConsole.Text)
Loop
End If
End Sub
也将无法回答任何问题,直到今晚晚些时候。去上班。
您从不更新bLoop
变量,导致循环无限运行。如果要中断循环,请实现一个循环终止条件,该条件将更改bLoop
的值。
压缩版本的代码执行以下操作:
bool bLoop = false;
while ( bLoop == false ) {
// This loop never terminates, unless bLoop is set to true
}
这有点难以理解,为什么你一开始就循环。我想您希望SendMessage
调用会以某种方式猜测,在满足某些条件之前,您不希望它运行。函数中没有这样的魔力。
要响应文本更改,您应该选择一个完全不同的解决方案:基于事件的模型。支持的实现方式是通过UI自动化。
您需要了解的第一件事是,这两个版本的代码对聊天窗口的内容所做的事情非常不同。VisualBasic版本将该文本放入一个文本控件中。这样做的效果是用聊天窗口中的新文本替换现有文本,这样你就不会看到重复的文本。C++版本每次检索文本时都会将文本输出到输出流(控制台)。与VB版本中使用的文本控件不同,输出流会附加文本而不是替换文本。
为了解决这个问题,你需要保留从聊天窗口检索到的先前文本的摘要,并且只输出差异。这可能意味着添加聊天中的新文本或输出整个字符串。下面的代码维护一个字符串缓冲区,并管理添加或替换聊天历史。它还创建了一个新的字符串,只包含与上次更改的差异,使您能够轻松处理更新。
class ChatHistory
{
std::wstring history;
public:
std::wstring update(const std::wstring& newText)
{
const std::wstring::size_type historySize = history.size();
if(newText.compare(0, historySize, history.c_str()) == 0)
{
history.append(newText.c_str() + historySize, newText.size() - historySize);
return history.c_str() + historySize;
}
else
{
history = newText;
}
return newText;
}
};
以下是使用它所需的代码更改。我还没有机会用你的确切设置来测试它,但它应该可以工作。
ChatHistory history;
while (bLoop == false)
{
const int MAXSIZE = 32678;
wchar_t szBuf[MAXSIZE];
SendMessage(hwndRichEdit20W, WM_GETTEXT, (WPARAM)textLen, (LPARAM)szBuf);
std::wcout << history.update(szBuf);
}
在VBA和C++中,该结构将导致无限循环。
听起来您想要一个无限循环,但不想无限打印缓冲区的内容。
正如@IInspectable所指出的(谢谢!)sendmessage将在循环的每次迭代中将聊天程序的内容复制到缓冲区中。
因此,清除聊天窗口或让程序知道哪些内容是新的,需要打印。
我现在正在使用linux操作系统,所以不能很容易地测试它。请让我知道以下是否有效。。。
#include <cwchar> // so we can use wcschr function
const int MAXSIZE = 32678; // moved outside of the loop
wchar_t szBuf[MAXSIZE]; // moved outside of the loop
szBuf[0] = L' '; // set sentinel (wide NULL!)
wchar_t* end_printed_message = szBuf;
//pointer to the end of the content that has been printed
while (bLoop == false)
{
SendMessage(hwndRichEdit20W, WM_GETTEXT, (WPARAM)textLen, (LPARAM)szBuf);
wchar_t* end_message_buffer = wcschr(szBuf, L' '); // find end of the string using wchar version of strchr()
if(end_printed_message != end_message_buffer){ // if the buffer contains something new
wcout << end_printed_message; // print out the new stuff (start at old end)
end_printed_message = end_message_buffer; // update the pointer to the end of the content
}
}
我不知道你已经包含了什么标题,因此使用了"ol忠实的<cstring>
">
顺便说一句(是的,我仍然会继续谈论这一点)混合使用(w)cout通常是不好的,可能会引起问题。
- 为什么在这个代码结束循环中没有得到结束
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- 使用 shared_ptr 在中断时结束多线程循环
- 如何使用循环结束 c++ 上的行
- 具有迭代器和自定义步长的循环结束条件
- 为什么这个 while 循环在下面的代码中没有结束?
- 为什么在使用不相关的宏时会阻止 while 循环结束?
- 为什么我的 while 循环永远不会在 C++ 中的数字猜测游戏中结束?
- while 循环 C++ 结束,但不继续到其余语句
- 当满足条件时,While循环未结束
- 使用分隔符结束用户输入的循环
- <= 和 == 运算符无法正常工作以结束循环
- C 如何结束一个段循环,该循环添加数字而不使用数字作为触发器来结束循环
- 如果其中一个为真,则 && 结束循环,而不是如果两者都为真
- 在 x 时间后结束循环的性能最低占用方式
- 如果用户对C++说,如何提前结束循环
- C++ 循环条件未结束循环
- 一旦用户错了两次,就结束循环
- EOF和GETCHAR结束循环
- 在sentinel使用条件语句结束循环后显示最大值