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.
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.
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.
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;
Am doing a calculator programme in vc++/MFC dialog application. Thier, i want to change the foreground and background colour of a push button in dialog. I have no idea, how to change.
Please suggests me with relevent code or example if any body have idea.
basu_sagar
There's no easy way to do this in a classical VC/MFC application, button colours are always system-defined. You either have to use a custom control, or create an owner-draw button. Handling WM_CTLCOLOR and returning a different brush doesn't work for buttons.
Edit:
This is an example replacement button control someone has built to solve this problem by encapsulating the owner-draw code into a class.
You can use a CMFCButton. Although you can directly say in your resources file a button is of this type, I do not recommend it, because it adds an unmaintainable hexadecimal piece of text on the rc file. And if you use several rc files, one for each language, it's really devilish!
So lets go. In your form class, declare a member
CMFCButton m_button1;
The DoDataExchange should look like:
void MyDialog::DoDataExchange(CDataExchange* pDX)
{
__super::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_button1);
// ...
}
Then the OnInitDialog should be something like:
BOOL CMyDialog::OnInitDialog()
{
if(!__super::OnInitDialog())
return FALSE;
m_button1.SetFaceColor(RGB(0,0,255));
m_button1.SetTextColor(RGB(0,255,0));
m_button1.SetHotTextColor(RGB(255,0,0));
return TRUE;
}
The code I posted will draw a blue button, with green text, and when cursor hovers the button, its text will turn red.
When I move to a CEdit control on my dialog using the tab key or the arrow keys all the text in the control is selected. This behaviour is causing me problems and I would prefer it if the control just put the cursor at the start (or end) of the text and didn't select anything.
Is there a simple way to do this (e.g. a property of the control that I can set)?
Another way of achieving your goal is to prevent the contents from being selected. When navigating over controls in a dialog the dialog manager queries the respective controls about certain properties pertaining to their behavior. By default an edit control responds with a DLGC_HASSETSEL flag (among others) to indicate to the dialog manager that its contents should be auto-selected.
To work around this you would have to subclass the edit control and handle the WM_GETDLGCODE message to alter the flags appropriately. First, derive a class from CEdit:
class CPersistentSelectionEdit : public CEdit {
public:
DECLARE_MESSAGE_MAP()
afx_msg UINT OnGetDlgCode() {
// Return default value, removing the DLGC_HASSETSEL flag
return ( CEdit::OnGetDlgCode() & ~DLGC_HASSETSEL );
}
};
BEGIN_MESSAGE_MAP( CPersistentSelectionEdit, CEdit )
ON_WM_GETDLGCODE()
END_MESSAGE_MAP()
Next subclass the actual control. There are a number of ways to do this. To keep things simple just declare a class member m_Edit1 of type CPersistentSelectionEdit in your dialog class and add an appropriate entry in DoDataExchange:
// Subclass the edit control
DDX_Control( pDX, IDC_EDIT1, m_Edit1 );
At this point you have an edit control that doesn't have its contents auto-selected when navigated to. You can control the selection whichever way you want.
I don't think that such a style exists.
But you can add OnSetfocus handler with the wizard:
void CMyDlg::OnSetfocusEdit1()
{
CEdit* e = (CEdit*)GetDlgItem(IDC_EDIT1);
e->SetSel(0); // <-- hide selection
}
Please note that there must be a code in your program to highlight the selection. Please find something like this:
CEdit* pEdit = ((CEdit*)GetDlgItem(IDC_EDIT1));
pEdit->SetFocus();
pEdit->SetSel(0, -1); // select everything
Simply comment the last two lines, instead of >SetSel(0). Your code is enabling and disabling which is meaningless to me.