I am programming a multi-language application which supports dynamical switch from one language to another. Since there is a GetName function in class CMFCRibbonPanel, I think there should also be a SetName function. But unfortunately I can't find the desired function. How do I rename a ribbon panel dynamically? Thank you very much.
the panel name is protected.
you can derive your own class from CMFCRibbon and add a "SetName" method.
class MyRibbonPanel : public CMFCRibbonPanel
{
public:
MyRibbonPanel(LPCTSTR lpszName = NULL, HICON hIcon = NULL ) : CMFCRibbonPanel(lpszName, hIcon) {};
void SetName(CString& name ) { m_strName = name; };
};
for example ( after creating a dummy SDI application in VS2010 )
CMFCRibbonCategory* pCategory = m_wndRibbonBar.AddCategory(_T("&Legume"),
IDR_PROPERTIES,
IDB_PROPERTIES_HC );
MyRibbonPanel* pMyPanel = (MyRibbonPanel*)pCategory->AddPanel(_T("Patate"), m_PanelImages.ExtractIcon(1));
pMyPanel->SetKeys(_T("zc"));
pMyPanel->SetCenterColumnVert();
pMyPanel->SetJustifyColumns();
CString s(_T("sdcasdc"));
pMyPanel->SetName(s);
It might also be useful to others if you have created your ribbons via the VS ribbon UI and don't want to have to manually create them.
Working on from the previous answer.
As panels don't have id's you can't select them to create a pointer too. But if the panels contain elements with ID's you can use these to create a pointer to the panel then rename instead of having to manually create it.
For example I have a combo on my panel, ID_TEST_COMBO
CMFCRibbonComboBox* m_RibbonTestCombo;
MyRibbonPanel* m_ribbonPanel;
m_RibbonTestCombo= DYNAMIC_DOWNCAST(CMFCRibbonComboBox,m_wndRibbonBar.FindByID(ID_TEST_COMBO));
m_ribbonPanel = DYNAMIC_DOWNCAST(MyRibbonPanel, m_RibbonSSSRules->GetParentPanel());
CString s(_T("sdcasdc"));
m_ribbonPanel->SetName(s);
This allows you to change the text without having to manually create the panel
You can try SetWindowText function.
Also you could override the drawing of the text and add you own text there.
Hope this helps.
You'll probably have to remove and re-add it. That's how some other MFC ribbon functions work.
Combining https://stackoverflow.com/a/5120994/6648895 and https://stackoverflow.com/a/25180098/6648895
is what finally worked for me in VS 2013:
MyRibbonPanel* m_ribbonPanel;
m_ribbonPanel = static_cast<MyRibbonPanel*>(m_wndRibbonBar.GetCategory(1)->GetPanel(1));
CString s(_T("sdcasdc"));
m_ribbonPanel->SetName(s);
Related
I am new to MFC and have built an "outlook" style MFC app using the wizard. I've extended the CMFCShellTreetCtrl using CMyShellTreeCtrl and had data member variables and all was working fine. Now I want to move the data over to the CDocument class. Since there is several accesses to the data as each item is clicked or enumerated, I thought I would create a member variable m_pDoc to access the public variables in the CDocument. The problem I'm having, I can't find where to get the CDocument as it appears it's not setup when the trees OnCreate is called. That is in OnCreate
CWnd* pWndMain = AfxGetMainWnd();
ASSERT(pWndMain);
ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)) && !pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an SDI app.
m_pDoc = (CMyDoc*) ((CFrameWnd*)pWndMain)->GetActiveDocument();
returns NULL in m_pDoc and if I tried in an AfterCreate() (which is called after CreateOutlookBar) it's too late as m_pDoc is already being used and get a crash.
// Create and setup "Outlook" navigation bar:
if (!CreateOutlookBar(m_wndNavigationBar, ID_VIEW_NAVIGATION, m_wndTree, m_wndCalendar, 250))
{
TRACE0("Failed to create navigation pane\n");
return -1; // fail to create
}
m_wndTree.AfterCreate();
Any Ideas?
TIA!!
I came up with the following but I'm not sure if this is the proper way. Again, I'm new to MFC (I always have used Win32 directly). This works so it's AN answer, but is it THE correct answer?
POSITION docpos = AfxGetApp()->GetFirstDocTemplatePosition();
CDocTemplate *doctemplate = AfxGetApp()->GetNextDocTemplate(docpos);
docpos=doctemplate->GetFirstDocPosition();
m_pDoc = (CMyDoc*)doctemplate->GetNextDoc(docpos);
ASSERT(m_pDoc);
ASSERT(m_pDoc->IsKindOf(RUNTIME_CLASS(CMyDoc)));
TIA!!
Hi I have two dialog form on C++ MFC 2010 and I want change edit control on from1 by form2 .
How I can done it ?
With all due respect, you should NOT directly access controls of one form from another. This creates unneeded tight coupling between them, exposing internals of one form to another.
I suggest you implement a public setter that identifies the purpose rather than the control ID that might change without you knowing it.
In the target form:
public:
void SetUserName(const char* name)
{
SetDlgItemText(IDC_EDIT1, name);
}
And in the caller:
form1.SetUserName("new text");
You use SetDlgItemText.
form1.SetDlgItemText(IDC_EDIT1, "new text");
I am creating a simple clock application using MFC. My application title appears as follows : "CLOCK - [CLOCK1]". How do I reset it to simply "CLOCK"?
FYI, I have enabled the Document-View architecture.
Put in this override of the MFC title:
void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
SetWindowText(L"CLOCK");
}
There's an answer here, but I feel that the following solution is more "proper".
In addition to overriding CMainFrame::OnUpdateFrameTitle(), you also need to override CMainFrame::PreCreateWindow() as below:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{ cs.style &= ~FWS_ADDTOTITLE;
return CFrameWndEx::PreCreateWindow(cs); // replace CFrameWndEx by CFrameWnd if
} // your CMainFrame is based on CFrameWnd
A note: it is better to use AfxSetWindowText(m_hWnd, _T("foo")) instead of SetWindowText(_T("foo")) to avoid excessive flicker, it checks that the text is different before setting the window text.
You can change it in visual editor by clicking on a your window and typing a title.
Or you can add this code in function OnInitDialog
this->SetWindowText(L"CLOCK");
I've created a read-only edit box in an MFC dialog box. I'm trying to have it so a user clicks in the edit box, which is read-only, it opens a file dialog, and then puts this value into the text box using UpdateData. I'm catching the ON_EN_SETFOCUS message but pressing OK on the file dialog respawns it, so I get caught in an infinite loop.
UpdateData(TRUE);
CFileDialog fileDialog(TRUE,NULL, NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, _T("Text Files(*.txt)|*.txt||"));
if( fileDialog.DoModal() == IDOK )
{
configFile=fileDialog.GetPathName(); //Note to self, this includes filename, getPathName includes filename and path.
}
else
{
return;
}
UpdateData(FALSE);
If you've got any ideas on how this should be done, I would be very grateful.
Alright Mr. Lister I guess I'll add an answer.
First off I would preface this with I would probably simply add a button name "..." to launch the file dialog to the right of the edit box for opening the file dialog as that's the simplest solution and what most windows users will expect.
Another option however is to extend an MFC control. When deciding to extend a control you want to pick one that mostly has the desired behavior and that has a virtual destructor which lends itself to being a subclass. Since you want button like behavior CButton may be a good choice.
Your class interface might look something like this:
class CPathButton : public CButton
{
public:
enum { ID /*= IDC_BUTTON1*/ };
const CString GetPath() const;
const CString GetFileName() const;
const CString GetDirectory() const;
const CString GetExtension() const;
// other useful methods for setting file filters etc
protected:
// add ON_CONTROL(BN_CLICKED, ID, &OnClick) or ON_BN_CLICKED(ID, &OnClick)
DECLARE_MESSAGE_MAP()
// CFileDialog fdlg.DoModal(), m_path = fdlg.GetPathName(), SetWindowText(fdlg.GetFileTitle()), etc
afx_msg void OnClick();
// additional message handlers etc
private:
CString m_path; // save full path for after dialog is closed
};
You can add as much or as little customization as you want depending on if the control will be created dynamically, via the resource file, or whatever. The basic idea being that you display the currently selected file name on the button while storing the full path for other uses as a member so the user doesn't need to see the clutter of a long path with nested directories.
If you don't like the way it looks by default you can override OnPaint and handle WM_PAINT messages and use a custom font, size, or add ellipsis for a long file title. You could also handle re-sizing the button to fit the file title by using text metrics and GetTextExtent to ensure the name fits or simply display a CToolTipCtrl when they hover the mouse over the button so they can see the full name. The CMFCButton from the MFC feature pack in VS2008+ has tool tip functionality built in so if you inherit from that instead of CButton displaying a tool tip would be as simple as calling SetTooltip(m_path)
If you want to get really fancy you could use some of the uxtheme API or new windows animation API.
You can override PreTranslateMessage() in your dialog class, and determine if the edit control was clicked that way:
CEdit m_CEditCtrl;
// ...
BOOL YourDialogClass::PreTranslateMessage(MSG *pMsg)
{
if((pMsg->wParam == VK_LBUTTON) && (m_CEditCtrl.m_hWnd == pMsg->hwnd))
{
// open your file dialog
return TRUE; // Return that the message was translated and doesn't need to be dispatched
}
return CDialog::PreTranslateMessage(pMsg);
}
Update: You can also (and it may be a better idea) to override your CEdit control's CWnd::PreTranslateMessage() function. This would require deriving a class from CEdit.
If you are using VS2008 SP1 or above, the easiest way to ask for a path is with CMFCEditBrowseCtrl. It displays an edit control with a button. The steps to use it are:
Change your edit control's class to CMFCEditBrowseCtrl
Call EnableFileBrowseButton to tell it that you want to browse for files, not folders (you can set a filter and default extension)
When the user clicks the button, a file dialog appears, and when you click OK in it, the selected path is written in the edit control.
In my application I have a number of panes from m_wndspliter classes. What I want to do is at run time show and hide one of these panes. Whilst with the following code I can show and hide the view associated with the pane, I can't temporarily remove the pane itself.
CWnd * pCurView = m_wndSplitter2.GetPane(2, 0);
if( !pCurView == NULL )
{
if( fShow )
{
pCurView->ShowWindow(SW_SHOW);
RecalcLayout();
}
else
{
pCurView->ShowWindow(SW_HIDE);
RecalcLayout();
}
}
Any examples / ideas ?
You need to call CSplitterWnd::DeleteView to do this, which basically means that you have to save your CView elsewhere if you intend to restore it. Usually this is not a problem as all data should be stored in the CDocument rather than CView, but in practice this may not be the case.
The way I have handled this in the past is to have a copy constructor for my CView classes so I could easily store them in temporary variables.
Does this help?
http://www.codeguru.com/cpp/w-d/splitter/article.php/c1543
I have used something very similar myself,
Only the CExtSplitter class from the CodeProject article https://www.codeproject.com/Articles/2707/A-Static-Splitter-with-the-Ability-to-Hide-Show-Mu worked for me.
This is still VC6 code but it worked with minor adaptions.