CStatic subclassed Control fails to receive input messages - c++

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.

Related

Why the superclass'es OnPaint() method is called on pressing button?

I'm trying to implement the OnPaint() method in the subclass of the CButton MFC class.
class CImageButton : public CButton
public:
using CButton::CButton;
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CImageButton, CButton)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CImageButton::OnPaint()
{ /* Draws an image; Doesn't call the CButton::OnPaint(). */ }
Then, I have a dialog. In the resource editor, I placed the button on its form. In the dialog declaration, I wrote
CImageButton m_btn;
and
DDX_Control(pdc, IDC_BUTTON, m_btn);
in the DoDataExchange(). So, I think, I done all in order to my painting routine be working. But I got the strange thing: when my dialog is opening the image is painted OK (without the button's border, as I implemented in my method). But, if I'm trying to click on it, the image disappears the button's border is drawn as well a text which I specified in the VS resource editor. I.e., it looks like the superclass'es OnPaint() method is called by some way. I even was placing a debugging output on the entry of my method -- it is really not called. Then, if I switch the focus to some other control, my button is being redrawn with image.
Please, don't suggest me to use other ways to draw the image on the button. I need to get an answer on the question asked.
Thank you!

How to define onDraw() in MFC

I understand that the onDraw() function is virtual void which is called automatically via OnPaint(), which is itself triggered by the WM_PAINT message.
My declaration goes something like this:
myDialog.cpp
void myDialog::OnDraw(CDC* dc)
{
CCustomMemDC pDC(dc);
CExampleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
myDialog.h
afx_msg void OnDraw(CDC* dc);
and in my OnPaint()
CDialog::OnPaint();
However I could not get OnDraw to be triggered at all... Could anyone enlighten if this method is correct?
Thanks!
A dialog has no OnDraw. This is a virtual function in views to allow printing and drawing to a screen.
In a dialog just use OnPaint. There isno redirection to a virtual OnDraw function in a dialog.
It is not correct. As others have pointed out, OnDraw() is a virtual method of CView and not CDialog. Therefore, your OnDraw() method will never be called.
I don't know why your dialog would have a flicker problem that you would need to mitigate it. If you have a custom control on the dialog that is causing flicker, then you probably need to fix the drawing code in it and possibly add WS_CLIPCHILDREN as a Window Style to your dialog. That will make sure that the background of the custom control is not erased when the dialog executes its WM_ERASEBKGND message.
It makes no sense to override the WM_PAINT of the dialog unless you are really planning to do custom drawing on it. Unless you have a very good reason, don't do it.
If you choose to ignore the advice then add an ON_WM_PAINT() to your message handler to the dialog, and then draw the dialog yourself:
void myDialog::OnPaint()
{
CPaintDC dc(this);
CCustomMemDC pDC(&dc);
// do your specialized code knowing you are responsible for drawing the whole dialog
}
If you really want to use your OnDraw() method, then you could also write OnPaint() like this:
void myDialog::OnPaint()
{
CPaintDC dc(this);
OnDraw(&dc);
}
But, the first thing I would do in your situation is try adding the style WS_CLIPCHILDREN to your dialog style.

How do i move parent dialog when dragging child dialog, in MFC?

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.

Get mouse clicked component

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

OnRButtonDown on a modal dialog

I have a modal dialog that I would like to implement a right mouse click event on. I have added ON_WM_RBUTTONDOWN() to the class's message map.
BEGIN_MESSAGE_MAP(MyDialog, CDialog)
//{{AFX_MSG_MAP(MyDialog)
ON_WM_RBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
and have overridden the class's afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
However, my OnRButtonDown function does not execute when I click the mouse button on the Dialog window. My dialog is called using DoModal(), could it be that modal dialogs don't allow for these mouse events? Is there something else that I'm missing?
No, this should work also in modal dialogs. Two possible scenarios:
you have an invisible control which
captures the click
you have overridden the window procedure and do something unwanted with the message.