I have SDI application that hand view, doc and mainframe. In view class, I have button to open another dialog, let say Chartering dialog. I would like to open that dialog and send initial value from view to assign some variable at dialog, but I can not catch message event at dialog class. Below as my code:
// button onclick to show new dialog
charteringDlg = new CharteringDlg();
// show chartering dialog
if(charteringDlg->Create(IDD_DIALOG_CHATTERING, GetDesktopWindow()))
{
bChartering = true;
charteringDlg->MoveWindow(900,300,450,300);
charteringDlg->ShowWindow(SW_SHOW);
int temp = 12;
GetMain()->SendMessage(UWM_MYMESSAGE_CHARTERING, 0,(LPARAM)&temp);
}
and in chartering dialog I handle message like below
ON_MESSAGE(UWM_MYMESSAGE_CHARTERING, &CharteringDlg::OnSetShowTemp)
chartering function
LRESULT CharteringDlg::OnSetShowTemp(WPARAM, LPARAM lParam)
{
int * s = (int *)lParam;
return 0;
}
I set break point at OnSetShowTemp() function but it cannot jump there.
Any idea would be great appreciated.
For assigning an initial value to one of your dialog's members you don't need to send it a message.
You can just assign the value directly:
So instead of
GetMain()->SendMessage(UWM_MYMESSAGE_CHARTERING, 0,(LPARAM)&temp);
you should have something like:
charteringDlg->thevalueorwhatever = 12;
And BTW:
GetMain()->SendMessage(UWM_MYMESSAGE_CHARTERING, 0,(LPARAM)&temp);
is wrong anyway, you should send the message to the dialog and not to the main window:
charteringDlg->SendMessage(UWM_MYMESSAGE_CHARTERING, 0,(LPARAM)&temp);
Related
firstly let me describe what I have:
scenario: CMFCMenuButton, loaded with a CMenu, in a dialog test: click on an item of the menuresult: the message map will get the ID of the CMFCMenuButton and not the ID of the menu
how to get the actual menu ID clicked: use CMFCMenuButton::m_nMenuResultThe idea is that I want to have menu items and buttons in this dialog, and there would be buttons that share IDs with the menu items.So in the handler that I've created for the menu button I can get that m_nMenuResult and send it to the dialog or do whatever I want, but that doesn't seem to be how the CMFCMenuButton should work. What is the correct way of doing it?
CodeHere follows an example on how you can reproduce this.
I've used ON_COMMAND_RANGE also with IDC_MFCMENUBUTTON1 just to reuse the code for the OnMenu function
void CRepositionDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MFCMENUBUTTON1, m_cmfcMenuButton);
}
BEGIN_MESSAGE_MAP(CRepositionDlg, CDialog)
ON_COMMAND_RANGE(IDC_MFCMENUBUTTON1,IDC_MFCMENUBUTTON1,OnMenu)
ON_COMMAND_RANGE(IDC_MENU1, IDC_MENU11, OnMenu)
END_MESSAGE_MAP()
// CRepositionDlg message handlers
afx_msg void CRepositionDlg::OnMenu(UINT nID)
{
CString csMessage;
csMessage.Format(L"OnMenu(%d)",nID);
AfxMessageBox(csMessage);
if(nID == IDC_MFCMENUBUTTON1)
{
OnMenu(m_cmfcMenuButton.m_nMenuResult);
}
}
BOOL CRepositionDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
CMenu* pMenu = new CMenu;
pMenu->CreatePopupMenu();
for(int i = IDC_MENU1; i <= IDC_MENU11; i++)
{
CString csMenu;
csMenu.Format(L"menu %d",i);
pMenu->AppendMenuW(MF_STRING,i,csMenu);
}
m_cmfcMenuButton.m_hMenu = pMenu->GetSafeHmenu();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
If you code a handler for BN_CLICKED for the menu button, it will respond with 0 for m_nMenuResult if the click is on the button, or, m_nMenuResult will contain the ID of the menu item selected. If that's not what you wanted, I think you're fighting against the way the button works. Your only other option would be to create your own class to represent a menu button and add the behavior you want.
I have a MFC project I am working on. In the main dialog box there is a button to open a child dialog box for some user input. This data is then set to variables in the parent dialog box when OK is clicked in the child box. This bit all works perfectly fine.
Right now the text boxes in the child box initialize to preset values in the OnInitDialog() of the child dialog box. I would like these values to initialize to whatever the variable they are connected to in the parent dialog box currently is.
So, for example I have a text box that sets in integer variable called sampleCount. In the child dialog box I have (just showing the code for this variable)
void ChildBox::DoDataExchange(CdataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_SAMPCOUNT, sampCnt);
}
BOOL FNameIn::OnInitDialog()
{
CDialog::OnInitDialog();
GetDlgItem(IDC_SAMPCOUNT)->SetWindowTextA("1");
return TRUE;
}
Then in the parent dialog box I have
void ParentDialog::OnInput()
{
ChildBox dlg;
if (dlg.DoModal() == IDOK)
{
sampleCount = dlg.sampCnt;
}
}
As I said, this code all works, but every time I open the ChildBox the sampleCount text box is set to 1. If I type in 20, then hit ok and set the sampleCount variable in ParentDialog to 20 I want it to show a 20 in the text box next time I open the child dialog box. The variable could also be set automatically by another function in ParentDialog, so the last value entered in child dialog isn't always correct, it needs to use whatever is currently the value of the variable sampleCount in ParentDialog.
I feel like this should be pretty straight forward but I can't quite figure it out, thanks for the help.
Modify the child dialog's constructor to accept a CString parameter and store that into the child's sampCnt variable. Then the MFC code will display it in the control because of the DDX_Text statement.
Remove the GetDlgItem(IDC_SAMPCOUNT)->SetWindowTextA("1"); line and set the value before calling dlg.DoModal(), like
ChildBox dlg;
dlg.sampCnt = sampleCount;
if (dlg.DoModal() == IDOK)
{ sampleCount = dlg.sampCnt;
}
I think you are creating local variable of ChildBox Dialog
so , even if you are assigning a value to its variable it will not work.
Rather create a pointer variable of ChildBox Dialog
void ParentDialog::OnInput()
{
ChildBox *dlg;
if (dlg->DoModal() == IDOK)
{
sampleCount = dlg->sampCnt;
}
dlg = NULL ;
}
I have a child dialog. I initiate other child dialog.
In the second dialog i have the following code for list box.
I need to access the m_selcomponents in the first child dialog. Itried to access this like
dlg->m_selcomponents. But it's getting null. How can i do this? Thank You for help.
int count = m_OutList.GetCount();
for ( i = 0; i <m_OutList.GetCount(); i++)
{
m_OutList.GetText( buf[i], text );
m_selcomponents->Add(text);
}
MSelCFLCompDlg *SelCflCompDlg= new MSelCFLCompDlg(&allcomponents, &m_cflcomponents,m_FileDecimal,this) ;
if(SelCflCompDlg->DoModal()==IDOK) { selectedcomponents.Append(*SelCflCompDlg->m_selcomponents); }
MSelCFLCompDlg::MSelCFLCompDlg(CStringArray *all, CStringArray *sel,int, CWnd* pParent /*=NULL*/)
: CDialog(MSelCFLCompDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(MSelCFLCompDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_allcomponents = all;
m_selcomponents = sel;
}
When you create the child dialog box, pass a pointer to the parent dialog box to the child dialog box constructor. If you show us a bit more of your code I can perhaps explain in a bit more detail.
I have followed this question to make a non-modal/modeless dialog:
How to display a non-modal CDialog?
I'm using MFC/C++ in VS2008. I'm more fluent with C# and .net than with MFC and C++.
I have a menu item in my form that launches the dialog. There can only be one instance of the dialog opened. The dialog displays fine. I can close it by clicking the X in the corner and it closes when I close the main form. The problem I am having is the dialog cannot be opened again after I click the X to close the dialog. I know it is because the pointer is never set back to NULL.
I have this in my form's header file:
CChildDialog *m_pDialog;
I have this part in my form's constructor:
m_pDialog = NULL;
When clicking on a menu item I have this code in the menu item's method (I modified it from the other SO answer because I only want one instance of the dialog opened):
if(m_pDialog == NULL)
{
// Invoking the Dialog
m_pDialog = new CChildDialog();
BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);
if (!ret) //Create failed.
{
AfxMessageBox(_T("Error creating Dialog"));
}
m_pDialog->ShowWindow(SW_SHOW);
}
Now I know I need to execute this part and set the pointer to NULL, but I don't know where to put this:
// Delete the dialog once done
delete m_pDialog;
m_pDialog = NULL;
Do I need to keep monitoring if the dialog has been disposed? Is there an event triggered to the parent form when the dialog is closed?
If you want to recycle the contents of the window after closing it with X, you have to handle the WM_CLOSE message in your dialog:
void CChildDialog::OnClose()
{
ShowWindow(SW_HIDE);
}
Then in the code that opens the window:
if(m_pDialog == NULL)
{
// Invoking the Dialog
m_pDialog = new CChildDialog();
BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);
if (!ret) //Create failed.
{
AfxMessageBox(_T("Error creating Dialog"));
}
}
m_pDialog->ShowWindow(SW_SHOW); //moved outside the if(m_pDialog == NULL)
Hope it can help
If you want to delete the modeless dialog, then just do so.
If you want to delete the dialog's object when the user closed the modeless dialog you might take a look at WM_PARENTNOTIFY. If a child window is destroyed and the child windows has not the extended window style WS_EX_NOPARENTNOTIFY set, then windows sends a WM_PARENTNOTIFY with wParam=WM_DESTROY to the parent window. You should implement a handler for that message in the parent window and check if it's the modeless dialog that is being destroyed.
I had the question drafted up and was ready to post it, but then I had an idea and ended up solving my own problem. So for anyone else who has an issue with detecting the closing of a modeless dialog, this is what I did:
void Form1::MenuItemMethod()
{
if(m_pDialog == NULL)
{
// Invoking the Dialog
m_pDialog = new CChildDialog();
BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);
if (!ret) //Create failed.
{
AfxMessageBox(_T("Error creating Dialog"));
}
m_pDialog->ShowWindow(SW_SHOW);
}
else
{
// cannot check if visible at the beginning of method because
// pointer could be NULL and will throw an exception
if(m_pDialog->IsWindowVisible())
{
return;
}
m_pDialog->DestroyWindow();
m_pDialog = NULL;
MenuItemMethod();
}
}
I just ended up checking if the modeless dialog is visible after clicking on the form's menu item again. If it is visible, don't do anything. If not, destroy the existing non-visible dialog, set the pointer to NULL, and recursively call the method again. Since the pointer is now NULL, it should recreate the dialog normally and then return to normal operation.
you have to delete the memory in PostNcDestroy like this
void CChildDialog ::PostNcDestroy()
{
CDialog::PostNcDestroy();
GetParent()->PostMessage(WM_WIN_CLOSED,0,0);
delete this;
}
and send a user defined message to the parent window that your window is closed. In the parent window add a message handler for WM_WIN_CLOSED like
LRESULT CMainDialog::OnMyMethod(WPARAM wParam, LPARAM lParam)
{
m_pDialog = NULL;
return 0;
}
I have a VC++ MFC dialog application and in my OnTimer function I am just trying to determine which button in my dialog currently has focus.
Here is some pseudocode of what I am trying to accomplish....
CDialog::OnTimer()
{
CButton *btn = GetButtonOnFocus();
int btnID = btn->GetDlgCtrlID();
}
I haven't tried it, but this should work:
CWnd * pFocus = GetFocus();
int btnID = 0;
if (pFocus != NULL && pDialog->IsChild(pFocus))
btnID = pFocus->GetDlgCtrlID();
This won't restrict the result to buttons only - to do that, you need to use GetClassName and compare to "button".