test.h 中的类:
class CHelixV3Dlg : public CDialogEx
{
DECLARE_DYNAMIC(CHelixV3Dlg);
friend class CHelixV3DlgAutoProxy;
// Construction
public:
CHelixV3Dlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_HELIXV3_DIALOG };
// Implementation
protected:
CHelixV3DlgAutoProxy* m_pAutoProxy;
HICON m_hIcon;
public:
DWORD WINAPI loop(LPVOID); //thread identifier
void AppendText(CEdit &edit, LPCTSTR pszText);
};
我有一个这样定义的方法,它应该打印一个字符串到编辑框,它通常工作(在 test.cpp 中):
void TestDlg::AppendText(CEdit &edit, LPCWSTR pszText)
{
// get the initial text length
int nLength = edit.GetWindowTextLength();
// put the selection at the end of text
edit.SetSel(nLength, nLength);
// replace the selection
edit.ReplaceSel(pszText);
}
然后这是我的线程,它监听按键(test.cpp)
DWORD WINAPI TestDlg::KeyThread(LPVOID PARAMS)
{
TestDlg* Testdlg;
while (1)
{
Sleep(1);
if (GetAsyncKeyState(VK_F1) & 1)
{
Enabled = !Enabled;
if (Enabled) {
CEdit* log = (CEdit*)GetDlgItem(IDC_EDIT1);
log->AppendText(*log, "test"); //causes a crash
}
}
return 0;
}
对话框初始化,其中创建“循环”线程:
BOOL CHelixV3Dlg::OnInitDialog()
{
TestDlg* Testdlg;
CDialogEx::OnInitDialog();
//creates the thread->
CreateThread(NULL, NULL, &Testdlg->KeyThread, NULL, NULL, NULL);
/* IGNORE THIS */
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
所以,程序可以编译,但是当它运行并且我按 F1 时,它崩溃了。
最佳答案
您的代码中存在多个问题。未初始化的Testdlg
指针已经被别人指向了。
还有一个:
log->AppendText(*log, "test");
我确定你想说:
Testdlg->AppendText(*log, "test");
但是,那是行不通的,因为这是在工作线程上。您需要做的是从工作线程向主线程的队列(创建您的测试对话窗口)发布/发送消息。在消息的处理程序中,您实际上可以调用您的 AppendText
方法。
这是您的操作方法(请注意,我在浏览器中输入了所有这些内容,因此可能包含错误):
在 header (TestDlg.h) 中声明一个处理程序:
LRESULT OnMessageFromWorker(WPARAM wParam, LPARAM lPARAM);
在源文件(TestDlg.cpp)中:
定义您的信息:
#define MY_WORKER_THREAD_MSG WM_APP + 123
在消息映射中为消息添加条目
ON_MESSAGE(MY_WORKER_THREAD_MSG, &TestDlg::OnMessageFromWorker)
从工作线程发送消息:
DWORD WINAPI TestDlg::KeyThread(LPVOID PARAMS)
{
HWND dlgWnd = (HWND)PARAMS;
while (1)
{
Sleep(1);
if (GetAsyncKeyState(VK_F1) & 1)
{
Enabled = !Enabled;
if (Enabled)
{
CString* msg = new CString("test");
PostMessage(dlgWnd, 0, reinterpret_cast<LPARAM>(msg));
}
}
}
return 0;
}
请注意,在本例中,您需要传递对话框窗口的HWND
,而不是指向线程函数的this
指针。换句话说:
CreateThread(nullptr, nullptr, &Testdlg->KeyThread, this->GetSafeHwnd(), nullptr, nullptr);
处理消息:
LRESULT TestDlg::OnMessageFromWorker(WPARAM wParam, LPARAM lPARAM)
{
CString* msg = reinterpret_cast<CString*>(lPARAM);
CEdit* log = (CEdit*)TestDlg->GetDlgItem(IDC_EDIT1);
AppendText(*log, *msg);
delete msg; // you must delete the object
return 0;
}
关于C++ MFC Appeding text to edit control 崩溃程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30513935/