Edit Label in TreeCtrl only on double click event of the items - mfc

In tree control, I want to edit labels only when double clicking the item text. I don't want to edit the label on single click on the item text.
How to achieve it?
I tried below code but in-place edit control is never getting display.
void CMyTreeCtrl::OnNMDblclkTree1( NMHDR *pNMHDR, LRESULT *pResult )
{
CPoint p;
GetCursorPos( &p );
ScreenToClient( &p );
HTREEITEM h = HitTest( p );
if( h )
{
if(EndEditLabelNow( FALSE ) )
{
SelectItem( h );
EditLabel( h );
}
}
void CMyTreeCtrl::OnTvnBeginlabeleditTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
if ( !m_bEditLabel)
*pResult = 1;
else
*pResult = 0;
}
void CMyTreeCtrl::OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
{
TV_DISPINFO *ptvinfo;
ptvinfo = (TV_DISPINFO *)pnmhdr;
if (ptvinfo->item.pszText != NULL)
{
ptvinfo->item.mask = TVIF_TEXT;
SetItem(&ptvinfo->item);
}
*pLResult = 0;
m_bEditLabel = false;
}
Thanks.

Related

virtual CMFCListctrl scrollbar flickering

I am using virtual list control.
I am refreshing/loading data the list control for each seconds(continuously).
I am using the following code:
bool CMyListCtrl::Init(CWnd* pParent)
{
CRect rectDummy;
if(!Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_OWNERDATA,
rectDummy, pParent, IDC_LIST1))
return false;
#define LVS_EX_DOUBLEBUFFER 0x00010000
SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_DOUBLEBUFFER);
InsertColumn(0,_T("#"),LVCFMT_LEFT, 20,1);
InsertColumn(1,_T("Tag Name"),LVCFMT_LEFT, 100,1);
InsertColumn(2,_T("Data Type"),LVCFMT_LEFT, 50,1);
InsertColumn(3,_T("Address/Exp"),LVCFMT_LEFT, 50,1);
InsertColumn(4,_T("# of Characters"),LVCFMT_LEFT, 110,1);
InsertColumn(5,_T("Initial Value"),LVCFMT_LEFT, 50,1);
InsertColumn(6,_T("Retentive Flag"),LVCFMT_LEFT, 50,1);
InsertColumn(7,_T("PLC/Int/Exp"),LVCFMT_LEFT, 50,1);
InsertColumn(8,_T("Write Tag"),LVCFMT_LEFT, 50,1);
return true;
}
void CMyListCtrl::UpdateUI(std::vector<CTagList*>* vpTags)
{
m_vpTags=vpTags;
if(m_vpTags==NULL) return;
if(m_iSortedColumn>-1 && m_vpTags->size()>1)
std::sort(m_vpTags->begin(), m_vpTags->end(), S_TagComparator(m_iSortedColumn,m_bAscending,this));
SetItemCountEx(m_vpTags->size(),LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL);
}
void CMyListCtrl::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
*pResult = 0;
LV_ITEM* pItem = &(pDispInfo)->item;
CDrawObjLad* pObj = m_vInss[pItem->iItem];
//update column text
if(pItem->mask & LVIF_TEXT){
CString text;
switch(pItem->iSubItem){
case 1: text = CUtils::Format(_T("%d"),pItem->iItem+1);break;
case 2: text = pObj->GetElementName(); break;
case 3: text = CUtils::Format(_T("%d"),pObj->m_nRow);break;
case 4: text = CUtils::Format(_T("%c"),0x40+pObj->m_nCol);break;
}
lstrcpyn(pItem->pszText, text, pItem->cchTextMax);
}
}
The list control vertical scrollbar seems to flickering or jumbs up and down. How to avoid it?
I tried ON_WM_ERASEBKGND() in list control but it didn't help me.

Deleting the checked items in listcontrol with extended style LVS_EX_CHECKBOXES

I am new to MFC. I have a listcontrol with LVS_EX_CHECKBOXES. I want to add delete functionality for the checked items in the listcontrol.
So far I have written a handler code to get notification from the CListCtrl:
void CAppDlg::OnListItemchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLISTVIEW pLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
if (pLV->uNewState) // item checked
{
//delete functionality
}
//by default allow change
*pResult = 0;
}
Can anyone help me. I have searched for examples over the net but I can't find any.
Here is the proper way of determining if the item check state has changed:
void CAttrSelectorDlg::OnLvnItemchangedAttrList(NMHDR* pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
int nItem = pNMLV->iItem;
// get old check box state
BOOL bPrevState = ( BOOL ) ( ( ( pNMLV->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 );
if ( bPrevState < 0 ) // On startup there's no previous state
bPrevState = FALSE; // assing as false (unchecked)
// get new check box state
BOOL bNewState = ( BOOL ) ( ( ( pNMLV->uNewState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 );
if ( bNewState < 0 ) // non-check box notification
bNewState = FALSE;
if (bPrevState != bNewState)
{
// state changed. DO STUFF
}
*pResult = 0;
}
For your task I'd suggest using Delete button to delete selected (checked) items:
for (int i=0; i<m_AttrList.GetItemCount(); i++)
{
BOOL bCheck = m_AttrList.GetCheck(i);
if (bCheck)
{
// item is checked
}
}

MFC C++ Tray Application Issue

I'm creating taskbar icon of a mfc application and in MyView.cpp file I've written
static const UINT WMU_NOTIFY_TASKBAR_ICON = ::RegisterWindowMessage(_T("NOTIFY_TASKBAR_ICON"));
IMPLEMENT_DYNCREATE(CMyView, CView)
BEGIN_MESSAGE_MAP(CMyView, CView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
// added messages by the developer
ON_REGISTERED_MESSAGE(WMU_NOTIFY_TASKBAR_ICON, OnNotifyTaskbarIcon)
END_MESSAGE_MAP()
//...
void CMyView::AddTaskbarIcon()
{
DWORD dwMessage = NIM_ADD;
NOTIFYICONDATA nid;
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = HWND(AfxGetApp()->m_pMainWnd);
nid.uID = 0;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = WMU_NOTIFY_TASKBAR_ICON;
nid.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_SS_ICON));
nid.dwInfoFlags = NIIF_INFO;
::Shell_NotifyIconW(dwMessage, &nid);
}
LRESULT CMyView::OnNotifyTaskbarIcon( WPARAM wParam, LPARAM lParam )
{
UINT uID = (UINT)wParam;
UINT uMouseMsg = (UINT)lParam;
switch(uMouseMsg)
{
case WM_LBUTTONDOWN:
break;
case WM_LBUTTONDBLCLK:
//if(IsIconic())
{
break;
}
case WM_RBUTTONDOWN:
{
// must be implemented:
// app popup menu will be showed
CMenu* pMenu = GetMenu();
if( pMenu )
{
CMenu *pSubMenu = NULL;
pSubMenu = pMenu->GetSubMenu( 0 );
{
SetForegroundWindow(); // *** little patch here ***
POINT pointCursor;
::GetCursorPos( &pointCursor );
pSubMenu->TrackPopupMenu( TPM_RIGHTALIGN,
pointCursor.x, pointCursor.y,
this );
}
}
}
break;
case WM_RBUTTONDBLCLK:
break;
case WM_MOUSEMOVE:
break;
}
return 0L;
}
and in My.cpp
BOOL CMyApp::InitInstance()
{
//...
myViewPtr->AddTaskbarIcon();
//...
}
the app launches, the icon appears on the taskbar but it disappears on mouse hovering.
Have I done something wrong? Thanx
AfxGetApp()->m_pMainWnd points to the main frame window, not to the view. I suspect that the frame window is receiving the WMU_NOTIFY_TASKBAR_ICON message and not handling it so Windows removes the icon.
You could either handle the message in the frame window class, or pass the handle to the view instead, like this:
void CMyView::AddTaskbarIcon()
{
...
nid.hWnd = GetSafeHwnd();
...
}

How to check if an other program is running in fullscreen mode, eg. a media player

How can I check if an other app is running in full screen mode & topmost in c++ MFC?
I just want to disable all of my auto dialogs (warnings) if media player or other players are running. (Like silent/gamer mode in Avast.)
How could I do that?
Thank you.
using a combination of EnumWindows, GetWindowInfo and GetWindowRect does the trick.
bool IsTopMost( HWND hwnd )
{
WINDOWINFO info;
GetWindowInfo( hwnd, &info );
return ( info.dwExStyle & WS_EX_TOPMOST ) ? true : false;
}
bool IsFullScreenSize( HWND hwnd, const int cx, const int cy )
{
RECT r;
::GetWindowRect( hwnd, &r );
return r.right - r.left == cx && r.bottom - r.top == cy;
}
bool IsFullscreenAndMaximized( HWND hwnd )
{
if( IsTopMost( hwnd ) )
{
const int cx = GetSystemMetrics( SM_CXSCREEN );
const int cy = GetSystemMetrics( SM_CYSCREEN );
if( IsFullScreenSize( hwnd, cx, cy ) )
return true;
}
return false;
}
BOOL CALLBACK CheckMaximized( HWND hwnd, LPARAM lParam )
{
if( IsFullscreenAndMaximized( hwnd ) )
{
* (bool*) lParam = true;
return FALSE; //there can be only one so quit here
}
return TRUE;
}
bool bThereIsAFullscreenWin = false;
EnumWindows( (WNDENUMPROC) CheckMaximized, (LPARAM) &bThereIsAFullscreenWin );
edit2: updated with tested code, which works fine here for MediaPlayer on Windows 7. I tried with GetForeGroundWindow instead of the EnumWindows, but then the IsFullScreenSize() check only works depending on which area of media player the mouse is in exactly.
Note that the problem with multimonitor setups mentioned in the comment below is still here.
in my oppinion a very little improvement
bool AreSameRECT (RECT& lhs, RECT& rhs){
return (lhs.bottom == rhs.bottom && lhs.left == lhs.left && lhs.right == rhs.right && lhs.top == rhs.top) ? true : false;
}
bool IsFullscreenAndMaximized(HWND hWnd)
{
RECT screen_bounds;
GetWindowRect(GetDesktopWindow(), &screen_bounds);
RECT app_bounds;
GetWindowRect(hWnd, &app_bounds);
if(hWnd != GetDesktopWindow() && hWnd != GetShellWindow()) {
return AreSameRECT(app_bounds, screen_bounds);
}
return false;
}
And thanks to priviose answer
BOOL CALLBACK CheckFullScreenMode ( HWND hwnd, LPARAM lParam )
{
if( IsFullscreenAndMaximized(GetForegroundWindow()) )
{
* (bool*) lParam = true;
std::cout << "true";
return FALSE;
}
return TRUE;
}
int main() {
bool bThereIsAFullscreenWin = false;
EnumWindows( (WNDENUMPROC) CheckFullScreenMode, (LPARAM) &bThereIsAFullscreenWin );
}

Make caption icon become drag source like explorer window

I made an editor which written in pure WinAPI. Some users want the caption icon become a drag source of the file that opened in editor, like what the explorer window does. I have no idea to implement such feature. Can someone give me example please?
Here is a sample showing how to use the system menu ("caption icon") to detect when to initiate a drag-drop operation:
class SysMenuDragSample
: public CWindowImpl< SysMenuDragSample, CWindow, CFrameWinTraits >
{
private:
static const UINT WM_SHOWSYSTEMMENU = 0x313;
bool mouse_down_in_sys_menu_;
public:
BEGIN_MSG_MAP_EX( SysMenuDragSample )
MSG_WM_NCLBUTTONDOWN( OnNcLButtonDown )
MSG_WM_NCLBUTTONUP( OnNcLButtonUp )
MSG_WM_MOUSEMOVE( OnMouseMove )
MSG_WM_LBUTTONUP( OnLButtonUp )
END_MSG_MAP()
SysMenuDragSample()
: mouse_down_in_sys_menu_( false )
{
}
void BeginDragDropOperation()
{
// TODO: Implement
}
void OnNcLButtonDown( UINT hit_test, CPoint cursor_pos )
{
if( hit_test == HTSYSMENU )
{
mouse_down_in_sys_menu_ = true;
SetCapture();
// NOTE: Future messages will come through WM_MOUSEMOVE, WM_LBUTTONUP, etc.
}
else
SetMsgHandled( FALSE );
}
void OnNcLButtonUp( UINT hit_test, CPoint cursor_pos )
{
if( hit_test == HTSYSMENU )
{
// This message and hit_test combination should never be received because
// SetCapture was called in OnNcLButtonDown.
assert( false );
}
else
SetMsgHandled( FALSE );
}
void OnMouseMove( UINT modifiers, CPoint cursor_pos )
{
if( mouse_down_in_sys_menu_ )
{
ClientToScreen( &cursor_pos );
UINT hit_test = SendMessage( WM_NCHITTEST, 0, MAKELPARAM( cursor_pos.x, cursor_pos.y ) );
if( hit_test != HTSYSMENU )
{
// The cursor has moved outside of the system menu icon so begin the drag-
// drop operation.
mouse_down_in_sys_menu_ = false;
ReleaseCapture();
BeginDragDropOperation();
}
}
else
SetMsgHandled( FALSE );
}
void OnLButtonUp( UINT modifiers, CPoint cursor_pos )
{
if( mouse_down_in_sys_menu_ )
{
// The button was released inside the system menu so simulate a normal click.
mouse_down_in_sys_menu_ = false;
ReleaseCapture();
ClientToScreen( &cursor_pos );
SendMessage( WM_SHOWSYSTEMMENU, 0, MAKELPARAM( cursor_pos.x, cursor_pos.y ) );
}
else
SetMsgHandled( FALSE );
}
};