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

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.

Related

CStatic subclassed Control fails to receive input messages

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.

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.

Hiding an MFC dialog box

Ok so I am using this code to hide the taskbar icon of a dialog based MFC application(VC++). The taskbar icon and the dialog box hide whenever I click on the cross or the close buttons. But I can’t get this one thing right. Whenever I hit the close or the cross button from title bar, the dialog box first flickers and shows a sort of intermediate dialog box and then hides. This is very annoying. I am posting my code here after two days of vain effort. So guys please help me. Thanks in advance.
void CMyAppDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
CWnd* pWnd;
pWnd = AfxGetMainWnd();
RemoveTaskbarIcon(pWnd);
pWnd->ModifyStyle(WS_VISIBLE, 0);
mVisible = FALSE;
}
BOOL CMyAppDlg::RemoveTaskbarIcon(CWnd* pWnd)
{
LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
// Create static invisible window
if (!::IsWindow(mWndInvisible.m_hWnd))
{
if (!mWndInvisible.CreateEx(0, pstrOwnerClass, _T(""),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, 0))
return FALSE;
}
pWnd->SetParent(&mWndInvisible);
return TRUE;
}
Here are the screen shots of dialog box. When I press the close or cross button, the dialog box which looks like this in the first place turns into this for like less than half a second and then disappears (hides).
If you show your dialog using CDialog::DoModal() the framework will make sure your dialog is shown. There is only one way to prevent a modal dialog from being shown:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
BOOL CHiddenDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_visible = FALSE;
return TRUE;
}
void CHiddenDialog::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if (!m_visible)
lpwndpos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpwndpos);
}
I think Paul DiLascia recommended the following. This is for modal dialogs only.
The following code can be put in OnInitDialog to move the dialog off-screen. You will need to implement a method for moving it back on-screen when appropriate.
CRect DialogRect;
GetWindowRect(&DialogRect);
int DialogWidth = DialogRect.Width();
int DialogHeight = DialogRect.Height();
MoveWindow(0-DialogWidth, 0-DialogHeight, DialogWidth, DialogHeight);
The answer from l33t looks good and is probably better but this is an alternative.
Maybe an obvious thing, but what happens when you do the hide before you reparent the dialog? Also what if you don't directly modify the window style but use ShowWindow(SW_HIDE)?
Finally, have you tried switching the dialog's window style to WS_CHILD before calling SetParent() and/or maybe moving it out of the client area so that the window isn't shown any more (MoveWindow(-1000, -1000) or something like that).

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.