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