I would like to add a second toolbar in my main frame window to sit under the existing toolbar.
Reading the following tutorials:
http://forums.codeguru.com/showthread.php?495887-Add-a-toolbar-to-an-MFC-application
http://www.codersource.net/2010/01/30/mfc-tutorial-toolbars/
MFC Toolbar on Dialog?
I have come to a similar conclusion to this unanswered thread:
https://stackoverflow.com/questions/35736580/how-to-add-a-second-toolbar-to-an-mfc-application-so-that-the-toolbar-is-added-o
This is my code:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// create a view to occupy the client area of the frame
if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
{
TRACE0("Failed to create view window\n");
return -1;
}
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetPaneInfo(EWF_PANE_INDEX, ID_SEPARATOR, SBPS_NORMAL, EWF_PANE_WIDTH);
for (int i=0;i<5; i++) {
// Change Status Bar style to make it Owner-drawn
m_wndStatusBar.GetStatusBarCtrl().SetText("", i, SBT_OWNERDRAW);
}
CToolBar myToolBar;
if (!myToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!myToolBar.LoadToolBar(IDR_MAINFRAME_B))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
return 0;
}
I have added:
CToolBar myToolBar;
if (!myToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!myToolBar.LoadToolBar(IDR_MAINFRAME_B))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
At the bottom for my second toolbar but it does not appear when the app is opened and it compiles with no errors.
In comparison to the already supplied toolbar which is called from InitInstance() by pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE , NULL, NULL);
If I call this pFrame->LoadFrame with my second toolbar in the next line the app will not load all together.
How do I need to call my second toolbar?
Have I missed something completely?
You need to add CToolBar myToolBar as a member variable of your CMainFrame class, the same way as m_wndToolBar. Otherwise, it gets destroyed if you define it as a local variable after the OnCreate exits.
Related
I have a strange Problem with my MFC Application which i create with visual Studio 2015.
If i run the Application inside Visual Studio via Local Windows Debugger everything works as expected.
If i start the generated .exe File outside of Visual Studio the Toolbar and the Statusbar are not displayed in the Mainframe. I couldn't activate them via View Menu. So my application crashs when I use a Menu Point which writes text to the statusbar.
Did someone now whats the Problem??
Perhaps I didn't know which code i should display in the question feel free to ask for specific code sections in the comments. I will edit the question and provide the code.
This is the code in which the Tool- and Statusbar are created.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
//TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
m_wndToolBar.LoadTCToolBar(16, IDB_TOOLICONS, IDB_TOOLICONS_HOT, IDB_TOOLICONS_DISABLED, RGB(255, 0, 255));
if (!m_wndStatusBar.Create(this))
{
//TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT));
return 0;
}
I have solved the Problem with a simple Code rearranging in the OnCreate Method.
The Method now looks like this:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
//TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
m_wndToolBar.LoadTCToolBar(16, IDB_TOOLICONS, IDB_TOOLICONS_HOT, IDB_TOOLICONS_DISABLED, RGB(255, 0, 255));
if (!m_wndStatusBar.Create(this))
{
//TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT));
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
I had to move the Lines
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
to the end of the Method. After that the Bars are displayed.
I am using MFC c++. I using CToolBar i try to changing the default Gripper Style:
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
I want to change this:
to this:
Any help?
Finally its work.
Thanks to Barmak Shemirani.
Method 1: (docking enable)
SetWindowTheme(m_wndToolBar.m_hWnd,L"",L"")
Method 2: (docking not working)
CReBarCtrl& rbc = m_wndReBar.GetReBarCtrl();
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof(rbbi);
rbbi.fMask = RBBIM_STYLE;
int nCount = rbc.GetBandCount();
for (int i = 0; i < nCount; i++)
{
rbc.GetBandInfo(i, &rbbi);
rbbi.fStyle |= RBBS_NOGRIPPER;
rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
rbc.SetBandInfo(i, &rbbi);
}
I'am now working with a MDI MFC app and want to add a console/command-line function to the app. The only function I want to take from QuickWin(see below) is to use its text area and the process function which captures input. If I can add it to a popup dialog or a dock bar, it will be great!
And I got the src-code of a SDI Applization without Document Class like this(link:http://www.codeproject.com/.../QuickWin-...):
My Question is: can I add the app into my MDI app, and how to deal with source or head files like:
MainFrm.cpp/MainFrm.h and class like: CQuickWinApp/CQuickView?(If I can pop up a child window to implement the function, better:))
In QuickWin's mainframe, it has something to do with client area, which is difficule to deal with:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// create splitter without views
m_wndSplitter.CreateStatic(this, 2, 1);
CCreateContext Context;
Context.m_pNewViewClass = RUNTIME_CLASS(CQuickView);
Context.m_pCurrentDoc = NULL;
Context.m_pNewDocTemplate = NULL;
Context.m_pLastView = NULL;
Context.m_pCurrentFrame = this;
// Create the Stdio QuickView
m_pStdioView = (CQuickView*)CreateView(&Context, AFX_IDW_PANE_FIRST);
if (m_pStdioView == NULL)
{
TRACE("Failed to create QuickWin Stdio View\n");
return FALSE; // fail to create
}
// Create the Stderr QuickView
m_pStderrView = (CQuickView*)CreateView(&Context, AFX_IDW_PANE_FIRST);
if (m_pStderrView == NULL)
{
TRACE("Failed to create QuickWin Stderr View\n");
return FALSE; // fail to create
}
m_pStderrView->SetReadOnly(TRUE);
ShowSplitter(theApp.m_bShowSplitter);
return TRUE;
}
in My MDI app:
The MDI app has 3 doctemplates:
//BCGPVisualStudioGUIDemo.cpp
m_pDocTemplateCpp = new CMultiDocTemplate(
IDR_BCGDEVTYPE_CPP,
RUNTIME_CLASS(CBCGPVisualStudioGUIDemoDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CBCGPVisualStudioGUIDemoView));
AddDocTemplate (m_pDocTemplateCpp);
m_pDocTemplateWeb = new CMultiDocTemplate(
IDR_BCGDEVTYPE_WEB,
RUNTIME_CLASS(CBCGPVisualStudioGUIDemoDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CBCGPVisualStudioGUIDemoView));
AddDocTemplate (m_pDocTemplateWeb);
m_pStartDocTemplate = new CMultiDocTemplate(
IDR_BCGDEVTYPE0,
RUNTIME_CLASS(CNetworkMapEditorDemoDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CNetworkMapEditorDemoView));
AddDocTemplate(m_pStartDocTemplate);
The app also has some dock bars:
//MainFrm.cpp
//------------------
// Create config bar:
//------------------
if (!m_wndClassView.Create (_T("config"), this, CRect (0, 0, 200, 200),
TRUE,
ID_VIEW_CLASS,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Class View bar\n");
return FALSE; // fail to create
}
//------------------
// Create output bar:
//------------------
if (!m_wndOutputView.Create (_T("output"), this, CRect (0, 0, 200, 100),
TRUE,
ID_VIEW_OUTPUT,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create output bar\n");
return FALSE; // fail to create
}
//------------------
// Create help bar:
//------------------
if (!m_wndDynamicHelpView.Create (_T("help"), this, CRect (0, 0, 200, 200),
TRUE,
ID_VIEW_DYNAMICHELP,
WS_CHILD | WS_VISIBLE | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Dynamic Help Bar\n");
return FALSE; // fail to create
}
//------------------
// Create watch bar:
//------------------
if (!m_wndWatchBar.Create (_T("watch"), this, CRect (0, 0, 300, 100),
TRUE,
ID_VIEW_WATCH,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create watch bar\n");
return FALSE; // fail to create
}
//------------------
// Create property bar:
//------------------
if (!m_wndPropertiesBar.Create (_T("property"), this, CRect (0, 0, 300, 200),
TRUE,
ID_VIEW_PROPERTIES,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Properties Bar\n");
return FALSE; // fail to create
}
Can I add the QuickWin app's text function into my app's dock bar or into a doctemplate or just a popup window?
All you need to integrate the functionality of QuickWin into your application are 3 textboxes (one for stdin, stdout and stderr) and the following classes from the Quickwin project:
CRedirect
CRedir
CParamDlg (only optical fluff, not essential)
The CRedirect-class manages the creation of the new process as well as the redirection of stdin/stdout/stderr (in combination with CRedir).
You have to modify CRedir::OnChildWrite and -Started and -Terminate to fit your needs. These methods actually write the content to the view/textbox/whatever. It is helpful to look at CMainFrame::OnCopyData and CQuickView::Append on how this can be done.
I'm having a problem with the CMFCToolbar class where the positions of the toolbars are not being restored properly between sessions.
Here is a screen shot of how the toolbars are arranged before the app is closed:
(source: achavis.net)
Here is a screen shot of how the toolbars are restored when the app is launched again:
(source: achavis.net)
Notice the large gap that appears above the first toolbar and the second toolbar is now to the right of the main toolbar instead of beneath it.
I was having problems with my app, so I generated this test app using the App Wizard, then I added the second toolbar manually.
I would like to know if this is because there is something I am doing wrong, or if it is just due to the buggy nature of the feature pack code.
Here is the code from my CMainFrame class which sets up the toolbars:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
BOOL bNameValid;
// set the visual manager used to draw all user interface elements
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
// set the visual style to be used the by the visual manager
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
if (!m_wndMenuBar.Create(this))
{
TRACE0("Failed to create menubar\n");
return -1; // fail to create
}
m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
// prevent the menu bar from taking the focus on activation
CMFCPopupMenu::SetForceMenuFocus(FALSE);
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
CString strToolBarName;
bNameValid = strToolBarName.LoadString(IDS_TOOLBAR_STANDARD);
ASSERT(bNameValid);
m_wndToolBar.SetWindowText(strToolBarName);
m_wndToolBar.EnableTextLabels();
if (!m_wndToolBar2.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar2.LoadToolBar(IDR_TOOLBAR))
{
TRACE0("Failed to create toolbar2\n");
return -1; // fail to create
}
CString strCustomize("Toolbar2");
m_wndToolBar2.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);
// Allow user-defined toolbars operations:
InitUserToolbars(NULL, uiFirstUserToolBarId, uiLastUserToolBarId);
if (!m_wndStatusBar.Create(this))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
// TODO: Delete these five lines if you don't want the toolbar and menubar to be dockable
m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar2.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndMenuBar);
DockPane(&m_wndToolBar);
DockPane(&m_wndToolBar2);
// enable Visual Studio 2005 style docking window behavior
CDockingManager::SetDockingMode(DT_SMART);
// enable Visual Studio 2005 style docking window auto-hide behavior
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// Load menu item image (not placed on any standard toolbars):
CMFCToolBar::AddToolBarForImageCollection(IDR_MENU_IMAGES, theApp.m_bHiColorIcons ? IDB_MENU_IMAGES_24 : 0);
// create docking windows
if (!CreateDockingWindows())
{
TRACE0("Failed to create docking windows\n");
return -1;
}
m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);
m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndFileView);
CDockablePane* pTabbedBar = NULL;
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndOutput);
// Enable toolbar and docking window menu replacement
EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, strCustomize, ID_VIEW_TOOLBAR);
// enable quick (Alt+drag) toolbar customization
CMFCToolBar::EnableQuickCustomization();
if (CMFCToolBar::GetUserImages() == NULL)
{
// load user-defined toolbar images
if (m_UserImages.Load(_T(".\\UserImages.bmp")))
{
m_UserImages.SetImageSize(CSize(16, 16), FALSE);
CMFCToolBar::SetUserImages(&m_UserImages);
}
}
// enable menu personalization (most-recently used commands)
// TODO: define your own basic commands, ensuring that each pulldown menu has at least one basic command.
CList<UINT, UINT> lstBasicCommands;
lstBasicCommands.AddTail(ID_FILE_NEW);
lstBasicCommands.AddTail(ID_FILE_OPEN);
lstBasicCommands.AddTail(ID_FILE_SAVE);
lstBasicCommands.AddTail(ID_FILE_PRINT);
lstBasicCommands.AddTail(ID_APP_EXIT);
lstBasicCommands.AddTail(ID_EDIT_CUT);
lstBasicCommands.AddTail(ID_EDIT_PASTE);
lstBasicCommands.AddTail(ID_EDIT_UNDO);
lstBasicCommands.AddTail(ID_APP_ABOUT);
lstBasicCommands.AddTail(ID_VIEW_STATUS_BAR);
lstBasicCommands.AddTail(ID_VIEW_TOOLBAR);
lstBasicCommands.AddTail(ID_SORTING_SORTALPHABETIC);
lstBasicCommands.AddTail(ID_SORTING_SORTBYTYPE);
lstBasicCommands.AddTail(ID_SORTING_SORTBYACCESS);
lstBasicCommands.AddTail(ID_SORTING_GROUPBYTYPE);
CMFCToolBar::SetBasicCommands(lstBasicCommands);
return 0;
}
This problem was resolved by creating the toolbars with explicit IDs as opposed to relying on the default parameter as in the above code.
Because the registry key that the toolbar's state is saved to is based on the ID, the second toolbar was saving its state on top of the first toolbar.
Here are the code changes that resolved the problem:
if (!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) ||
!m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
...
if (!m_wndToolBar2.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_TOOLBAR) ||
!m_wndToolBar2.LoadToolBar(IDR_TOOLBAR))
{
TRACE0("Failed to create toolbar2\n");
return -1; // fail to create
}
This question is related to this one.
In a CDockablePane derived class I have a CTreeCtrl member for which I add a ToolTip in OnCreate():
int CMyPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
const DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TVS_CHECKBOXES | TVS_DISABLEDRAGDROP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT |
TVS_INFOTIP | TVS_NOHSCROLL | TVS_SHOWSELALWAYS;
if(!m_tree.Create(dwStyle, m_treeRect, this, TREECTRL_ID) ) { return -1; }
m_pToolTip->AddTool(&m_tree, LPSTR_TEXTCALLBACK, &m_treeRect, TREECTRL_ID);
m_tree.SetToolTips(m_pToolTip);
return 0;
}
I have to call AddTool() with all of the optional parameters because the default values won't work with CDockablePane.
m_treeRect is a CRect member set to (0, 0, 10000, 10000) in the CTor. This is really ugly.
I would like to adjust the tool's rectangle whenever m_tree's size changes.
So I tried some stuff in CMyPane::OnSize() but none of it worked:
Calling m_pToolTip->GetToolInfo() then modify the CToolInfo's rect member, then calling SetToolInfo()
Calling m_pToolTip->SetToolRect()
How is it meant to be done?
I know no other way to do this other than calling DelTool then AddTool again in your OnSize handler:
void CMyPane::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
if (m_pToolTip != NULL)
{
m_pToolTip->DelTool(&m_tree, TREECTRL_ID);
CRect treeRect;
m_tree.GetClientRect(treeRect);
m_pToolTip->AddTool(&m_tree, LPSTR_TEXTCALLBACK, &treeRect, TREECTRL_ID);
}
}
int CMyPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
const DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TVS_CHECKBOXES | TVS_DISABLEDRAGDROP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT |
TVS_INFOTIP | TVS_NOHSCROLL | TVS_SHOWSELALWAYS;
if(!m_tree.Create(dwStyle, m_treeRect, this, TREECTRL_ID) ) { return -1; }
m_pToolTip->AddTool(&m_tree, LPSTR_TEXTCALLBACK, &m_treeRect, TREECTRL_ID);
m_tree.SetToolTips(m_pToolTip);
return 0;
}