-
October 2nd, 2004, 01:51 PM
#1
MFC Thread: How to access UI elements from a thread in MFC?
Q: How to access UI elements from a thread in MFC?
A: Since the MFC is not thread-safe at object level (only at class level) one have to be careful when UI elements (like edit controls, listboxes etc.) should be accessed from inside the thread. The safest way is to pass a windows object handle and uses this inside the thread to post messages to the object.
The following sample shows this technique assuming that the created dialog contains a static text control named 'IDC_THREAD_TEXT'. The object handle of the dialog will be passed to the thread. Inside the thread this handle will be used to post ten messages to the dialog causing it to update the static control.
Code:
// 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;
}
Last edited by Andreas Masur; July 25th, 2005 at 12:43 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|