C++ MFC Appeding text to edit control 崩溃程序

标签 c++ mfc

This is the disassembly of the program at runtime when exception occurs 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/

相关文章:

java - 如何检查我的 Java 程序是否在虚拟机中运行?

c++ - "drawed"这样的UI可以在MFC中完成吗

javascript - 如何使用 mfc/c++ 在 chrome 或 firefox 中注入(inject)脚本

c++ - 如何在MFC中捕获帧

c++ - 从工作线程访问对象

c++ - 维护最近的文件列表

c++ - 为每种参数类型重新定义相同模式的函数

c++ - 您如何获得进程运行了多长时间?

c++ - 在函数声明之后声明一个整数有什么用?

C++ 动态数据——如何获取它以及如何摆脱它