C++SendMessage循环停止并结束

C++ SendMessage loop stop and end of line

本文关键字:结束 循环 C++SendMessage      更新时间:2023-10-16

这是我的难题。我有一个程序,它使用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);
}

在VBAC++中,该结构将导致无限循环。

听起来您想要一个无限循环,但不想无限打印缓冲区的内容。

正如@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通常是不好的,可能会引起问题。