I have program that has status window on separate thread. I need to make status thread form update with new text information information. What is the best way of doing that?
Main thread creates status window:
void CMainWindow::OnPushButtonClicked ()
{
CWinThread* pThread= AfxBeginThread(RUNTIME_CLASS(CMySecondUIThreadClass) );
}
UI thread:
class CMySecondUIThreadClass : public CWinThread
{
DECLARE_DYNCREATE(CMySecondUIThreadClass)
protected:
CMySecondUIThreadClass();
virtual ~CMySecondUIThreadClass();
public:
CMainWindow * v1;
virtual BOOL InitInstance();
virtual int ExitInstance();
protected:
DECLARE_MESSAGE_MAP()
};
InitInstance of UI:
BOOL CMySecondUIThreadClass::InitInstance()
{
v1 = new CMainWindow;
v1->Inform("Thread"); //Procedure that updates vi dialog form controls with text information
m_pMainWnd=v1;
ShowWindow (m_pMainWnd->m_hWnd,SW_SHOW);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
Related
I have a Dialog on MFC application.
MyDialog :
{
int variable1;
int variable2;
Class1 cls = new Class1();
}
And in class1()
Class1()
{
void Function1()
void Function2()
}
--
So How to Access and return to variable1 in Class1::Function1()
Class1::Function1()
{
MyDialog dlg = new MyDialog ();
Get x = dlg->variable1; //if like this, variable1 alway=0, because in above line, i'm define new myDialog()
}
I think to delegate on .NET but in MFC application, I can't get it done ?
You can
"extend" your constructor, by adding a pointer to the parent in your child dialog and access your variable or call public functions (requires header of parent)
use SendMessage and handle the messages in your parent dialog
use GetParent in-place and dynamic_cast it to your parent dialog (requires header of parent)
1.
Class1::Class1(MyParent *parent)
{
m_parentPointer = parent;
}
void Class1::Function1(void)
{
m_parentPointer->myPublicVariable;
}
2.
void Class1::Function1(void)
{
CWnd *parent = GetParent();
if (parent)
parent->SendMessage(WM_YOUR_MESSAGE, yourWPARAM, yourLPARAM);
}
//MessageMap of parent
ON_MESSAGE(WM_YOUR_MESSAGE, ParentClassHandler)
LRESULT Parent::ParentClassHandler(WPARAM wp, LPARAM lp)
{
//Process
}
3.
void Class1::Function1(void)
{
CWnd *parent = GetParent();
if (parent)
{
Parent *p = dynamic_cast<Parent*>(parent);
if (p)
{
//Process
}
}
}
If Class1::Function1() needs to access the dialog, then you need a pointer to the dialog in Function1.
void Class1::Function1(MyDialog *dlg) {
}
If you want to store the dialog pointer permanently, then adjust the constructor of Class1.
class Class1 {
public:
Class1(class MyDialog *dlg_) : dlg(dlg_) {}
class MyDialog *dlg;
}
Another, probably better, way to implement it, is to move the code that needs to access Class1 and MyDialog into global functions or into MyDialog member functions. But which way to go depends on what the classes do and which design you want.
You have to start with basic C++ classes before diving in to this. But here is how it's done:
MyDialog dlg = new MyDialog ();
dlg->variable1 = 1; //set the variable
if (IDOK == dlg->DoModal()) //wait for user to click OK
{
int x = dlg->variable1; //get the variable
}
However, dlg->variable1 is not changed unless you drive your own class and do something to change it.
For example, you can use Dialog Data Exchange to assign variable1 to a check box.
void MyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Check(pDX, IDC_CHECK1, variable1);
}
To try it, use Visual Studio's dialog wizard to create a check box and an edit box. It will probably create check box with resource id IDC_CHECK1, an edit box with resource id set to IDC_EDIT1.
Another option:
use OnInitDialog to assign variable to dialog controls
use OnOK() to get variables from dialog controls:
:
BOOL MyDialog::OnInitDialog()
{
//put `CString m_string1;` in class declaration
BOOL result = CDialog::OnInitDialog();
SetDlgItemText(IDC_EDIT1, m_string1);
return result;
}
void MyDialog::OnOK()
{
GetDlgItemText(IDC_EDIT1, m_string1);
CDialog::OnOK();
}
Hi I have created a dialog box and it woks.
My question is: how do you retreive the handle for it?
Also, if you get the handle, how would you change the static text control text inside it?
class CStatisticsDlg : public CDialogEx
{
public:
CStatisticsDlg();
// Dialog Data
enum { IDD = IDD_STATISTICS };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
};
CStatisticsDlg::CStatisticsDlg() : CDialogEx(CStatisticsDlg::IDD)
{
}
void CStatisticsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CStatisticsDlg, CDialogEx)
END_MESSAGE_MAP()
Assuming you're using MFC (as indicated by the tag), then presumably you have a CDialog class instance. CDialog is a subclass of CWnd, so you can retrieve the window handle by one of 3 ways:
Directly accessing its m_hWnd member
Casting it to an HWND with operator HWND()
Calling GetSafeHwnd() on it
Here is how to do it.
First create a member function to the main application class.
Then use the following code (Assuming the class name is CGenericApp, and your Dialog class is CGenericDlg.
CWnd* CGenericApp::GetDlg()
{
return m_pMainWnd;
}
Then when you want to get a handler to the main Dialog box, use:
CGenericApp* app = (CGenericApp*)AfxGetApp();
CGenericDlg* pDlg = (CGenericDlg*)(app->GetDlg());
HWND win = pDlg->GetSafeHwnd();
'win' will hold the HWND you are looking for.
I'm trying to get the handle of a dialog box with this code:
class CStatisticsDlg : public CDialogEx
{
public:
CStatisticsDlg();
// Dialog Data
enum { IDD = IDD_STATISTICS };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
};
CStatisticsDlg::CStatisticsDlg() : CDialogEx(CStatisticsDlg::IDD)
{
}
void CStatisticsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
// DDX_Control(pDX, IDC_FUCK, m_fuck);
}
BEGIN_MESSAGE_MAP(CStatisticsDlg, CDialogEx)
END_MESSAGE_MAP()
But when I create an instance of the class with this:
CStatisticsDlg statisticsDlg;
and try to get its handle via statisticsDlg.m_hWnd, the handle is null.
Why this is the case? What is the best way to get the handle for a dialog box?
The first point during the creation process where you can get the m_hWnd is the dialog's OnInitDialog function. The m_hWnd does not exist before the DoModal call and does not exist after the DoModal returns.
try modalless dialog model .Use create function instead of domodal.m_hWnd does not exist before create call begins.
I have made a DLL with a function that opens a non-modal window.
class CMainFrame : public CFrameWnd
{
protected:
CMainFrame() {}
DECLARE_DYNCREATE(CMainFrame)
public:
virtual void PostNcDestroy()
{ AfxPostQuitMessage(0); }
public:
virtual ~CMainFrame() {}
};
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
class CDllApp : public CWinApp
{
public:
CDllApp() :
m_pDocTemplate(NULL)
{};
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
m_pDocTemplate = new CMultiDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(C3DGraphDoc),
RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(C3DGraphView));
return TRUE;
}
public:
CMultiDocTemplate* m_pDocTemplate;
};
CDllApp theApp;
class C3DThread : public CWinThread
{
DECLARE_DYNCREATE(C3DThread)
public:
virtual BOOL InitInstance()
{
theApp.m_pDocTemplate->OpenDocumentFile(NULL);
}
};
IMPLEMENT_DYNCREATE(C3DThread, CWinThread)
void __stdcall ExportedFunction()
{
AfxBeginThread(RUNTIME_CLASS(C3DThread));
}
If I close all windows before exiting main application, then all looks fine, otherwise my threads hang up. So, I think I need to clean up by closing all open documents and I wonder what would be the simplest way to do it gracefully. m_pDocTemplate->CloseAllDocuments() from theApp doesn't work, since frame windows for documents belong to different threads.
I am trying to get a context menu to work for a CListCtrl derived class. I just created a method OnContextMenu, but it isn't being called. What am I missing? I am using Visual Studio 2008, to create a CDialog based MFC application.
CustomList.h
class tcCustomListCtl : public CListCtl
{
DECLARE_DYNAMIC(tcCustomListCtl)
public:
tcCustomListCtl();
virtual ~tcCustomListCtl();
protected:
DECLARE_MESSAGE_MAP()
afx_msg void OnContextMenu(CWnd* pWnd,CPoint pos );
};
CustomList.cpp
// tcFaultListCtl
IMPLEMENT_DYNAMIC(tcCustomListCtl, CListCtrl)
tcCustomListCtl::tcCustomListCtl()
{
}
tcCustomListCtl::~tcCustomListCtl()
{
}
BEGIN_MESSAGE_MAP(tcCustomListCtl, CListCtrl)
END_MESSAGE_MAP()
// tcCustomListCtl message handlers
afx_msg void tcCustomListCtl::OnContextMenu(CWnd* pWnd,CPoint pos )
{
TRACE("tcCustomListCtl::OnContextMenu\n");
}
I found out I had to add ON_WM_CONTEXTMENU() to message map.