initialize double click on edit control in MFC - c++

I am trying to set an mouse click event on editbox and when I am double clicking on edit box it should bring up a message box.
ON_WM_LBUTTONDBLCLK(IDC_EDITItem, &MessageManage::OnItemDoubleClick)
void MessageManage::OnItemDoubleClick()
{
MessageBox( m_strItemMsg, "Sample code", MB_OK | MB_ICONINFORMATION );
}

At alternative is to just use PreTranslateMessage on your dialog:
BOOL CMFCApplication1Dlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_LBUTTONDBLCLK &&
pMsg->hwnd == ::GetDlgItem(m_hWnd, IDC_EDIT1))
{
AfxMessageBox(_T("Run Code"));
return TRUE; //Important!!! Message is handled
}
return CDialogEx::PreTranslateMessage(pMsg);
}

It's not taking double click event from edit box
One way to accomplish this is to derive your own class from CEdit and handle ON_WM_LBUTTONDBLCLK(). The following code responded to the double click on an edit control in a sample program.
BEGIN_MESSAGE_MAP(MyEdit, CEdit)
ON_WM_LBUTTONDBLCLK()
END_MESSAGE_MAP()
// MyEdit message handlers
void MyEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CEdit::OnLButtonDblClk(nFlags, point);
}

Related

MFC Win32 | LButtonUp not being received after clicking toolbar button (CMFCToolBarButton::OnClick)

What I'm trying to achieve
Well, the title might not have explained the problem very well, so here goes:
I am trying to create a Win32 app using MFC that lets you edit and inspect other windows.
I want the user to be able to select other windows.
I got inspired by the "Find Window Process" tool on the toolbar on sysinternals applications such as ProcessExplorer.
The way it works is you click, then the window disappears, and then you drag it over the window you want to select. A border pops up around it and when you let go, it selects the window the mouse is over.
My problem
The problem I was facing is that I don't know how to detect when the user lets go of the mouse on another window.
I detect mouse down using OnClick in CMFCToolBarButton
I tried using SetCapture() but that did nothing.
I tried using OnNcLButtonUp and OnLButtonUp but neither of them worked. (alongside SetCapture)
Here's my code so far (ChildView.cpp):
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_UPDATE_COMMAND_UI(ID_TB_LOCATEWINDOW, &CChildView::EnableToolbarButton)
ON_UPDATE_COMMAND_UI(ID_TOOLS_MESSAGELAUNCHER, &CChildView::EnableToolbarButton)
ON_WM_XBUTTONUP()
// ON_WM_LBUTTONUP()
ON_WM_NCLBUTTONUP()
END_MESSAGE_MAP()
....
void CChildView::LocateWindow()
{
GetParentFrame()->ShowWindow(SW_MINIMIZE);
SetCapture();
}
void CChildView::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
ReleaseCapture();
GetParentFrame()->ShowWindow(SW_NORMAL);
MessageBox(L"Stuff", L"");
CWnd::OnNcLButtonUp(nHitTest, point);
}
I want to mention that the LocateWindow function gets called when the toolbar button is clicked (as in mouse down, not mouse down AND up)
It is called from the OnClick function.
Here's the code for that:
(I replace the button with OnToolbarReset)
// CLocateWindowButton.cpp : implementation file
//
#include "pch.h"
#include "WindowHacker.h"
#include "MainFrm.h"
#include "CLocateWindowButton.h"
// CLocateWindowButton
IMPLEMENT_SERIAL(CLocateWindowButton, CMFCToolBarButton, 1)
// CLocateWindowButton member functions
CLocateWindowButton::CLocateWindowButton()
{
}
CLocateWindowButton::CLocateWindowButton(CMainFrame* mainFrame, UINT uiCmdID, LPCTSTR lpszText) : CMFCToolBarButton(uiCmdID, NULL, lpszText)
{
this->mainFrame = mainFrame;
}
BOOL CLocateWindowButton::OnClick(CWnd* pWnd, BOOL bDelay = TRUE) {
//(CMainFrame*)m_pWndParent->LocateWindow();
mainFrame->LocateWindow();
return FALSE;
}
void CLocateWindowButton::CopyFrom(const CMFCToolBarButton& src)
{
CMFCToolBarButton::CopyFrom(src);
mainFrame = ((CLocateWindowButton&)src).mainFrame;
}
//void CLocateWindowButton::AssertValid() const
//{
// CMFCToolBarButton::AssertValid();
//
// // TODO: Add your specialized code here and/or call the base class
//}
UPDATE:
It seems to work when I put it inside an LButtonDown event, it just seems to not work when it is being detected from OnClick in CMFCToolBarButton
I found that in CMFCToolBar::OnLButtonUp, after calling OnClick in the button, it recaptures the cursor, invalidating our SetCapture.
BUT if I return TRUE instead of FALSE in OnClick, the mouse is not recaptured.
So changing this:
BOOL CLocateWindowButton::OnClick(CWnd* pWnd, BOOL bDelay = TRUE) {
//(CMainFrame*)m_pWndParent->LocateWindow();
mainFrame->LocateWindow();
//ReleaseCapture();
this->mainFrame->SetCapture();
return FALSE;
}
To this:
BOOL CLocateWindowButton::OnClick(CWnd* pWnd, BOOL bDelay = TRUE) {
//(CMainFrame*)m_pWndParent->LocateWindow();
mainFrame->LocateWindow();
//ReleaseCapture();
this->mainFrame->SetCapture();
return TRUE; // The line is changed here
}
The message gets sent to CMainFrame instead.

How to get events when I press an item in a submenu MFC?

I am creating a program like Windows Task Manager.
The working environment is visual c ++ 6.0.
void CProcess01Dlg::OnRclickListCtrl(NMHDR* pNMHDR, LRESULT* pResult) {
CPoint ptInList, ptInSrceen;
GetCursorPos(&ptInSrceen);
ptInList = ptInSrceen;
m_ctrlList.ScreenToClient(&ptInList);
POSITION pos = m_ctrlList.GetFirstSelectedItemPosition();
int nListIndex = m_ctrlList.GetNextItem(-1, LVNI_SELECTED);
CMenu menu, *pMenu;
menu.LoadMenuA(IDR_MENU1);
CString str;
str.Format("%d",nListIndex);
GetDlgItem(IDC_EDIT1)->SetWindowText(str);
if( 0 <= nListIndex)
{
pMenu = menu.GetSubMenu(0);
}
else
{
}
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, ptInSrceen.x, ptInSrceen.y, this);
}
The above code is a function that handles events when an item in list control is right-clicked in MFC.
I want to add an event in the context menu when a context menu appears when I right-click an item.
Tell us how you're handling the event.
Thank you :)
Use InsertMenu and/or AppendMenu to add more items to the menu.
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu* popup = menu.GetSubMenu(0);
popup->InsertMenu(MF_STRING, MF_BYPOSITION, ID_XXX1, "Insert");
popup->AppendMenu(MF_STRING, ID_XXX2, "Append");
popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, ptInSrceen.x, ptInSrceen.y, this);
The last parameter in TrackPopupMenu is the handle of the window which will receives the menu messages. You just need to handle the commands in your dialog:
BEGIN_MESSAGE_MAP(CProcess01Dlg, CDialogEx)
ON_COMMAND(ID_FILE_NEW, onfilenew)
ON_COMMAND(ID_XXX1, foo)
...
END_MESSAGE_MAP()
CProcess01Dlg::foo()
{
...
}

How to move window by right mouse button using C++?

I need to move window by right mouse button. The window has no caption, titlebar. By left button it works
void CMyHud::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SendMessage(WM_SYSCOMMAND, SC_MOVE|0x0002);
CDialogEx::OnLButtonDown(nFlags, point);
}
But if I place this code on OnRButtonDown it dosen't work. What is the problem?
Well, the solution is found, thanks to Mark Ransom:
CRect pos;
void CMyHud::OnRButtonDown(UINT nFlags, CPoint point)
{
pos.left = point.x;
pos.top = point.y;
::SetCapture(m_hWnd);
CDialogEx::OnRButtonDown(nFlags, point);
}
void CMyHud::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd* pWnd = CWnd::FromHandle(m_hWnd);
CRect r;
if(GetCapture() == pWnd)
{
POINT pt;
GetCursorPos(&pt);
GetWindowRect(r);
pt.x -= pos.left;
pt.y -= pos.top;
MoveWindow(pt.x, pt.y, r.Width(), r.Height(),TRUE);
}
CDialogEx::OnMouseMove(nFlags, point);
}
void CMyHud::OnRButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture();
CDialogEx::OnRButtonUp(nFlags, point);
}
In your OnRButtonDown function, do a SetCapture to ensure all mouse messages are routed to your window while the mouse button is down. Also store the mouse position in a member variable. Now, in your OnMouseMove function, check to see if GetCapture returns an object with the same HWND as yours - if it does, calculate the difference between the current mouse position and the saved one, then call MoveWindow to move the window.
In regards to left-mouse click:
SC_MOVE|0x0002 comes out as 0xF012 or SC_DRAGMOVE. This is apparently an undocumented constant. There is probably a good reason Microsoft doesn't want anybody to use this, that's why they have hidden it.
Also WM_SYSCOMMAND is a notification message. You should respond to it, not send it. To drag the window with left-mouse click:
message map ...
ON_WM_NCHITTEST()
LRESULT CMyDialog::OnNcHitTest(CPoint p)
{
//responding to a notification message
return HTCAPTION;
}
To drag the window with right-mouse you have to override OnRButtonDown, OnMouseMove, OnRButtonUp and make your own routine. But Window's behaviour gets very confusing. Is that really worth it?
you can use mouse message to realize.
WM_RBUTTONDOWN, WM_MOUSEMOVE

CMFCCaptionMenuButton alternative?

I need to create a caption bar button for a CDockablePane which will call up a menu with various options. I tried to use CMFCCaptionMenuButton and the button and menu show up but the message map methods for the menu ids don't fire. The MFC documentation states that CMFCCaptionMenuButton is meant for internal infrastructure and not really for your code.
So assuming that is what my problem is should I be using a CMFCCaptionBarButton and then making a separate popup menu? Has anyone made a similar caption bar based menu in MFC before?
Here's some slimmed down code snippets in case I just made a stupid mistake in hooking up the events:
BEGIN_MESSAGE_MAP(CDockPane, CDockablePane)
ON_COMMAND(ID_MORPH_BROWSER, OnMorphBrowser)
END_MESSAGE_MAP()
void CDockPane::OnPressButtons(UINT nHit)
{
// only for custom button handling don't call base
// close, maximize, and pin will be handled by default
switch (nHit)
{
case ID_MORPHTEST:
{
CMorphMenuButton* pButton = dynamic_cast<CMorphMenuButton*>(m_arrButtons.GetAt(m_morphIndex));
pButton->ShowMenu(this);
break;
}
}
}
void CDockPane::SetCaptionButtons()
{
CDockablePane::SetCaptionButtons(); // for close, pin etc
m_morphIndex = m_arrButtons.Add(new CMorphMenuButton(ID_MORPHTEST));
}
void CDockPane::OnMorphBrowser()
{
// do stuff on menu item click
}
Edit: Removed previous code no longer in use
Now that the sound of crickets chirping has dwindled in the background I guess I'll post the workaround I currently have in place:
Instead of inheriting and extending CMFCCaptionMenuButton I build my class by extending CMFCCaptionButton. I then create a menu and provide a ShowMenu method to be explicitly called when handling the custom button events as well as overriding GetIconID to return a particular system icon for the button for each menu added to the caption bar ending up with something like this for the example outlined in the question:
#pragma once
// CMorphMenuButton command target
class CMorphMenuButton : public CMFCCaptionButton
{
public:
CMorphMenuButton(UINT nHit);
virtual ~CMorphMenuButton();
virtual CMenuImages::IMAGES_IDS GetIconID (BOOL bHorz, BOOL bMaximized) const;
void ShowMenu(CWnd* pWnd);
private:
CMenu m_dockMenu;
CMenu* m_subMenu;
};
// MorphMenuButton.cpp : implementation file
//
#include "stdafx.h"
#include "MorphMenuButton.h"
// CMorphMenuButton
CMorphMenuButton::CMorphMenuButton(UINT nHit)
: CMFCCaptionButton(nHit)
{
SetMiniFrameButton(); // already defaulted?
m_dockMenu.LoadMenu(IDR_DOCKPANE); // resource ID for dock pane menus
}
CMorphMenuButton::~CMorphMenuButton()
{
m_dockMenu.DestroyMenu();
}
CMenuImages::IMAGES_IDS CMorphMenuButton::GetIconID(BOOL bHorz, BOOL bMaximized) const
{
return CMenuImages::IdArrowForward;
}
void CMorphMenuButton::ShowMenu(CWnd* pWnd)
{
CRect windowRect, buttonRect;
pWnd->GetWindowRect(&windowRect);
buttonRect = GetRect();
CPoint menuPos(windowRect.left + buttonRect.right, windowRect.top + buttonRect.bottom);
m_subMenu = m_dockMenu.GetSubMenu(0);
if (!m_subMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, menuPos.x, menuPos.y, pWnd))
{
DWORD id = GetLastError();
wchar_t errMsg[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, id, 0, errMsg, sizeof(errMsg), 0);
MessageBox(0, errMsg, L"Error", MB_OK);
}
}
The setting of caption bar buttons and handling of click events for both buttons and menus are the same as defined in the question and this works.

List box context menu

How do I add a context menu in a list box in MFC? I don't see any WM_CONTEXTMENU handler in list box's properties. Any ideas?
EDIT: I followed this tutorial MFC List Control: How to use a context menu in a list control?. The tutorial says to derive my own class from CListBox which I did, but now how do I add list box of my derived class to the dialog?
Since my edit was rejected with the rationale of "changing too much", I will put my proposal here because in my opinion the original code promotes bad coding practices.
void CYourDialog::OnContextMenu(CWnd* pWnd, CPoint point)
{
int CtrlID = pWnd->GetDlgCtrlID();
if (CtrlID == ID_YOUR_LIST) {
CMenu menu;
// Create your menu items...
int retVal = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, this);
// Handle selected options here...
}
}
Put an OnContextMenu handler in the parent class. Then add a popup menu
Edit To add the OnContextMenu handler, add an event handler to the PARENT window (ie not the list class). This is most easily done through the resource editor. Go to the properties page then go to the messages section. Then add a function for WM_CONTEXTMENU.
void CYourDialog::OnContextMenu(CWnd* pWnd, CPoint point)
{
CListCtrl* pList = (CListCtrl*)GetDlgItem( ID_YOUR_LIST );
if ( (CWnd*)pList == pWnd )
{
CMenu menu;
// Create your menu items.
int retVal = menu.TrackPopupMenu( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, this );
// Handle your returns here.
}
}
You need to take the following steps:
Add
ON_WM_CONTEXTMENU()
to
BEGIN_MESSAGE_MAP()
So you will have something like
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_QUERYDRAGICON()
ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
Add the Context Menu function in the header file:
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point)
Then add the Context Menu function, as suggested in the article:
void CMyDialog::OnContextMenu(CWnd* pWnd, CPoint point)
{
CListCtrl* pList = (CListCtrl*)GetDlgItem( ID_YOUR_LIST );
if ( (CWnd*)pList == pWnd )
{
CMenu menu;
// Create your menu items.
int retVal = menu.TrackPopupMenu( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, this );
// Handle your returns here.
}
}
Add a handler for your dialog window. That will generate this:
void YourDialogClass::OnContextMenu(CWnd* pWnd, CPoint point) {
...
}
pWnd will point to the window/control in which the user right clicked the mouse.
If you followed the tutorial to derive you own class, make sure ON_WM_CONTEXTMENU() is added to the new class message map.
To add a list box of your derived class, you simply add a variable for your ListBox control and specify the variable class as your derived class.
However I think #Goz's answer is also a valid solution, and a simpler one.