How to bring dialog to top when child control on it is clicked - mfc

Working with C++ app, using MFC.
I have an aux dialog that is created as a secondary dialog to the main application dialog. This aux dialog has several buttons etc. as child controls. If I click on the aux dialog background or in its nonclient area, it comes to the top as expected. But if I click on one of the child buttons, the button functions correctly but the dialog doesn't come to the top.
Is there some event I should handle in the dialog to bring it to the top when any child control is clicked? Or perhaps set some property in the dialog that will ensure that happens?
I'm suspicious I need to handle some activate or focus event that I'm not. Or maybe once the children handle the click, it needs to be propagated up? Or the other way around?
EDIT: Additional details answering question in comment:
Main dialog class CMyDlg and aux dialog class CAuxDlg are both derived from CDialog.
A blank dialog resource exists for each; all child controls etc are created programmatically.
class CMyDlg : public CDialog
{
public:
CAuxDlg *aux;
...
protected:
virtual BOOL OnInitDialog()
...
DECLARE_MESSAGE_MAP()
}
class CAuxDlg : public CDialog
{
...
protected:
...
DECLARE_MESSAGE_MAP()
}
Aux dialog is created in main dialog's OnInitDialog() method:
BOOL CMyDlg::OnInitDialog()
{
...
aux = new CAuxDlg(this);
aux->Create(IDD_AUX_DIALOG, GetDesktopWindow());
...
}
In the aux dialog resource, all properties are FALSE except for:
border: resizing
style: popup
title bar: true
tool window: true
use system font: true

All of my custom controls are derived from a custom base class CMyBase. I added a handler to this base class:
ON_WM_LBUTTONDOWN()
...
void CMyBase::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);
GetParent()->SetActiveWindow();
}
and ensured that classes derived from CMyBase that handle WM_LBUTTONDOWN also call the base class's handler:
class CMyCtrl : public CMyBase
...
void CMyCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// do stuff here
CMyBase::OnLButtonDown(nFlags, point);
}
and that seems to have done the trick.
Note 1: As mentioned in the comments on the question, if I add a standard CButton or CStatic or even CWnd to the aux dialog, clicking on that standard control does bring the aux dialog to the top. I don't know what the standard controls are doing that mine is not (other than elaborate mouse handling), but it must be something like this.
Note 2: It isn't enough to just call CWnd::OnLButtonDown(). Activating the containing aux dialog seems to be necessary.

Related

Float (or detach) the tabbed CMDIChildWndEx window from CMDIFrameWndEx,any idea?

In visual studio,all opened editor windows are tabbed in the workspace.when you right click one,there is a "float" option in the menu.if you float a window,the window is detached from the tab and you can drag it anywhere and after all you can dock it back to the tab.
i created a test mdi project,it's not a default behavior.
i overrided the ID_FILE_NEW command and followed the OpenDocumentFile routine,never found out where the framework add the newly created child frame window to the tab.
in the OpenDocumentFile routine,i bumped into a CMFCTabCtrl class and there is a AddTab function.
now the AddTab function:
virtual void AddTab(
CWnd* pTabWnd,
LPCTSTR lpszTabLabel,
UINT uiImageId = (UINT)-1,,
BOOL bDetachable = TRUE
);
virtual void AddTab(
CWnd* pTabWnd,
UINT uiResTabLabel,
UINT uiImageId = (UINT)-1,
BOOL bDetachable = TRUE
);
the Remarks:
If pTabWnd points to an object that is not derived from the CDockablePane Class and
if bDetachable is TRUE, the framework automatically creates a wrapper for the pTabWnd object.
The wrapper makes the pTabWnd object detachable.
By default, the wrapper is an instance of the CDockablePaneAdapter Class.
If the functionality offered by the default wrapper is unacceptable,
use the CMFCBaseTabCtrl::SetDockingBarWrapperRTC method to specify a different wrapper.
still no luck.
i did try to on the fly create a CView and attach it to the CDocument and put that CView in a CDockablePane.so i could switch the old tabbed one to the new dockable one. it's not working yet.
So any thoughts about floating the tabbed CMDIChildWndEx window from CMDIFrameWndEx?

How to disable scroll function when Ctrl is pressed in QMainWindow

I currently works on QT for my project. I implemented a MainWindow class which inherited from QMainWindow.
In MainWindow, I handled mouse wheel event like this:
void MainWindow::wheelEvent ( QWheelEvent * event )
{
if (event->modifiers().testFlag(Qt::ControlModifier)) {
if (event->delta() > 0) {
zoomInAct();
}
else if(event->delta()<0){
zoomOutAct();
}
}
}
The problem is: when I press CONTROL KEY and Wheel the mouse, the scroll bar alway scroll to top or bottom before reach my wheelEvent function. Would you please help to allow zoom-in/out when press control and wheel the mouse? (Not scroll the scroll bar)
Sorry for my bad english.
Looking at your current implementation here you have not specified event->accept() if you have added your own functionality and you don't want to propagate the event further to the parent. Try adding event->accept() in the if conditions where you have added your logic.
And try adding debug statement to test whether the event is reaching here or someone else is handling the event. By someone else I mean some other child widget. Some description of the UI and what widget is to be zoomed in would be helpful to further investigate the problem.
Make sure you read about the event system in Qt. Docs available here
Acctualy, there is a child widget that handle the wheel event first (default event handle is scroll the scrollbar).
Solution: override wheelevent in child widget to send it to parent widget (MainWindow) when the control key is pressed.
class WorkArea: public QWidget {
...
virtual void wheelEvent(QWheelEvent *event)
{
if(event->modifiers().testFlag(Qt::ControlModifier))
MainWindow::wheelEvent(event);
else
QWidget::wheelEvent(event);
}
...
}

Parent Window is NULL in CFormView (MFC)

I have a CFormView-derived class that has a button I am trying to call ShowWindow on. However, this call fails because the m_hWnd variable is null. Why is m_hWnd null? The dialog has the child style set in the properties window, and I'm associating the parent CFrameWnd with the form view. This view is intended to be modeless.
Code that creates view:
void CMainFrame::SwitchEditView(CRuntimeClass * pViewClass)
{
context.m_pNewViewClass=pViewClass;
context.m_pCurrentDoc=pDoc;
context.m_pNewDocTemplate=NULL;
context.m_pLastView=NULL;
context.m_pCurrentFrame=this;
m_subSplitter.CreateView(0,1,pViewClass,CSize(0,0), &context); // create new view and add it to the splitter window
}
The constructor for my CFormView-derived class:
CDFAManEditViewProject::CDFAManEditViewProject()
: CFormView(CDFAManEditViewProject::IDD)
{
// c_btnEdit is a CButton MFC control
c_btnEdit.ShowWindow(SW_SHOW); // this call fails on ASSERT(::IsWindow(m_hWnd) )
}
You are trying to access an edit control from the view constructor. But the view window has not been created yet when the constructor runs. That is why you have no m_hWnd and no edit control yet.
Move your initialization of controls into the view's OnInitialUpdate.

CMFCButton::SetToolTip(str) not work in OnInitDialog() and

I want my CMFCButton to show tooltip when mouse over.
It doesn't work if I use SetToolTip() method in OnInitDialog
CMFCButton* bt = ((CMFCButton*)GetDlgItem(IDC_MFCBUTTON1));
bt->SetTooltip(_T("tooltip"));
BUT it does work if I put this code in message handle function like another button's click handle.
What I want is that the CMFCButton could show tooltip when the dialog is created, where should I put these code?
========================
By the way, The tooltip text I set in the Property view does not work for most time.
I just derived a class
class CMyButton : public CMFCButton
{
public:
void SetDelayFullTextTooltipSet(bool DelayFullTextTooltipSet)
{
m_bDelayFullTextTooltipSet = DelayFullTextTooltipSet;
}
};
Instead of a CMFCButton variable on the Dialog class I use the button, I now have a CMyButton.
And in the OnInitDialog, after the SetTooltip call, I do
button.SetDelayFullTextTooltipSet(FALSE);
Have you called the base class' OnInitDialog()? The main point is that the control needs to be created before you call SetToolTip() on it. Step into OnInitDialog() with the debugger and see if m_hWnd of the control has a value at the moment you call SetToolTip().

TaskDialog with no buttons

Is it possible to show the TaskDialog with no buttons? I would like to be able to show just a progress bar (with a message), and then close the TaskDialog window when when my processing is complete (from the Timer event). Right now, I can show a disabled button and then call ButtonClick to close the window, but showing no buttons and having a CloseDialog method would be ideal.
Thanks.
Derive your own class from CTaskDialog
class CTaskDlg : public CTaskDialog
{
in CTaskDlg.h declare:
public:
void CloseTaskDlg(void);
protected:
HWND m_TaskDlgHwnd;
virtual HRESULT OnInit();
};
in CTaskDialog.cpp:
void CTaskDlg::CloseTaskDlg(void)
{
::SendMessage(m_TaskDlgHwnd, TDM_CLICK_BUTTON, static_cast<WPARAM>(TDCBF_OK_BUTTON), 0);
}
HRESULT CTaskDlg::OnInit()
{
m_TaskDlgHwnd = ::GetActiveWindow();
return S_OK;
}
CTaskDlg dlg;
dlg.CloseTaskDlg();
Both TaskDialog() and TaskDialogIndirect() force a default button if you do not specify any buttons, but you do have control over what kind of buttons are used, so I would place an Abort button in the dialog to cancel whatever operation you are displaying status of. Or maybe a Hide button if the user does not want to see the progress anymore without stopping the operation that is in progress.
You have to use TaskDialogIndirect() in order to activate the progress bar feature. You can also use its callback feature to obtain the HWND of the dialog so you can close it programmably when needed.
Otherwise, don't use the TaskDialog API. Just create your own window with your own UI, then you can do whatever you want with it.