CMFCPropertyGridProperty with multi line edit box - c++

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");
}

Related

New Buttons in Interactive Grid toolbar

I need to add a new button to existing IG toolbar, which will set a specific value in the table column and then save the record.
Is there any way to create new buttons/change the behavior of existing Interactive Grid toolbar buttons?
I see you are using APEX 5.1. Yes, you can customise toolbar buttons in an interactive grid. For example, you can modify the look and feel of the Save and Add Row buttons and also add a Delete button. Select your interactive grid region and in the property editor, enter a value for Advanced > Static ID. Select Attributes > Advanced > JavaScript Initialization Code and input the following:
function(config) {
let $ = apex.jQuery,
toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),
toolbarGroup = toolbarData.toolbarFind("actions3");
addrowAction = toolbarData.toolbarFind("selection-add-row"),
saveAction = toolbarData.toolbarFind("save"); // Save button
// adding a "Delete" button
toolbarGroup.controls.push({type: "BUTTON",
action: "selection-delete",
icon: "icon-ig-delete",
iconBeforeLabel: true,
hot: true
});
// Modifying the buttons
addrowAction.icon = "icon-ig-add-row";
addrowAction.iconBeforeLabel = true;
addrowAction.hot = true;
saveAction.iconBeforeLabel = true;
saveAction.icon ="icon-ig-save-as";
saveAction.hot = true;
//storing the config
config.toolbarData = toolbarData;
return config;
}
Now run the page to see the customisation.
Here's a nice video that shows how to customise IG toolbar.
https://www.youtube.com/watch?v=_PBdBAfPBfQ

Make icon above text for MFC Button

I wanted to create CMFCButton dynamically at runtime (Icon with Text on the button). The icon is created successfully but I wanted to display the icon above text.
I want to implement "Image on Top" property found in Resource Editor for the button.
My Code:
CMFCButton* appButton = new CMFCButton;
appButton->Create( _T("MfcButton1"), WS_CHILD | WS_VISIBLE, CRect(10, 10, 70, 50), this );
appButton->SetIcon( sfi.hIcon );
(according to the "NewControls" MFC sample).
To set an image in a CMFCButton use CMFCButton::SetImage.
To set the image above (or below) the text you can use the undocumented variable m_bTopImage
appButton->m_bTopImage = TRUE;
FYI: the complete samples can be downloaded from :
http://www.microsoft.com/en-us/download/details.aspx?id=5718

Split view in two with a menu button? (MFC)

I have an MFC program written that reads files, stores the data, and draws it as text on the client view.
I want to make a menu button View->Split that splits the client area into two, separately scrolling views displaying the same data.
I saw some things about CWndSplitter online and read through some documentation but none of it has proved to be useful because they talk about using OnCreate and deleting the default view to get it to work. This is not an option. I want to keep the default view, but split it in two if the user clicks the button.
I've currently created a CWndSplitter member variable and defined a menu button event handler in my SDI-1View.cpp. When called, it does absolutely nothing but cause the screen to flicker and a second click crashes the program.
void CSDI1View::OnViewSplit32778()
{
// TODO: Add your command handler code here
/*
int rows = 2;
int columns = 1;
if (!m_wndSplitter.CreateStatic(this, rows, columns))
return;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL) ||
(!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL)))
{
m_wndSplitter.DestroyWindow();
return;
}
*/
}
Can anyone tell me what the normal approach to splitting a client view in half is? I just want to integrate that into an event handler.
Any help would be greatly appreciated.
Thanks.
--------------------------------EDIT----------------------------------
I now have the following code in my Split button event handler, thanks to the outline provided by xMRi, but it is still not working properly...
void CMainFrame::OnViewSplit()
{
// TODO: Add your command handler code here
//calculate client size
CRect cr;
GetClientRect(&cr);
if (!m_mainSplitter.CreateStatic(this, 2, 1))
{
MessageBox(_T("Error setting up splitter frames! (CreateStatic)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
// Set the parent of the splitter window to the current view
CSDI1View * view = CSDI1View::GetView();
m_mainSplitter.SetParent(this);
view->SetParent(&m_mainSplitter);
// Create a CCreateContext
CCreateContext cc;
CRuntimeClass* prt = RUNTIME_CLASS(CSDI1View);
cc.m_pNewViewClass = prt;
cc.m_pCurrentDoc = view->GetDocument();
cc.m_pNewDocTemplate = NULL;
cc.m_pLastView = NULL;
cc.m_pCurrentFrame = this;
if (!m_mainSplitter.CreateView(0, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 1)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
if (!m_mainSplitter.CreateView(1, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 2)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
m_bInitSplitter = TRUE;
}
Upon clicking the view->split button, I get a "Debug Assertion Error" popup and the first call to CreateView returns FALSE, displaying my messagebox: "Error setting up splitter frames! (CreateView 1)"
A static splitter is for a static split--i.e., a window that's always split. You usually use it when you want to have a different view in each pane of the split (e.g. display a column of numbers in one pane, and a graph in the other pane).
For a situation like yours that you want to be able to have the window, then later split it and have two essentially identical views, you (at least normally) want to use a dynamic splitter.
At least normally, you create the splitter when you create the view. That will create a window that has a handle at the top, right-hand corner that the user pulls down to split the view:
To split the window, the user pulls down on the handle:
When the split is where they want it, they release the mouse button, and the view splits into two separately scrollable sections:
Since you didn't specify whether you wanted vertical or horizontal splitting, I set this one up to allow either or both:
The code for this looks something like this:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
return my_splitter.Create(this,
2, 2, // 2 rows, 2 columns
CSize(20, 20), // minimum pane size
pContext);
}
where my_splitter is defined something like this:
CSplitterWnd my_splitter;
If you want to use a splitter window on demand, you need to change the parent of the current view.
So the steps are:
create a simple SDI application
On demand create a splitter window
Use SetParent to the current view and set it as a parent in the splitter window.
Create another window in the second splitter.
And the way back.
Use SetParent and attach the normal view back to the main frame.
Destroy the splitter
There are active samples how to switch a view in a current document (MSDN). It helps you how IDs must be replaced and changed.

Make single items editable in a list control (C++, MFC)

I have a list control (CListCtrl) with two columns (Name, Value). I add entries dynamically from a xml file. Now i want to make the Value-Column editable and subscribe the Edit-Event to write the changes to the xml. How i do this?
My Code now:
LVITEM item_value;
item_value.iItem = row;
item_value.iSubItem = 1;
item_value.mask = LVIF_TEXT;
item_value.pszText = value;
ctrl->SetItem(&item_value);
Placing an edit control in CListCtrl is easier by setting the LVS_EDITLABELS style. Use EditLabel() function to place an edit control for a specific item, and retrieve the new text from edit control using GetEditControl() function by listening to the notification LVN_ENDLABELEDIT.

MFC, How do I change the capiton of TabCtrl

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 );