Programmatically and completely delete button from MFC toolbar - c++

I have a document within MFC C++ application. I need to delete one the buttons from the particular CMFCToolbar within a code (not resources) completely, even preventing a user to restore the button via toolbar customization dialog. At this moment I use RemoveButton method of CMFCToolbar but it only makes the button invisible and it can be restored via toolbar customization dialog that is not an option for me at this time. I will be very glad if you suggest something that can help me there.

There are two internal lists in CMFCToolBar that are used to reset the Buttons upon customization.
They are named m_OrigButtons and m_OrigResetButtons.
You may need to derive your own class and delete the buttons with the specific IDs from there.
But better: Never to include such a button on the first time when the toolbar is created!

Related

MFC: Use a dialog's class for a second dialog

I have an dialog with several buttons and sliders on it and am adding another button that should close the dialog and open another that is essentially a mini version it.
I need access to the buttons in the first dialog in the second mini dialog (since they should have the same functionality).
Is there a way to use the class from the first dialog on the second so that I have access to those buttons? I've tried right clicking the dialog and adding a class, but it makes me make a new one instead of being able to use an existing one.
Thanks in advance!

Create a property sheet using a dialog template

I need to extend an existing MFC app with a UI that will end up very cluttered unless I use a tab control. However, the nature of the UI is that there are some controls that are global, and only some that can be localised to a particular tab.
The standard use of tab controls (CPropertySheet + CPropertyPage) more or less expects there only to be CPropertyPage instances (tabs) visible on the CPropertySheet object, and nothing else. There is a Microsoft Example Project that shows a single additional window painted outside the area occupied by the tab control... but it's not immediately clear how it is created/drawn/handled, and it is only one single additional window that generates few events (I guess it is painted, so there must be a WM_PAINT event handler lurking somewhere).
Is it possible to lay out a bunch of controls with the MS Dialog Editor, including a tab control, and create the CPropertySheet using that template, hook up event handlers in a nice way, etc... or some equivalent way of getting the MFC framework to do as much of the creating, drawing and event handling as possible when it comes to a situation like this?
Yes it is possible to create dialog templates and use them in a CPropertyPage.
Each CPropertyPage behaves nearly like a dialog and handles all events for the controls on it.
Also there are features like OnApply that help you to manage the data exchange between the controls and your internal storage.
The central CPropertySheet only creates the dialog that get active. So OnInintDialog for a page is called the first time when the page gets active.
In the MFC since 2010 are more possibilities than a CPropertySheet. You can create tabbed views, that again may be CFormViews. I don't like CDialog based applications so I would prefer a tabbed view in a standard frame with toolbar and menus if appropriate for the application. So another method to unclutter your UI is to choose the MDI interface with tabbed documents... but multiple documents maybe isn't what you want.
Here is a sample of an SDI application with multiple tabbed views.
Also Coeproject shows some more samples here and with splitters and tabs here.
There are at least three solutions paths:
Try to squeeze the situation into the CPropertySheet + CPropertyPage framework which does not naturally allow for additional dialog controls on the CPropertySheet object, and so you will get no framework support this
Place a tab control on an ordinary dialog, and then use the TCN_SELCHANGE messages to fire code that manually hides & shows individual dialog controls subject to the tab control (again no framework support, but this time "within" the tab control instead of outside it)
Follow Mark Ransom's observation that if you can embed one kind of CWnd-based control on a CPropertySheet then you can probably embed any such object, including a CDialog-based object that has been developed in the MFC Dialog Editor
All of these approaches are going to encounter challenges, and it will depend on the specifics of the situation as to which is better. But first you should really consider whether there is a cleaner UI design which would lend itself to a simpler solution.
In my specific case, I saw no cleaner design alternatives, and found it easiest to take the second approach. It left me with some reasonably simple calls to ShowWindow() to show/hide the controls inside the tab control.

MFC - Deactivating all buttons except one

I have a legacy C++ MFC application with a complex GUI with Ribbons. I have a use case as follows : User clicks button A on a ribbon panel and does some work. After his work is done, before he can exercise the rest of the GUI controls, he absolutely must click button B on the same ribbon panel, and failing to click button B in this manner results in a crash if the user exercises some other controls.
Hence, in order to deal with this use case, I figured it would solve my problem if I could disable all of program's GUI controls in Button A's event handler except button B. Button B's event handler then enables the rest of the GUI controls. This way, I ensure that button B always gets pressed after button A.
Hence, my question to you is as follows : Is there a way to disable all GUI controls in one fell swoop, and then enable and disable controls individually?
I know how to enable or disable controls individually, but I have not yet come across an API that allows one to disable all controls.
This way, you get all IDs of the ribbon buttons:
CList<UINT, UINT>& lstItems;
CMFCRibbonBar *pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
pRibbon->GetItemIDsList(lstItems);
Put the three lines in your view's OnInitialUpdate() handler.
Then use the list to compare the IDs coming through your OnCmdMsg() handler to disable all the buttons (except button B).

Embedding dialogs in main dialog and switching them with button click in MFC

I have a design like below:
So basically, I want to embed three dialogs in the application main dialog and switch between them, for each button click i.e., button 1 will show dialog one , button 2 will hide dialog 1 and show dialog 2 .. and so on.
Each dialog will be having a different design and functions.
I tried using CPropertySheet class to Add pages but its GUI is different. It has either option for navigating the dialogs using next / back button , or from a tab control.
None of which is as per my requirement.
So I want to know is it possible to have a design like this in MFC ? If yes how? Which Class/ control should I use.
Any help will be appreciated.
What you can do is use a normal CDialog class, add your buttons to it and also create a frame/rect as a placeholder for where your embedded dialogs are to appear. The following piece of code will create and position your embedded dialog.
CRect rect;
CWnd *pHost = GetDlgItem(ID_OF_YOUR_FRAME_RECT);
pHost->GetWindowRect(&rect);
ScreenToClient(&rect);
pDialog->Create(ID_OF_YOUR_DIALOG, this);
pDialog->MoveWindow(&rect);
pDialog->ShowWindow(SW_SHOW);
On button clicks, you hide the previously shown dialog (SW_HIDE) and show your selected dialog(SW_SHOW) with ShowWindow(...).
If you create your embedded dialogs with IDD_FORMVIEW style in the add resource editor it'll have the proper styles for embedding.
Another option is probably to use an embedded PropertySheet and hide the tab row and programatically change the tabs on the button clicks. I just find it to be too much fuzz with borders, positioning, validation and such for my liking.
If you have the MFC Feature Pack, that first came with VS2008 SP1 and is in all later versions, you might like to consider CMFCPropertySheet. There are a number of examples on the linked page, that are very similar to your design.
For example, this:
What worked for me just using dialog based application is SetParent() method. Dont know why nobody mentioned it. It seems to work fine.
I am doing like below:
VERIFY(pDlg1.Create(PanelDlg::IDD, this));
VERIFY(pDlg2.Create(PanelDlg2::IDD, this));
VERIFY(pDlg3.Create(PanelDlg2::IDD, this));
::SetParent(pDlg1.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg2.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg3.GetSafeHwnd(), this->m_hWnd);
Now I can show or hide a child dialog at will (button clicks) as below:
pDlg1.ShowWindow(SW_SHOW);
pDlg2.ShowWindow(SW_HIDE);
pDlg3.ShowWindow(SW_HIDE);

What are the differences between FormView and Dialog in MFC?

What are the differences between FormView and Dialog in MFC? and can anyone suggest when to use FormView and when to use Dialog?
I have to respectfully disagree with posts above. There is no difference between CFormView and a dialog.
CFormView is a dialog created as modeless and hosted by the frame as a client, resized as frame resize.
It is created from dialog resource you have to supply, as any standalone dialog. All message handlers for dialog controls are the same.
CFormView Create member calls CreateDlg, passing dialog template loaded by the constructor.
CWnd CreateDialog, calls CreateDlgIndirect member that in turn calls CreateDialogIndirect API creating modeless dialog.
You can also embed modeless dialog inside another dialog and it is still a dialog.
A dialog application just shows a dialog (and whatever controls you put in the dialog, plus any other controls you pop up from it, etc.)
A FormView gives you a fairly normal application with a main menu and such -- but the view part can also hold controls.
You'd use a dialog if you just want a dialog, and a formview if you want (possibly multiple) views that can hold controls. Big difference is that making it a dialog changes the basic nature of the entire application, where a formview just changes one view -- you could (for example) also have other (non-form) views if you wanted.
someone_ smiley
To answer your question about dialog versus CFormView.
I rarely use dialog-based application; only in cases that require simple tasks without overhead of more complicated UI.
Most of programmers start with dialog based app and after getting into implementing some functionality, it usually turns that the application needs menu and a toolbar and status bar, data storing/handling object, command routing handling and so on.
I would suggest creating SDI application with non-resizable frame.
You will have a dialog look and all the functionality of the MFC application free. You do not have to use document support if you do not need one.
From the coders view point, FormView supports laying out of UI controls with dialog resource, in WYSIWYG way. So when making a view with a lots of controls FormView could be helpful.
Dialog is not a view. It is totally different. Dialogs are separate windows and normally presented in the modal event loop (or modelessly in special cases).