I create modal dialog like this :
CDialog dlg;
dlg.DoModal();
but when window opens I can access background windows of my program (move them and close them) but I need focus only on my curent window. (I think modal dialog shouldn't behave like this)
How can I do this?
EDIT:
It seems I found the reason of this behavior: before open my dialog,I open another modal dialog in CMyDlg::OnInitDialog() function, when I comment this,my dialog again became modal. But how to solve this problem?
Some code describing problem:
void CMyView::OnSomeButtonPress()
{
CMyDlg dlg;
dlg.DoModal();
}
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//some init here...
//new modal dialog here (if comment this CMyDlg works as modal)
CSettingsDlg dlg;
dlg.DoModal();
//...
}
you can solve your problem by specifying parent window for the dialog, you can do by passing this pointer in constructor of each dialog class as shown in code .
void CMyView::OnSomeButtonPress()
{
CMyDlg dlg(this);
dlg.DoModal();
}
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//some init here...
CSettingsDlg dlg(this);
dlg.DoModal();
//...
}
You cannot use a dialog from within the OnInitDialog method or from any function called from the OnInitDialog method. You have to use the DoModal() of CSettingsDlg from else where.
Something like this:
void CMyView::OnSomeButtonPress()
{
//new modal dialog here (if comment this CMyDlg works as modal)
CSettingsDlg dlgSettings;
dlgSettings.DoModal();
...
CMyDlg dlg;
dlg.DoModal();
}
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//some init here...
//...
}
Related
I have an Android application with a dialog and a few buttons inside.
I want to reuse the dialog for different purposes and looking for a way to call the button from a separate class and define an action event for it.
Creating a test class, I managed to define an action event for a button inside a form, but the same code does not work for a button inside a dialog, and I can't get my head around why it is not working for the dialog.
Below is what I already have. Any suggestions would be appreciated.
public Class One {
Test test = new Test();
test.testOne(); // this is working : button prints
test.testTwo(); // this is not working : button does not print
buttonTest = test.getTestButton();
buttonTest.setText("Hello World"); // not working for a button in a dialog
buttonTest.addActionListener(l-> { // prints when the button in a Form
System.out.println("try"); // does not print when the button is in a dialog
});
}
public class Test {
Dialog dialog = new Dialog();
Form form = new Form();
Button button;
public void testOne() {
button = new Button("Test");
form.add(button);
form.show();
}
public void testTwo() {
button = new Button("Testing");
dialog.add(button);
dialog.show();
}
public Button getTestButton () {
return button;
}
}
You add the action listener after showing the form and dialog. This isn't a problem for the form since the forms show method will continue. But a dialogs show() method will block.
Two solutions:
Move the listener binding higher in the code (before the show) that would be a problem since the button doesn't exist yet so you will need some refactoring.
Change the show() call on the dialog to showModless()
I have a checkbox and an edit control. I want to disable the Edit control when Check-box is 'not checked', and enable Edit control when Check-box is 'checked.
OnBnClickedCheck1 gets called when I check/uncheck the check-box. m_CHECK1_VARIABLE tells me if the check box is checked or un-checked. If-else part is executed correctly but m_TEXT1_CONTROL.EnableWindow(FALSE/TRUE) doesn't seem to work.
Below is the code.
void CPreparationDlg::OnBnClickedCheck1()
{
UpdateData(TRUE);
if (m_CHECK1_VARIABLE)
{
m_TEXT1_CONTROL.EnableWindow(TRUE);
}
else if (m_CHECK1_VARIABLE)
{
m_TEXT1_CONTROL.EnableWindow(FALSE);
}
}
There are 2 cases.
When Edit-box is disabled by default when dialog pops up.
If the Edit-box is enabled by default (I set 'Disabled' behavior in dialog properties to 'False'), Edit-box stays enabled throughout the operation. (check and uncheck operation on check-box)
When Edit-box is enabled by default when dialog pops up.
When I disable the Edit-box by default (I set 'Disabled' behavior in dialog properties to 'True'), Edit-box becomes enabled on 'first' 'check' on the Check-box but stays enabled throughout the rest of the operation. (check and uncheck operation on check-box).
What is it that I am missing here?
The following code example will implement the required logic.
Header file:
public:
int m_Check;
CEdit m_EditBox;
afx_msg void OnBnClickedCheck1();
Class implementation source:
CMfcApplicationDlg::CMfcApplicationDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMfcApplicationDlg::IDD, pParent)
, m_Check(0) // Default checkbox state
{
// ...
}
void CMfcApplicationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_EditBox);
DDX_Check(pDX, IDC_CHECK1, m_Check);
m_EditBox.EnableWindow(m_Check);
}
void CMfcApplicationDlg::OnBnClickedCheck1()
{
UpdateData();
}
All required functionality can be implemented inside the DoDataExchange() method. First time the edit box control state set according to the m_Check default value. And each next time the edit box control state will be triggered by OnBnClickedCheck1() event.
IMHO using DoDataExchange(..) to maintain the state of a dialog is dicey at best. Add a member like UdateState( ) and use that. Stage the dialog in OnInitDialog( ) with anything that doesn't easily initialize in the constructor and call UpdateState( ).
Use DoDataExchange(..) only to do what it sounds like, exchange data between the dialog and objects. This way you won't paint yourself into a corner as the Dialog evolves.
//....h
CEdit m_EditBox;
CButton m_CheckBox;
//...cpp
BOOL MyDialog::OnInitDialog( )
{
if( ! CDialogEx::OnInitDialog( ) )
return FALSE;
//do more stuff then
UpdateState( );
return TRUE;
}
void MyDialog::UpdateState( )
{
m_EditBox.EnableWindow( m_CheckBox.GetCheck( ) == BST_CHECKED );
//more state stuff...
}
void MyDialog::OnBnClickedCheck1( )
{
UpdateState( );
}
I am creating a modeless dialog box. The dialog box is called from the menu item of main frame window.
MainFrm.h
CModeless* modeless;
bool modelessDlgOpen;
MainFrm.cpp
void CMainFrame::OnDatabaseMLdlg()
{
// TODO: Add your command handler code here
if (modelessDlgOpen == TRUE)
return;
modelessDlgOpen = TRUE;
modeless = new CModeless(this);
//modeless->Create(IDD_MLDLG, GetDesktopWindow());
modeless->Create(IDD_MLDLG, this);
mbPoll->ShowWindow(SW_SHOW);
}
When menu item is clicked, OnDatabaseMLdlg() function is called and a modeless dialog box with resource ID IDD_MLDLG appears.
The issue is while closing the modeless dialog box.
I am not able to find out the correct method to have a clean closure / destroy of this modeless dialog box. Upon clicking the cross button in right-top corner, which message gets
generated?
My current code which I have tried is as follows. (producing code related only to the closure of the dialog box)
MLDLG.h
#pragma once
#define WM_MLDLG_CLOSED (WM_USER + 555)
// CModeless dialog
class CModeless : public CDialog
{
DECLARE_DYNAMIC(CModeless)
public:
CModeless(CWnd* pParent = NULL); // standard constructor
virtual ~CModeless();
// Dialog Data
enum { IDD = IDD_MLDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);
afx_msg void OnNcDestroy();
virtual void PostNcDestroy();
CWnd* mParent;
afx_msg void OnBnClickedCancel();
};
MLDLG.cpp
void CModeless::OnNcDestroy()
{
CDialog::OnNcDestroy();
// TODO: Add your message handler code here
}
void CModeless::PostNcDestroy()
{
CDialog::PostNcDestroy();
GetParent()->PostMessage(WM_MLDLG_CLOSED,0,0); // **CRASHES HERE**
delete this;
}
void CModeless::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
//CDialog::OnCancel();
DestroyWindow();
}
Not able to understand what am I doing wrong or what am I missing?
I can provide additional details in case required.
Thanks in advance.
EDIT-20130612: Additional information:
My constructor is as follows:
CModeless::CModeless(CWnd* pParent /*=NULL*/)
: CDialog(CModeless::IDD, pParent)
{
mParent = pParent;
if (mParent == NULL)
{
MessageBox(L"mParent is NULL");
}
else
{
MessageBox(L"mParent is not NULL");
}
}
Here, I have verified that mParent is not NULL.
PostNCDestroy() is called VERY late and most of the useful state of the MFC window is not valid at that point. GetParent() is probably returning NULL, which will cause a crash the way you are using it.
Try moving the PostMessage call to OnDestroy() before calling the base class implementation there.
Another option is to cache the parent's hWnd and call ::PostMessage() on that hWnd;
I am working on a game where I am extending the view and performing operations in the class. I need to have a popup in the game which will have 3 buttons inside it. I have managed to have the popup show-up using custom dialogs but when I configure the onClick as follows:
private void popUp() {
Context mContext = getContext();
Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_fullimage_dialog);
dialog.setTitle("Cheese Market");
Button one = (Button)findViewById(R.id.firstpack);
one.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
cheeseLeft = cheeseLeft + 10;
masterMoveLock = false;
return;
}
});
}
It force closes giving a nullpointerexeption even though it is defined in the custom_fullimage_dialog layout.
Can someone help me figure out how to have the button click detected in this scenario?
Thank you.
Try calling dialog.findViewById instead.
You're setting the contentView for the dialog, but by calling findViewById you're looking for it under your activity's content view.
I am using mfc CDialog. I need to show the close and minimize/maximize button, but they should not close or maximize the dialog. I have overriden OnClose method and kept the dialog open even if close button is clicked. But I am unable to block maximize and minimize of the dialog as there doesn't seem to be a OnMaximize method. Is there an alternative way?
You need to handle the WM_SYSCOMMAND message, watching for wParam == SC_MAXIMIZE.
If you catch the SC_MINIMIZE, you can do what you want and not pass it on to Windows.
msdn
Found this snippet here.
const int WM_SYSCOMMAND= 0x0112;
const int SC_MAXIMIZE= 0xF030;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_SYSCOMMAND)
{
if((int)m.WParam==SC_MAXIMIZE)
{
MessageBox.Show("Maximized!!");
return; // swallow the message
}
}
base.WndProc (ref m);
}
You can not show at all the minimise/maximise icons i your dialog. You can do that by going to Dialog properties (right vlick on your Dialog Contorol --> Properties), Select Styles pain and unselect 'Minimise Box', 'Maximise Box'.