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();
}
Related
I have a lot of CDialogEx derived classes that do something like this in OnInitDialog:
CMeetingScheduleAssistantApp::InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
CMeetingScheduleAssistantApp::RestoreWindowPosition(_T("PublisherDB"), this, true);
Then, I have the following added to each derived dialog class:
int CPublishersDatabaseDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CPublishersDatabaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CPublishersDatabaseDlg::OnClose()
{
CMeetingScheduleAssistantApp::SaveWindowPosition(_T("PublisherDB"), this);
CDialogEx::OnClose();
}
The only thing that is different for each dialog is the phrase that is used for saving the window position.
I want to have a based CDialogEx class that I can inherit from that will perform the above actions. I have looked on SO and seem some questions and creating a CDialog class and inheriting from another CDialog class. But this class I want to create is more generic. Effectively to be used as a base instead of CDialogEx.
Can this be done? Am I over-complicating this?
Problems
Why I try to create a new class, derived from CDialogEx:
I don't know if it is because it requires a dialog ID as stated here.
Classes such as CDialog, CFormView, or CPropertyPage, which require a dialog ID.
So I can't work out the correct way to create a base CDialogEx class for use in all my other dialog classes.
Update
I created this code and it tells me that CResizingDialog is not a class or a namespace:
#include "ResizingDialog.h"
#include "resource.h"
#include "stdafx.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent = nullptr)
: m_strWindowID(strWindowID), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
Based on the comments encouraging me to try to create the class manually, I have it working:
#include "stdafx.h"
#include "resource.h"
#include "ResizingDialog.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent /* nullptr */, bool bOnlyStorePosition /* false */)
: m_strWindowID(strWindowID),
m_bOnlyStorePosition(bOnlyStorePosition), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
void CResizingDialog::OnOK()
{
SaveWindowPosition();
CDialogEx::OnOK();
}
BOOL CResizingDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
if(!m_bOnlyStorePosition)
InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
RestoreWindowPosition(m_strWindowID, this, true);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
I decided to duplicate the methods that were in the app class into this new dialog class instead. Eventually they can be removed from the app class. The only thing I also had to do was #include my resource file because the image needs to know the value of the resource ID.
This is the ResizingDialog.h header:
#pragma once
#include <afxwin.h>
class CResizingDialog : public CDialogEx
{
DECLARE_DYNAMIC(CResizingDialog)
public:
CResizingDialog(const CString& phrase, UINT nIDTemplate, CWnd* pParent = nullptr, bool bOnlyStorePosition = false); // Constructor
virtual ~CResizingDialog(); // Destructor
protected:
void OnOK() override;
virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
void SaveWindowPosition(void) { SaveWindowPosition(m_strWindowID, this); }
public:
BOOL OnInitDialog() override;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnClose();
DECLARE_MESSAGE_MAP()
private:
CBitmap m_bmpResize;
CStatic m_lblResize;
CRect m_rcInit;
CString m_strWindowID;
bool m_bOnlyStorePosition;
void RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState = false);
void SaveWindowPosition(CString strWindow, CWnd* pWindow);
void InitialiseResizeIcon(CBitmap& rBmpResize, CStatic& rLblResize, CWnd* pDialog);
};
The actual functions SaveWindowPosition, RestoreWindowPosition and InitialiseResizeIcon are not shown here as they don't directly relate to the issue.
In my application I have a QDialog which itself contains a complex, QWidget-derived GUI element. The QDialog is modal and opened with exec() and the embedded GUI element handles all user interactions.
So only this child QWidget knows when the QDialog can be closed, which is done this way:
QDialog* parent=qobject_cast<QDialog*>(parentWidget());
if (parent) parent->close();
This is necessary because the QDialog has to be closed and not only the QWidget.
Now a user reported a situation where QDialog::exec() has returned but where the dialog (or only the GUI element?) was still visible. From the log files I can see QDialog::exec() really has returned and the code right after this call was executed.
So my current assumption: the GUI element has lost its parent so that the close() call shown above was not called because "parent" was null.
Any idea how this can happen? Is there a regular way where the parent of a QWidget can disappear?
Generally speaking, using QDialog::exec to reenter the event loop will cause trouble, because suddenly all the code that runs in the main thread must be reentrant. Most likely you're facing fallout from that. Don't reenter the event loop, and you'll be fine or the problem will become reproducible.
If you need to react to the dialog being accepted or rejected, connect code to the relevant slots. I.e. change this:
void do() {
MyDialog dialog{this};
auto rc = dialog.exec();
qDebug() << "dialog returned" << rc;
}
to that:
class Foo : public QWidget {
MyDialog dialog{this};
...
Foo() {
connect(&dialog, &QDialog::done, this, &Foo::dialogDone);
}
void do() {
dialog.show();
}
void dialogDone(int rc) {
qDebug() << "dialog returned" << rc;
}
};
or, if you want to lazily initialize the dialog:
class Foo : public QWidget {
MyDialog * m_dialog = nullptr;
MyDialog * dialog() {
if (! m_dialog) {
m_dialog = new MyDialog{this};
connect(m_dialog, &QDialog::done, this, &Foo::dialogDone);
}
return m_dialog;
}
...
void do() {
dialog()->show();
}
void dialogDone(int rc) {
qDebug() << "dialog returned" << rc;
}
};
It is a horrible antipattern for the child widget to attempt to meddle with the parent. The knowledge that the widget has a parent should not leak into the widget, it should be localized to the parent. Thus, the child widget should emit a signal that indicates that e.g. the data was accepted. When you create the dialog, connect this signal to the dialog's accept() or close() slots:
class MyWidget : public QWidget {
Q_OBJECT
public:
Q_SIGNAL void isDone();
...
};
class MyDialog : public QDialog {
QGridLayout layout{this};
MyWidget widget;
public:
MyDialog() {
layout.addWidget(&widget, 0, 0);
connect(&widget, &MyWidget::isDone, this, &QDialog::accepted);
}
};
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've been searching a lot and I still can't find a good example of how to have multiple windows inside the same application with GTK. My program is in C++ but I don't mind an example in C which would help me understand the principle anyway.
So, the basic idea is to create my own derived object from Gtk::Window as opposed to Gtk::Dialog. Dialog has a run method which works flawlessly to open a modal popup window, but it's not flexible enough for what I'm trying to do. Does anyone know how I'd go about spawning a new window when I click a button in my program?
For example:
void MainWindow::on_button_clicked()
{
NewWindow window;
//Some code to display that window and stay in a loop until told to return
}
Where NewWindow is derived from Gtk::Window as such:
class NewWindow : public Gtk::Window
{
//Normal stuff goes here
}
Anything will help...I'm really confused here!
Another way to have a new window is to create a pointer to a Gtk window variable(Gtk::Window* about_window_;) then set the Gtk window variable to a new instance of the other window (about_window_ = new Window;), after that show the new window (about_window_->show();). Below is a full example of this:
class AboutWindow : public Gtk::Window
{
public:
AboutWindow();
~AboutWindow();
protected:
Gtk::Label lbl_;
};
AboutWindow::AboutWindow()
{
this->set_default_size(100, 100);
this->set_title("About");
lbl_.set_label("About label");
this->add(lbl_);
this->show_all_children();
}
AboutWindow::~AboutWindow()
{
}
class MainWindow : public Gtk::Window
{
public:
MainWindow();
virtual ~MainWindow();
protected:
void onButtonClicked();
void aboutWinClose();
Gtk::Button button_;
Gtk::Label lbl_;
Gtk::Box box_;
Gtk::AboutWindow* aboutw_;
};
MainWindow::MainWindow()
{
this->set_default_size(100, 100);
box_.set_orientation(Gtk::ORIENTATION_VERTICAL);
this->add(box_);
box_.pack_start(lbl_);
lbl_.set_label("a test");
button_.set_label("Open About Window");
box_.pack_end(button_);
button_.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::onButtonClicked));
aboutw_ = 0;
this->show_all_children();
}
MainWindow::~MainWindow()
{
}
void MainWindow::onButtonClicked()
{
if(aboutw_ != 0)
return;
aboutw_ = new AboutWindow;
aboutw_->signal_hide().connect(sigc::mem_fun(*this, &MainWindow::aboutWinClose));
aboutw_->show();
}
void MainWindow::aboutWinClose()
{
aboutw_ = 0;
}
Added for reference.
If you don't want the new window to be modal, then simply create it, show() it, and return from your main window's method without entering a loop.
I have an MFC view, and I have another project which implements and MFC dialog.
I want to host the dialog in my view.
My view is of class CFormView.
I did it that way in my view code:
m_myDialog->Create(myDialog::IDD, this);
Now, I see my dialog, but I can't set focus on it and can't use it.
What do I have to change in order to host my dialog in my view, and be able to use it and set focus to it, just as part of the view?
Thanks
I know this is a few weeks old, but you need to provide more code or a better context of what is taking place.
I had a similar problem to yourself & found this hard to find info on when I first tried this. Following is an abstract of something I've used. I'm sure there's probably a better way to do this, but I find it works the way I want;
//MyApp.h
class MyDialogClass;
class MyApp : public CWinAppEx
{
public:
MyApp();
virtual BOOL InitInstance();
//code etc
MyDialogClass *p_myDlg;
};
//MyApp.cpp
#include "MyApp.h"
#include "CMyView.h"
#include "mydialogclass.h"
BOOL MyApp::InitInstance()
{
//code etc
p_myDlg = CMyView::GetView()->p_myDlg;
//can be used here or elsewhere. I have mine linked with a button
p_myDlg->ShowWindow(true);
};
//CMyView.h
class MyDialogClass;
class CMyView : public CFormView
{
protected: // create from serialization only
CMyView();
DECLARE_DYNCREATE(CMyView)
public:
enum{ IDD = IDD_CMyView_VIEW };
static CMyView* GetView();
MyDialogClass *p_myDlg;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};
//CMyView.cpp
#include "MyApp.h"
#include "CMyView.h"
#include "mydialogclass.h"
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
p_myDlg = new MyDialogClass(this);
return 0;
}
void CMyView::DisplayDialogFoo()
{
//can be used here or elsewhere. I have mine linked with a button
p_myDlg->ShowWindow(true);
}
//mydialogclass.h
class MyDialogClass : public CDialog
{
DECLARE_DYNAMIC(MyDialogClass)
public:
MyDialogClass(CWnd* pParent /*= NULL*/);
enum { IDD = IDD_MyDialog_DLG };
};
//mydialogclass.cpp
#include "mydialogclass.h"
MyDialogClass::MyDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(MyDialogClass::IDD, pParent)
{
Create(IDD, pParent);
}
There's also an article here I just found:
http://www.codeproject.com/Articles/1651/Tutorial-Modeless-Dialogs-with-MFC