I'm adding item in a treeview like that:
TVINSERTSTRUCT tvinsert;
tvinsert.hParent = selectedtreeitem;
tvinsert.hInsertAfter = TVI_LAST;
tvinsert.item.pszText = name;
tvinsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvinsert.item.iImage = 0;
tvinsert.item.iSelectedImage = 1;
HTREEITEM ti=(HTREEITEM)SendDlgItemMessage(_hSelf, IDC_TREE1, TVM_INSERTITEM, 0, (LPARAM)&tvinsert);
It works perfectly, but when I try to remove like that:
TreeView_DeleteItem(_hSelf, tvinsert);
It doesn't do anything.
It works with that:
SendDlgItemMessage(_hSelf, IDC_TREE1, TVM_DELETEITEM, TVGN_CARET, (LPARAM)tvinsert);
Related
From this post, I have set up the code by putting in the OnInitDialog event:
LITEM* pItem = new LITEM;
pItem->iLink = 0; // Url index is 0
//LIF_ITEMINDEX is required for iLink, LIF_STATE is required for modifing state
pItem->mask = LIF_ITEMINDEX | LIF_STATE;
//using LIS_DEFAULTCOLORS state
pItem->state = LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS;
pItem->stateMask = LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS;
// Send the LM_SETITEM MESSAGE with pItem
HWND m_hWnd=nil; GetDlgItem(IDC_lbstackoverflow, &m_hWnd);
And from OnCtrlColor event:
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkColor(normal);
pDC->SetDCBrushColor(RGB(255, 255, 255));
return (HBRUSH)GetStockObject(DC_BRUSH);
After the code runs, my result is:
If I click on it, now it works:
But, how I can change text color?
You may not be setting the control state correctly.
Please try the MFC way (it works for me). Add to your dialog class:
CLinkCtrl syslink;
Connect it to the resource ID of your link:
void CMFCApplication4Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SYSLINK1, syslink);
}
and in OnInitDialog add this:
syslink.SetItemState(0, LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS,
LIS_ENABLED | LIS_FOCUSED | LIS_DEFAULTCOLORS);
I see red link with your code in OnCtlColor.
I have been struggling with a problem for weeks. I have an MDI app, explore style. In right side, I have a CTabView, which has 5 CListViews and one CFormView. Depending on what I choose in leftview (CTreeView), I should remove (or add) the FormView from CTabView.
The CTabView could be re-arranged by drag and drop (you could drag CTestFormView as first tab), and they are stored in that order.
Here is the link to have a sample project that simulates the problem:
Explore sample project
In left view, I have:
As soon as I select "Without test-form-view" item, the CTestFormView is removed from CTabView, using CTabView::RemoveView.
To reproduce that, you can do the following simple steps:
Go to "With test-form-view"
Drag CTestFormView as first tab
Select, let's say, CExploreListView4
Select "Without test-form-view" item in left view
The "CTestFormView" has disappeared from CTabView, and the first tab is selected. Right-click on this CExploreListView1, and you will see the context menu of CExploreListView4, not the context menu of CExploreListView1.
If you select another treeitem from leftview ("With-test-form-view"), which add CTestFormView, then all listviews from CTabView are not redrawn correctly. Is there a bug in CTabView ?
With this following code I remove a view in CTabView:
RemoveView(nTabIndex);
This is the code I used to add a view to CTabView dynamically:
int CExploreTabbedView::AddView(CRuntimeClass* pViewClass, const CString& strViewLabel, int iIndex /*= -1*/, CCreateContext* pContext/* = NULL*/, BOOL bAfterCreation/* = FALSE*/)
{
ASSERT_VALID(this);
ENSURE(pViewClass != NULL);
ENSURE(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
CView* pView = DYNAMIC_DOWNCAST(CView, pViewClass->CreateObject());
ASSERT_VALID(pView);
if(! pView->Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), &m_wndTabs, (UINT)-1, pContext))
{
TRACE1(_T("CTabView:Failed to create view '%s'\n"), pViewClass->m_lpszClassName);
return -1;
}
CDocument* pDoc = GetDocument();
if (pDoc != NULL)
{
ASSERT_VALID(pDoc);
BOOL bFound = FALSE;
for (POSITION pos = pDoc->GetFirstViewPosition();! bFound && pos != NULL;)
{
if(pDoc->GetNextView(pos) == pView)
bFound = TRUE;
}
if(! bFound)
pDoc->AddView(pView);
}
pView->SetParent(this);
if(bAfterCreation)
pView->SendMessage(WM_INITIALUPDATE, 0, 0);
m_wndTabs.InsertTab(pView, strViewLabel, iIndex);
int nTabs = m_wndTabs.GetTabsNum();
return nTabs - 1;
}
Could you help me figure out why removing/adding view to CTabView is causing this problem?
You must specify the context where you add the view and set the document there.
Like:
CCreateContext newContext;
newContext.m_pNewViewClass = NULL;
newContext.m_pNewDocTemplate = NULL;
newContext.m_pLastView = NULL;
newContext.m_pCurrentFrame = NULL;
newContext.m_pCurrentDoc = GetDocument();
CTabView *pTab = GetLayoutViewsTab();
int index=pTab->AddView(RUNTIME_CLASS(YourClass), tabName,-1,&newContext);
I want to highlight listview item by default.I mean the by default first item should be highlighted .
Actually I did a sample but it is not working :(
Here is the code snippet I am using for Inserting Items to the list and setting the first row to get highlighted.
BOOL OnInitDialog()
{
CDialog::OnInitDialog();
LVCOLUMN pColumn;
pColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
pColumn.fmt = LVCFMT_LEFT;
pColumn.pszText = L"Product Name";
pColumn.cx = 150;
pColumn.iSubItem = 1;
m_ListCtrl.InsertColumn(2, &pColumn);
::ZeroMemory(&pColumn, sizeof(LVCOLUMN));
pColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
pColumn.fmt = LVCFMT_LEFT;
pColumn.pszText = L"Country";
pColumn.cx = 150;
pColumn.iSubItem = 2;
m_ListCtrl.InsertColumn(3, &pColumn);
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = L"Himami";
m_ListCtrl.InsertItem(&lvItem);
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 1;
lvItem.iSubItem = 0;
lvItem.pszText = L"Shampoo";
m_ListCtrl.InsertItem(&lvItem);
//Trying highlight first item in the list.
m_ListCtrl.SetItemState(0, LVIS_SELECTED ,LVIS_SELECTED);
m_ListCtrl.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
return TRUE;
}
void CListControlFocusDlg::OnListViewItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if ((pNMListView->uChanged & LVIF_STATE) && (pNMListView->uNewState & LVNI_SELECTED))
{
m_ListCtrl.SetCheck(m_ListCtrl.GetSelectionMark(), TRUE);
m_ListCtrl.SetSelectionMark(0);
}
}
After using SetItemState the list control is as follows:
List item is not highlighted.
But I want the item to be highlighted as in the below image.
After Implementing tab-order I am able to get the first item in the list highlighted.
But I am not able to uncheck the first item until unless I press down arrow.when I press down arrow a rectangular selection is coming on to the first item of the list and now I am able to check or uncheck the highlighted item by pressing space bar.This is how the list looks like after I pressed down arrow.
Can anyone please let me know how can I check or uncheck the first item by pressing space bar without pressing down arrow for the rectangular selection.
The cancel button looks like it has the focus. The default behavior of Windows is to set the focus to the first item in the tab order. I would suggest you use the resource editor to set the tab order. The easiest way is to set the tab stop order of the items in the dialog and make the list control the first item. The standard keystroke to edit the tab order is to hit Ctrl+D.
Use LVN_ITEMCHANGED notification
void OnItemchangedList2(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if ((pNMListView->uChanged & LVIF_STATE) && (pNMListView->uNewState & LVNI_SELECTED))
{
m_ListCtrl.SetCheck(m_ListCtrl.GetSelectionMark(), TRUE);
}
}
I'm new to the CMFCMenuButton control; here's my code in OnInitDialog():
// Load application list into menu button
m_ApplicationMenu = CreateMenu();
m_MenuInfoSize = 2;
m_MenuInfo = new MENUITEMINFO[m_MenuInfoSize];
memset(m_MenuInfo, 0, sizeof(MENUITEMINFO) * m_MenuInfoSize);
UINT menuIndex = 0;
BOOL b;
// 1st menu item
memset(m_MenuInfo + menuIndex, 0, sizeof(MENUITEMINFO));
m_MenuInfo[menuIndex].cbSize = sizeof(MENUITEMINFO);
m_MenuInfo[menuIndex].fMask = MIIM_ID | MIIM_STRING | MIIM_DATA;
m_MenuInfo[menuIndex].wID = menuIndex;
m_MenuInfo[menuIndex].dwTypeData = new WCHAR[10];
swprintf_s(m_MenuInfo[menuIndex].dwTypeData, 10, L"%s", L"A1");
m_MenuInfo[menuIndex].cch = wcslen(m_MenuInfo[menuIndex].dwTypeData) + 1;
b = InsertMenuItem(m_ApplicationMenu, menuIndex, TRUE, &(m_MenuInfo[menuIndex]));
menuIndex++;
// 2nd menu item
memset(&m_MenuInfo[menuIndex], 0, sizeof(MENUITEMINFO));
m_MenuInfo[menuIndex].cbSize = sizeof(MENUITEMINFO);
m_MenuInfo[menuIndex].fMask = MIIM_ID | MIIM_STRING | MIIM_DATA;
m_MenuInfo[menuIndex].wID = menuIndex;
m_MenuInfo[menuIndex].dwTypeData = new WCHAR[10];
swprintf_s(m_MenuInfo[menuIndex].dwTypeData, 10, L"%s", L"B2");
m_MenuInfo[menuIndex].cch = wcslen(m_MenuInfo[menuIndex].dwTypeData) + 1;
b = InsertMenuItem(m_ApplicationMenu, menuIndex, TRUE, &(m_MenuInfo[menuIndex]));
menuIndex++;
// Attach menu to CMFCMenuButton
m_ApplicationList.m_bOSMenu = TRUE;
m_ApplicationList.m_bRightArrow = FALSE;
m_ApplicationList.m_bStayPressed = TRUE;
m_ApplicationList.m_bDefaultClick = FALSE;
m_ApplicationList.m_hMenu = m_ApplicationMenu;
// Testing the constructed menu with the dialog's menu bar
::SetMenu(this->m_hWnd, m_ApplicationMenu);
When I ran the application, the CMFCMenuButton displayed a dropdown menu when I clicked on it... but those two items were empty, no text and no image.
I added the last line to test my constructed menu; and the two items showed up in the menu bar properly.
I also tried using a menu created from the resource editor. It showed up fine in menu bar, but in the CMFCMenuButton, there were again empty spaces.
What did I miss?
Try
m_ApplicationMenu = CreatePopupMenu();
Also, you'd better use 1 as the first menuIndex if you want to get the m_nMenuResult of CMFCMenuButton in click event. Because:
CMFCMenuButton::m_nMenuResult
An integer that indicates which item the user selects from the pop-up menu.
The value of this member variable is zero if the user cancels the menu
without making a selection or if an error occurs.
I would like to add a menu item to my main menu and then populate it with items at run time. How would I do this? And besides adding items how would I have a message map entry for them since I do not know the id?
You can create a CMenu object dynamically like this:
CMenu *menu = new CMenu;
menu->CreatePopupMenu();
// Add items to the menu
menu->AppendMenu(MF_STRING, menuItemID, "Text");
...
Then add this sub-menu to your main menu:
wnd->GetMenu()->AppendMenu(MF_POPUP, (UINT_PTR)menu->m_hMenu, "Menu Name");
As for the message map, assuming all your menu item IDs are within a certain range, you can use ON_COMMAND_RANGE to map the entire range to a single function. This function will receive the ID as a parameter, and within the function, you can perform different operations based on the ID.
define the menu's using #define
#define ID_SHOW 2002
#define ID_HIDE 2004
//create a menu object for main menu
CMenu *menu = new CMenu();
menu->CreateMenu();
//another menu object for submenu
CMenu *subMenu = new CMenu();
subMenu->CreatePopupMenu();
subMenu->AppendMenu(MF_STRING, ID_HIDE, _T("four"));
subMenu->AppendMenu(MF_STRING, ID_SHOW, _T("three"));
//append submenu to menu
menu->AppendMenu(MF_POPUP|MF_STRING, (UINT)subMenu->m_hMenu, _T("Advanced") );
SetMenu(menu);
CMenu menuPopup;
menuPopup.LoadMenu(IDR_CNTXT_PLAN);
subMenu.CreatePopupMenu();
subMenu.AppendMenu(MF_STRING, MENU1,"Menu1");
subMenu.AppendMenu(MF_STRING, MENU2,"Menu2");
CMenu* pMenu = menuPopup.GetSubMenu(0);
pMenu->InsertMenu(0,MF_BYPOSITION|MF_POPUP,(UINT)subMenu.m_hMenu,"Layers");
menuPopup.GetSubMenu(0)->InsertMenu(1,MF_BYPOSITION|MF_SEPARATOR,0,"");
menuPopup.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
Following example if you wish to dynamically add menu item & also attach data to that menu item.
struct MyStruct
{
int abc;
};
CMenu MyMenu;
MyMenu.CreatePopupMenu();
CMenu MyMainMenu;
VERIFY(MyMainMenu.LoadMenu(IDR_MAIN_MENU_ID));
MyMainMenu.InsertMenu(0, MF_POPUP, (UINT_PTR)MyMenu.m_hMenu, _T("Main Menu"));
const int iMenuAdds = 5;
for (int i = 0; i < iMenuAdds; ++i)
{
MyStruct myStruct;
myStruct.abc = i+10001;
CString MenuDesc;
MenuDesc.Format(_T("MenuNo: %d"), i);
MENUITEMINFO tmpItem;
tmpItem.fMask = MIIM_STRING | MIIM_ID | MIIM_DATA;
tmpItem.fType = MFT_STRING;
tmpItem.fState = MFS_ENABLED;
tmpItem.wID = i + 101; //See note 1. below.
tmpItem.dwItemData = (ULONG_PTR)&myStruct; //data set.
tmpItem.dwTypeData = MenuDesc.GetBuffer(); //string description
tmpItem.cch = MenuDesc.GetLength();
tmpItem.cbSize = sizeof(tmpItem);
MyMenu.InsertMenuItem(i, (LPMENUITEMINFO)& tmpItem, FALSE);
}
To retrieve menu item & associated data:
CMenu* pPopup = &MyMenu; //or CMenu* pPopup = MyMainMenu.GetSubMenu(0); depending on parent.
ULONG_PTR lRetVal = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, this, NULL);
//^^lRetVal should return same value as tmpItem.wID above.
MENUITEMINFO tmpItem;
tmpItem.cbSize = sizeof(MENUITEMINFO);
tmpItem.fMask = MIIM_STRING | MIIM_ID | MIIM_DATA;
tmpItem.fType = MFT_STRING;
TCHAR dwTypeData[256];
tmpItem.dwTypeData = dwTypeData;
tmpItem.cch = 256;
pPopup->GetMenuItemInfo(lRetVal, &tmpItem, FALSE);
MyStruct *myStruct = (MyStruct*)tmpItem.dwItemData; //and now we have our data.
Used as your #define & can be used for ON_COMMAND_RANGE(idFirst, idLast, Function), so would still need to have some sort of defined range if you were planning on using ON_COMMAND_RANGE. Alternatively: use command range for dynamic menu or create your own within the data set. Also need to make sure any ranges used do not conflict with any already #defined menu items on the same or parent menu.
Added above as I found this thread from googling due to an issue & I was already using the accepted answers method for adding menu items.