MFC, How do I change the capiton of TabCtrl - mfc

I know the InsertItem is for add new tab in tabctrl, but I need change the caption of tab after create, I use keyword tabctrl and caption to search the old article ,but no relation problem to solve it, hot do I change the caption of tab page...

OK,
I got the solution, as follow code
TC_ITEM TabCtrlItem;
switch(m_tabCtrl.GetCurSel())
{
case TAB1:
TabCtrlItem.mask = TCIF_TEXT;
TabCtrlItem.pszText = _T("Some Text");
m_tabCtrl.SetItem(TAB1, &TabCtrlItem );

Related

MFC MDI Designing user preferences dialog GUI layout functionality

In this instance I am not "stuck" but looking for some 'guidance' on how to perform a GUI layout mechanism that makes sense and easy to construct. I am using a TreeControl that visually "matches" Winamp's options/preferences dialog for all the settings and program options.
TO BE CLEAR: This is not something I've ever attempted and looking for user input to help me get across the finish line.
I have 6 items in the 'tree' (the 'parent') and 5 'subitems'. I have it fully constructed and I can get the data from whatever node is selected (which I'll post below images).
I am using a "do.Modal dialog" and, when I click on the tree node, I want the right side of the dialog to update to the needed controls for that node function. The execution of controls through "show" and "hide" to me seems pretty easy. The issue I have is the how to do the visual "static" controls in the resource editor when each "node paged" controls may or may not sit on top of each other visually during design time. During run time, when each node is selected on the nodes controls will be active but during design time, I may have controls sitting on top of each other and will be a logistical nightmare trying to sort out their positions etc.
How do I resolve that aspect of building it? I think of it as a select: 'node' show: 'option page controls' so I get the logic; I'm just wondering if I should have separate "popup" pages and call those … or deal with the controls directly. Does that makes sense?
I've done some searching on how to do this, but the examples are all over the place and I figured asking here makes the most sense. I'm sure there are multiple ways to do this, I'm just looking for the shortest path and easiest to maintain and possibly expand on the options in the future.
The examples of the dialog and the source code I'm using:
Here is the initialization code:
BOOL CSettingsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
HTREEITEM hParent, hToolbars, hColorScheme, hTabStyles, hPowerUser,
hResetApp;
//HTREEITEM hCompany, hLevel, hLevelNext; // Used in core example, not needed here
hParent = m_TreeCtrl.InsertItem((L"Preferences"), TVI_ROOT);
hToolbars = m_TreeCtrl.InsertItem((L"Toolbars"), hParent);
hColorScheme = m_TreeCtrl.InsertItem((L"Color Scheme"), hParent);
hTabStyles = m_TreeCtrl.InsertItem((L"Tab Styles"), hParent);
hPowerUser = m_TreeCtrl.InsertItem((L"Power User"), hParent);
hResetApp= m_TreeCtrl.InsertItem((L"Reset All Options"), hParent);
m_TreeCtrl.Expand(hParent, TVE_EXPAND);
m_TreeCtrl.SelectItem(hParent);
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Preferences Settings"));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Here is the dialog framework that I'm starting from scratch with just to arrive here:
void CSettingsDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
//LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
//SetDlgItemInt(IDC_TXT_TREE1, m_TreeCtrl.GetItemData(pNMTreeView->itemNew.hItem));
//*pResult = 0;
HTREEITEM sel = m_TreeCtrl.GetSelectedItem();
CPoint point;
CString str;
GetCursorPos(&point);
m_TreeCtrl.ScreenToClient(&point);
UINT flags = 0;
HTREEITEM hitItem = m_TreeCtrl.HitTest(point, &flags);
if (hitItem && sel != hitItem)
{
sel = hitItem;
m_TreeCtrl.SelectItem(sel);
str = m_TreeCtrl.GetItemText(sel);
//MessageBox((LPCTSTR)str); // Just to verify.
}
if (str == "Preferences")
{
this->SetWindowText(_T("Preferences Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Preferences Settings"));
}
if (str == "Toolbars")
{
this->SetWindowText(_T("Toolbars Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Toolbars Settings"));
}
if (str == "Color Scheme")
{
this->SetWindowText(_T("Color Scheme"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Color Scheme Settings"));
}
if (str == "Tab Styles")
{
this->SetWindowText(_T("Tab Styles Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Tab Styles Settings"));
}
if (str == "Power User")
{
this->SetWindowText(_T("Power User Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Power User Settings"));
}
if (str == "Reset All Options")
{
this->SetWindowText(_T("Reset All Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Reset All Settings"));
}
*pResult = 0;
}
So as shown, you can see that I have the ability to change the static caption to the "active" page node that is selected from the tree. I'm looking to solve the best way to handle the GUI elements that will go on the right side....
Some controls for example will be:
Color scheme Node: 5 check boxes for theme changing
Toolbars Node: Radio button for Docked or Floating
Power User Node: Checkbox to disable user warning within program operation
Tab Styles Node: Radio buttons to select flat, 3d, whatever.
and when the user "selects" whatever it writes it to the registry and then I call the function to read the data blah blah blah...
So that is where I'm at. Does anyone have any suggestions on a course of action, so I don't paint myself into a corner?
Although I can't actually speak for how the authors of the "Winamp" software implemented their UI, I would suggest that you consider using a property sheet for your case, where each set of controls can be implemented as separate property pages, each of which will be defined (both in the resource script and in the C++ code) in ways very similar to individual modal dialog boxes.
The 'classic' property sheet has a horizontal row of tabs (normally, at the top of the sheet) to select each page, as shown in the sample below. Indeed, some sources/platforms refer to a property sheet as a "tabbed dialog".
However, the new(ish) CMFCPropertySheet class allows you to replace that tab control with one of several other options, which will show as separate 'panes' (on the left-hand side of the sheet). To use one of these alternative styles, call the SetLook() member function in your constructor override with the CMFCPropertySheet::PropSheetLook_Tree enum value. The example shown in the link is not exactly what you have shown in your question, but the CMFCPropertySheet and CMFCPropertyPage classes allow many, many customizations to their appearance and style.
I have never actually used the PropSheetLook_Tree style, but the image below shows "one I made earlier" with the PropSheetLook_OutlookBar style.

How to hide propertysheet?

I had a propertysheet where I am facing an issue in hiding the sheet.I will briefly explain what I had done.
In the PropertySheet OnWizardFinish() I am trying hide the sheet and do the following ,
BOOL CSecondEditpage::OnWizardFinish()
{
BOOL bAsyRet = ShowWindowAsync(m_hWnd,SW_HIDE);
int MsgRet = ::MessageBox(NULL,L"Do you want to restart",L"Test",MB_YESNO | MB_ICONINFORMATION);
if(IDYES == MsgRet)
{
SystemRestart();
}
else
{
//Do Nothing..
}
return CPropertyPage::OnWizardFinish();
}
So here only the message box should be visible and the sheet should be hidden this is what I am expecting that ShowWindowAsync does.But in the background sheet still exists.
Same thing I tried with a dialog based application there it is working as expected like as,the background window is hidden and only message box is shown .
For more details:
And now when I click finish the sheet should be hidden and should show a message box something like this,
Can anyone please let me know how can achieve this in propertysheet wizard.
You're trying to hide PropertyPage not a PropertySheet.
Do like this.
CPropertySheet* prop = (CPropertySheet*)GetParent();
ShowWindowAsync(prop->m_hWnd, SW_HIDE);

How to map help id of a error messagebox in MFC?

I have a dialog box in MFC which has help button.
I am able to map help button with my help content.
on my dialog box, I have a edit box also i which user can enter anything.
i am validating the edit control box that if something wrong user enters it will open
error message box which display error and having help button too.
i wanted to map this error message box helpid to my content (which different from parent dialog box) but whenever click help button it shows me parent help content.
NOTE: i tried both APIs Afxmessagebox and Messagebox.
Solution from my side , (i don't know if it is correct )
Create another dialog box and mapp to help id as i di fro parent dialog box.
and treat this dialog box as a error messagebox with domodal.
I feel i we can do this with messagebox itself but didn't find anything on web.
What i tried -
I tried following link but couldn't get success.
http://www.codeproject.com/Articles/562/Add-a-Help-Button-to-a-MessageBox
VOID CALLBACK MsgBoxCallback(LPHELPINFO lpHelpInfo)
{
CString str = AfxGetApp()->m_pszHelpFilePath;
AfxGetApp()->WinHelp(lpHelpInfo->dwContextId);
}
UINT AfxMessageBox(HWND hWnd, LPCTSTR szText, UINT nType, UINT nIDHelp = 0)
{
MSGBOXPARAMS mbp;
memset(&mbp, 0, sizeof mbp);
mbp.cbSize = sizeof MSGBOXPARAMS;
mbp.hwndOwner = hWnd;
mbp.hInstance = AfxGetInstanceHandle();
mbp.lpszText = szText;
AfxGetApp()->m_pszHelpFilePath = "C:\\Program Files (x86)\\\HELP\\130.htm";
// if you wanted to specify a different caption, here is where you do it
mbp.lpszCaption = AfxGetAppName();
// if Help ID is not 0, then add a help button
if (nIDHelp != 0)
{
mbp.dwStyle = nType | MB_HELP;
}
else
{
mbp.dwStyle = nType;
}
// mbp.lpszIcon = ; // note, you could provide your own custom ICON here!
mbp.dwContextHelpId = nIDHelp;
mbp.lpfnMsgBoxCallback = &MsgBoxCallback;
mbp.dwLanguageId = 0x0409;
return ::MessageBoxIndirect(&mbp);
}
Here's how to do it:
Create a string resource for each message box.
Be sure to name the resource with an IDP_ prefix. Although IDS_ also corresponds to strings, the makehm command-line tool will not look for IDS_ when it builds the HTMLDefines.h file.
Change your message box call(s) to AfxMessageBox(IDP_FOO, MB_OK|MB_HELP, IDP_FOO), substituting in other flags, as needed.
(Note: I had another answer, but it was way off, so I decided to start clean with a new answer instead of updating it.)

Incorrect displaying of menu items text in status bar - wxWidgets 3.0

I am writing simple GUI software using wxWidgets 3.0 in CodeBlocks 13.12, on Win 7 x64 machine.
I would like to create a menu for the frame, and each item in the frame should make a different text appear in the status bar when highlighted. Below is what I have done so far ( only the menu part of code ). Menu and status bar appear as planned. The problem is that every item ( in File and Data sub menus ) when highlighted displays "Save project" in the status bar - which is the very first item in the first sub menu. How to change this so that proper menu item names are displayed ?
CODE :
wxMenuBar* mbar = new wxMenuBar();
wxMenu* fileMenu = new wxMenu(_T(""));
//fileMenu->Append(, _("&"), _("")));
fileMenu->Append(SaveProject, _("&Save project"), _("Save project"));
fileMenu->Append(SaveProjectAs, _("&Save project as"), _("Save project as"));
fileMenu->Append(OpenNewProject, _("&Open new project"), _("Open new project"));
fileMenu->Append(OpenExistingProject, _("&Open existing project"), _("Open existing project"));
fileMenu->AppendSeparator();
fileMenu->Append(Quit, _("&Quit"), _("Quit"));
mbar->Append(fileMenu, _("&File"));
wxMenu* dataMenu = new wxMenu(_T(""));
//fileMenu->Append(, _("&"), _("")));
dataMenu->Append(ImportData, _("&Import data"), _("Import data"));
dataMenu->Append(ExportData, _("&Export data"), _("Export data"));
dataMenu->Append(SavaDataAs, _("&Save data as"), _("Save data as"));
mbar->Append(dataMenu, _("&Data"));
mainFrame->SetMenuBar(mbar);
I suspect the problem is due to your use of duplicate menu IDs (e.g. SaveProject is used twice). While it's not clear why should this result in the observed behaviour, it is pretty clear that you cannot reuse the menu IDs as you will have no way of distinguishing between the events generated by the two items with the same ID. So don't do this.

CMFCPropertyGridProperty with multi line edit box

How to create a multi line property with edit box? I need one more property that will show text in multi line box.
CMFCPropertyGridProperty* pGroup1 = new CMFCPropertyGridProperty(_T("Appearance"));
pGroup1->AddSubItem(new CMFCPropertyGridProperty(_T("Name"), (_variant_t) _T(""), _T("Specifies the text that will be displayed in the property")));
pGroup1->AddSubItem(new CMFCPropertyGridProperty(_T("Comments"), (_variant_t) _T(""), _T("Specifies the text that will be associated with the property")));
m_wndPropList.AddProperty(pGroup1);
It seems that multi-line properties are not implemented in MFC Property Grid. You can create a custom property with a button and show your own dialog with multi-line edit control when user click this button.
You can do it like in old style editors (replacing "\n","\n" so user can divide lines by "\n"):
Initialization:
CString s = m_initial_params.m_info;
s.Replace("\n","\\n");
CMFCPropertyGridProperty* pProp = new
CMFCPropertyGridProperty(misc_get_str_my(IDS_INFO),
(_variant_t) s, misc_get_str_my(IDS_INFO));
pProp->SetData(E_PROPERTY_DATA::OBJ_INFO);
pPropCtrl->AddProperty(pProp);
Reading Value:
int nProperty = pProperty->GetData();
if(E_PROPERTY_DATA::OBJ_INFO == nProperty)
{
m_initial_params.m_info = pProperty->GetValue().bstrVal;
m_initial_params.m_info.Replace("\\n","\n");
}