Current, I have a parent CWnd, which is displaying many other child CWnds. All my message handling job are being done in parent CWnd, as I do not have access to child CWnds' code.
I wish to know which child CWnds is being clicked.
I can detect the right click
afx_msg void OnContextMenu(
CWnd* pWnd,
CPoint pos
);
pWnd will be the clicked child window.
However, how about left click? I know I can get the mouse coordinate, and perform some calculation accordingly to iterate through see which child CWnds falll into the point. However, I just don't want to go through all this. I which I can have something like.
CWnd* childWind = mouseEvent.getParent();
CWnd* me = ChildWindowFromPoint(point);
Related
I am using a MFC dialog based application and have a subclassed CStatic control. I would like to receive WM_MOUSEWHEEL and other messages inside my subclassed control but somehow those messages never arrive.
Here is how my Dialog looks like:
I'm only doing some really simple drawing and want to be able to move my list up and down by scrolling.
I did already:
Change the Tab-Order to ensure focus on the subclassed CStatic control first
Overwrote OnNcHitTest to give focus to the subclassed CStatic all the time
Added a scroll bar to the side
Wrote message handler for WM_MOUSEWHEEL, WM_LBUTTONDOWN, WM_KEYDOWN and WM_VSCROLL
Tried catching the messages in PreTranslateMessage
Sadly nothing ever gets called when I'm scrolling inside the Dialog / Pressing a key or clicking with my mouse. The messages just don't arrive.
Here is my Mousewheel handler for example:
class CFolderView : public CStatic
{
...
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
DECLARE_MESSAGE_MAP()
...
}
BEGIN_MESSAGE_MAP(CFolderView, CStatic)
ON_WM_MOUSEWHEEL()
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
BOOL CFolderView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
MessageBox("Mouse Wheel moved!", "Debug", MB_OK);
return CStatic::OnMouseWheel(nFlags, zDelta, pt);
}
I fail to understand why no input messages are being sent to my subclassed control. Is there some switch that enables input for a subclassed control?
You cannot handle WM_MOUSEWHEEL in CStatic because it cannot get focus by design.
From MSDN:
The WM_MOUSEWHEEL message is sent to the focus window when the mouse
wheel is rotated
By looking at your screenshot I'd suggest subclassing CListBox instead.
I need to change the cursor icon when the mouse hovers a certain HWND. I achieved the mouse cursor change with
SetClassLong(hWindow, GCL_HCURSOR, (LONG)LoadCursor (NULL, IDC_CROSS));
But it applies the cursor to each element which share the same class with the specified HWND. For example, in my case, the HWND is a Button element, and it's class is "Button", so all the buttons in my window will have the same cursor. How can I just change the cursor to a specified HWND? Something like this:
SetHwndCursor(hWindow, GCL_CURSOR, Cursor); //Invented function, just to make the example
Thanks.
To show a different cursor than the class's default cursor, you need to handle the WM_SETCURSOR message for the window and call SetCursor in response to WM_SETCURSOR. For a brief example, see Displaying a Cursor.
You'll need to subclass the button to override the button's WndProc to handle WM_SETCURSOR. Use SetWindowSubclass to subclass the window (and then remove the subclassing with RemoveWindowSubclass when the button is destroyed, in response to WM_NCDESTROY—see Raymond Chen's Safer subclassing for details). SetWindowLongPtr is no longer recommended for subclassing windows.
Thanks to #IInspectable and #JonathanPotter for the information on SetWindowSubclass.
I accomplish this by handling WM_SETCURSOR for the window in question and use SetCursor.
Really need some help
How do I move the parent dialog when dragging the child dialog?
I have it so that when I drag the parent dialog, the child dialog is also moved, but not the reverse relationship.
Any help would be greatly appreciated, thanks!
My Main dialog.cpp:
void MainDialog::OnMove(int x, int y)
{
CDialog::OnMove(x, y);
m_pDialog->SetWindowPos(&wndTop, x, y, 50, 50, SWP_NOZORDER); // child dialog
}
BEGIN_MESSAGE_MAP(CTranslucentDialog, CDialog)
//AFX_MSG_MAP
ON_WM_ERASEBKGND()
ON_WM_MOVE()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
Thanks, I was able to get it to work by creating a handler for NCHITTEST and returning HTTRANSPARENT.
LRESULT CGadgetStandardDialog::OnNcHitTest(CPoint point)
{
return HTTRANSPARENT;
}
The Problem is that the Mouse Input is consumed by the child. So clicking in a child window and dragging there, usually selects some data in the child (in an edit Control). Or for a static Control the mouse Input is forwarded to the parent.
So you. Need to decide... You always have the posibility to handle this in WM_NCHITTEST and return HTCAPTION, or you allow the parent to handle this in retunring HTTRANSPARENT.
BTW: If you want to implement moving a window with the mouse in the Client area too just handle WM_NCHITTEST and return HTCAPTION. there is no Need to implement a mouse movehandler and doing it by yourself.
I want find control handle lie under other when mouse over, but it only found control above (use WindowFromPoint, ChildWindowFromPoint , etc does not work).
Any suggestion?
You could use GetNextWindow Win32 API call to retrieve next window in Z-Order that lays below this one.
Algorithm could be like this:
Get initial window by HWND hwnd = ChildWindowFromPoint(hwndParent, point);
If hwnd is sought-for window then stop
hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
If hwnd contains point then go to 2
Otherwise go to 3.
Another way - just enumerate all controls on dialog or view, store their rectangles and handles in some container and do the point check manually.
I have created a dialogbox. On which I have created two list views.
I have created a sub class for list view.
I wanted to know where is mouse, I mean on which list view.
After that I will find the index of list view using CListCtrl::HitTest().
Now I am getting the index using HitTest but Mouse move is common for both List view.
So how I can distinguish the list view in mouse move event.
Finally I am going to create the tooltip according to list view and index of that list view.
CListCtrl inherits form CWnd. You can get the mouse pointers coordinates implementing CWnd::OnMouseMove. You mainly have two options:
either subclass the CListCtrl and implement OnMouseMove as you want in the derived class
either implement OnMouseMove in the parent window (dialog window) and test the coordinates of the mouse against the coordinates of the two list controls.
Whatever solution you pick keep in mind that OnMouseMove is called very often and the implementation of the function must be very light otherwise it will load the computers resources and the application will lag.
HTH,
JP.
If all you really want is to display a tool-tip whenever the mouse hovers over some control you have, there's no need getting your hands so dirty with hit-tests, mouse coordinates, etc. Just use windows' built-in mechanism for that.
Assuming that your dialog class is the parent of the two list views:
From the dialog's OnCreate() call EnableToolTips().
Add a handler to the message map, such as: ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnTtnNeedText).
Implement OnTtnNeedText() in the dialog class. Example:
BOOL CMyDialog::OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
pTTT->hinst = AfxGetResourceHandle();
switch ( pNMHDR->idFrom )
{
case IDC_LV_LEFT:
pTTT->lpszText = "I'm lefty!";
break;
case IDC_LV_RIGHT:
pTTT->lpszText = "I'm righty!";
break;
}
return TRUE;
}
And that's more or less it. Refer to this for more information: article