I have following requirement for my MFC application:
Dialog 1 --> Dialog 2 --> Dialog 3 --> Dialog 4 --> Dialog 5
^ | | ^ ^ |
| ---------------------------- | |
| | | |
| -------------------------- |
--------------------------------------------------------
Navigate from Dlg1 to Dlg2 to Dlg3 to Dlg4 to Dlg5
Navigate from Dlg2 to Dlg4
Navigate from Dlg3 to Dlg5
Navigate from Dlg5 back to Dlg1
After navigation e.g. Dlg1 to Dlg2, the prevous dialog (Dlg1) shall not be visible
The user shall not see that it is a different dialog when he navigates (E.g. from Dlg1 to Dlg2), he should have the feeling of one application.
Question: What application type should I use? (SDI, MDI, Dialog based)
How about a tabbed dialog? Start with the dialog based architecture but replace the main dialog with a CPropertySheet. Your dialog 1 through dialog 5 will become pages in the tabbed sheet.
I would suggest creating SDI application then delete all document and view classes. Only CFrameWnd and CWinApp classes would stay. Make CFrameWnd non-resizable and dynamically Create all child dialogs into it. Then you would have one window CFrameWnd with many dynamically loading Dialogs inside.
Choose either SDI or MDI. Many time initial requirements like yours make SDI the best fit but often times people have to convert SDI to MDI at the end of the road so use own your judgement if you might want to start MDI right away but given your today requirements SDI is good option.
You could also achieve the same with Dialog and use DoModal() but it will be a new window everytime. I in fact did this myself because I had to use CDialog and here is how I did it:
// here how I exit from say a given dialog to a different screen.
void CSummaryDlg::OnBnClickedButtonBack()
{
EndDialog( Batch::BatchGoBack ); // goes to previous dialog
}
void CSummaryDlg::OnBnClickedButtonExitBatch()
{
EndDialog( Batch::BatchComplete ); // finishes all dialogs in the chain.
}
// how ending all dialog takes places (example of propagation)
void CResultDlg::OnBnClickedButtonViewReport()
{
CSummaryDlg dlg;
int dlgResult = dlg.DoModal();
if ( dlgResult == Batch::BatchComplete )
EndDialog( Batch::BatchComplete );
}
You can create a dialog based application with an empty dialog, then dynamically insert the required dialog as a new window that fills the entire client area of the outer dialog. Set the DS_CONTROL style of the inner dialogs. As you switch from one dialog to another, you can destroy the old one or just hide it for faster activation if you'll need it back again later.
Related
The title of the toolbar and also the menu item ID_VIEW_TOOLBAR remains empty. I have tried to set it within CMainFrame::OnCreate:
CString strToolbar;
strToolbar.LoadStringA(IDS_TOOLBAR_STANDARD); // IDS_TOOLBAR_STANDARD = "Standard"
m_wndToolBar.SetWindowText(strToolbar);
DockPane(&m_wndToolBar);
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
EnablePaneMenu(TRUE, ID_ANSICHT_ANPASSEN, "Anpassen", ID_VIEW_TOOLBAR);
The menu Looks like following:
Do you know how to set it properly?
Generally speaking people do not change the display text of standard commands at runtime. At compile time you can set the ID's menu text in in the string table section of the resource editor.
If you want to change the menu text at runtime, you can add an ON_UPDATE_COMMAND_UI handler for ID_VIEW_TOOLBAR and call CCmdUI::SetText inside the handler. When the user click a top level menu to display a drop-down menu, a WM_INITMENUPOPUP is sent to the owner of the menu, in this case your CFrameWnd-derived class. CFrameWnd::OnInitMenuPopup then iterates through each menu item and calls the update command UI handlers if exists.
Reference
MFC TN021: Command and Message Routing
To solve this problem, I had create the Toolbar by explicitly specifying the ID of the Toolbar (instead of using the default argument of the function).
m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP |
CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC,
CRect(1,1,1,1),
IDR_MAINFRAME) // <-- Custom ID
After this I could set the title of the toolbar to what I want:
m_wndToolBar.SetWindowText(_T("My Toolbar Name");
I got it working after reading this thread.
if (IDOK == dlg.DoModal())
{
csFile = dlg.GetPathName();
return (LPCTSTR)csFile;
}
return NULL;
I have a desktop application and in this I have a dialog box. When I click on open button in this dialog box another open dialog box should pop up. Once this open dialogue box is displayed I am able to again go to the previous dialogue box and click on open. So second instance of open dialog box is displayed. I can do this many times. The open dialog box is modal to the whole application and not to the previous dialog box. Can anyone help me with this? As per design once open dialog box is displayed nothing else should be active till this is closed.
The standard wizard-generated constructor for the dialog box contains an optional constructor-parameter where you can specify the parent window:
class CMyOpenDialog : public CDialog
{
// Construction
public:
CMyOpenDialog(CWnd* pParent = NULL); // standard constructor
...
When you invoke this second dialog from your dialog, supply the parent, like
CMyOpenDialogdlg(this);
Could you please any one let me know what all the classes will get invoke at the time of creation of Dailog in Dialog based applications.
and please let me know the differnce bitween dialog based application and SDI and MDI's.
When the dialog is created only one class is invoked: the CDialog-derived class. A dialog based application is the simplest type of MFC app.
SDI and MDI applications create a frame window, with a menu, tool bar and status bar, a view window (inside the frame), and a document object. MDI also allows the user to open more than one file at a time and creates a document, MDI frame and view for each open document. Several types of view can be used, depending on what you wish to display.
I have created a MFC Document View app and added several classes which inherit from CEdit to the CView. I would like to get tabbing between each CEdit working. I have looked around and most solution involve Adding IsDialogMessage() to either the message loop or in PreTranslateMessage. I have tried this in the PreTranslateMessage method of the CEdit class like this:
BOOL WordControl::PreTranslateMessage(MSG* pMsg)
{
if(IsDialogMessage(pMsg))
return TRUE;
else
return __super::PreTranslateMessage(pMsg);
}
however, now the CEdit doesn't receive any keyboard messages and doesn't tab. I have created the CEdit like this:
Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_CENTER , Rect, Parent, Index);
What am I doing wrong?
EDIT:
The app uses the basic MFC single document
template. I am dynamically adding several objects which inherit from CEdit and several which inherit from CStatic. I have managed to create all the CEdits and CStatics but I would like to be able to tab from CEdit to CEdit.
A picture is worth a thousand words; here is a screenshot:
I want to be able to type "hello" in the first CEdit, hit tab and for the next CEdit to have focus. Then I will type "world" and then hit tab and the next CEdit will have focus for me to type "this" etc.
EDIT:
New Window:
Use a CFormView as your base. You can add controls dynamically and the form will manage the tabbing for you. If you only have a small number of maximum edit controls you could also just create them on the form and then show/hide them as necessary.
I need to handle multiple panels, containing variuous data masks. Each panel shall be visible using a TreeView control.
At this time, I handle the panels visibility manually, by making the selected one visible and bring it on top.
Actually this is not much confortable, especially in the UI designer, since when I add a brand new panel I have to resize every panel and then design it...
A good solution would be using a TabControl, and each panel is contained in a TabPage. But I cannot find any way to hide the TabControl buttons, since I already have a TreeView for selecting items.
Another solution would be an ipotethic "StackPanelControl", where the Panels are arranged using a stack, but I couldn't find it anywhere.
What's the best solution to handle this kind of UI?
You need a wee bit of Win32 API magic. The tab control sends the TCM_ADJUSTRECT message to allow the app to adjust the tab size. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
You'll get the tabs at design time so you can easily switch between pages. The tabs are hidden at runtime, use the SelectedIndex or SelectedTab property to switch between "views".
using System;
using System.Windows.Forms;
class StackPanel : TabControl {
protected override void WndProc(ref Message m) {
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else base.WndProc(ref m);
}
}
A good solution would be using a TabControl, and each panel is contained in a TabPage.
But I cannot find any way to hide the TabControl buttons, since I already have a
TreeView for selecting items.
For the above,
You need to set the following properties of TabControl.
tabControl.Multiline = true;
tabControl.Appearance = TabAppearance.Buttons;
tabControl.ItemSize = new System.Drawing.Size(0, 1);
tabControl.SizeMode = TabSizeMode.Fixed;
tabControl.TabStop = false;