samedi 9 mai 2015

MFC worker threads

So I successfully with my learning difficulties managed to make a few small MFC based apps, but now I am on to something harder I am having difficulties in understanding how to access edit controls inside a thread. Well, let me first say that I found a good example that with a bit of tinkering I managed to half get it to work right in my test application. The problem is, is that it now does not act like a thread, it hangs like it would outside of a thread.

My test app sends a message to another application every x seconds, in this case every 20. After 20 seconds it sends another message, then after 20 it says the first message again, and repeats every 20 seconds until the app is closed.

Here is the sample code I used to help me understand how to use threads, and also how to access MFC controls.

    // StdAfx.h
#define WM_UPDATE_CONTROL    WM_APP + 0x10

// MyDialog.h
class CMyDialog : public CDialog
{
public:
  CMyDialog(CWnd* pParent = NULL);

private:
  CWinThread *m_pThread;

  LRESULT OnUpdateControl(WPARAM wParam, LPARAM lParam);            
  static UINT ThreadFunc(LPVOID pvParam);
};

// MyDialog.cpp
CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/)
  : CDialog(CMyDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDialog)
//}}AFX_DATA_INIT

  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

  m_pThread = 0;
}

BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
  //{{AFX_MSG_MAP(CMyDialog)
  ON_WM_SYSCOMMAND()
  ON_WM_PAINT()
  ON_WM_QUERYDRAGICON()
  //}}AFX_MSG_MAP
  ON_MESSAGE(WM_UPDATE_CONTROL, OnUpdateControl)
END_MESSAGE_MAP()

BOOL CMyDialog::OnInitDialog()
{
  CDialog::OnInitDialog();
  //...

  // Set object handle for thread
  HWND *phObjectHandle = new HWND;

  *phObjectHandle = GetSafeHwnd();

  // Create thread
  m_pThread = AfxBeginThread(ThreadFunc, phObjectHandle);
  if(!m_pThread)
  {
    // Could not create thread
    EndDialog(IDCANCEL);
  }
  return TRUE;
}

LRESULT CMyDialog::OnUpdateControl(WPARAM wParam, LPARAM lParam)
{
  static int iCounter = 0;
  CString    strText;

  strText.Format("Message %d", ++iCounter);
  GetDlgItem(IDC_THREAD_TEXT)->SetWindowText(strText);

  return 0;
}

UINT CMyDialog::ThreadFunc(LPVOID pvParam)
{
  HWND *phObjectHandle = static_cast<HWND *>(pvParam);

  for(int iCnt = 0; iCnt < 10; ++iCnt)
  {
    ::PostMessage(*phObjectHandle, WM_UPDATE_CONTROL, 0, 0);
    ::Sleep(2000);
  }

  // Release memory
  delete phObjectHandle;

  return 0;
}

Without including all the other necessary code i.e stdax.h, here is the code that I am having problems with. I know it's terrible, but with my issused it's currently the best I can come up with.

LRESULT MyDlg::OnUpdateControl(WPARAM wParam, LPARAM lParam)
{
        CString    sWnd1;
        CString    sWnd2;
        HWND       hWnd;

        sWnd1.Format(_T("%p"), &hWnd);
        GetDlgItemText(IDC_APPWINDOW1, sWnd1);
        GetDlgItemText(IDC_APPWINDOW2, sWnd2);
        swscanf_s(sWnd1, _T("%p"), &hWnd);
        ::SendMessage(hWnd, WM_SETTEXT,0, (LPARAM)L"hello test");
        Sleep(20000);
        ::SendMessage(hWnd, WM_SETTEXT,0, (LPARAM)L"goodbye test");
        Sleep(20000);
        return 0;
}

UINT MyDlg::ThreadFunc(LPVOID pvParam)
{
        HWND *phObjectHandle = static_cast<HWND *>(pvParam);

        for(;;)
        {
            ::PostMessage(*phObjectHandle, WM_UPDATE_CONTROL, 0, 0);
        }

        delete phObjectHandle;

        return 0;
}

APPWINDOW1 and APPWINDOW2 are edit controls that I input the window handles from the other program 0x000000 etc, I plan to work on doing this automatically somehow instead of having to use winspy every time, but for now my only concern is the thread problem. Everything runs fine, except it hangs. In the unmodified code it runs perfectly, and as long as I try to send commands repeatedly to the same window or use Sleep(x) it's fine I think. I don't know it's giving me a headache. Any help would be greatly appreciated, and a small note is that I must in my little app access controls from a worker thread. The example above has been the only one I haven't had too much trouble understanding and getting to work.

Aucun commentaire:

Enregistrer un commentaire