How to shutdown DLL with user-interface threads? - c++

I have made a DLL with a function that opens a non-modal window.
class CMainFrame : public CFrameWnd
{
protected:
CMainFrame() {}
DECLARE_DYNCREATE(CMainFrame)
public:
virtual void PostNcDestroy()
{ AfxPostQuitMessage(0); }
public:
virtual ~CMainFrame() {}
};
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
class CDllApp : public CWinApp
{
public:
CDllApp() :
m_pDocTemplate(NULL)
{};
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
m_pDocTemplate = new CMultiDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(C3DGraphDoc),
RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(C3DGraphView));
return TRUE;
}
public:
CMultiDocTemplate* m_pDocTemplate;
};
CDllApp theApp;
class C3DThread : public CWinThread
{
DECLARE_DYNCREATE(C3DThread)
public:
virtual BOOL InitInstance()
{
theApp.m_pDocTemplate->OpenDocumentFile(NULL);
}
};
IMPLEMENT_DYNCREATE(C3DThread, CWinThread)
void __stdcall ExportedFunction()
{
AfxBeginThread(RUNTIME_CLASS(C3DThread));
}
If I close all windows before exiting main application, then all looks fine, otherwise my threads hang up. So, I think I need to clean up by closing all open documents and I wonder what would be the simplest way to do it gracefully. m_pDocTemplate->CloseAllDocuments() from theApp doesn't work, since frame windows for documents belong to different threads.

Related

Visual C++ How to override event handler of parant class?

I need to override event wm_lbuttonup of CMFCRibbonSlider class
class CMyRibbonSlider : public CMFCRibbonSlider
{
public:
virtual void OnLButtonUp(CPoint point); // need this event handler!
};
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
AfxMessageBox(_T("Works!"))
return;
}
Use CMyRibbonSlider object in MainFrame class
class CMainFrame : public CMDIFrameWndEx
{
....
CMyRibbonSlider* SliderLine;
}
When CMFCRibbonSlider control apears and I click left mousebutton, nothing happens. What do I do wrong?
EDIT:
initialization
CArray<CMFCRibbonBaseElement*, CMFCRibbonBaseElement*> ar;
m_wndRibbonBar.GetElementsByID(ID_SLIDER2, RibbonElementsArray);
m_wndRibbonBar.GetElementsByID(ID_START_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_STOP_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_SLIDER_LINE, ar); //HERE!
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(IDC_STATIC_TT, ar);
RibbonElementsArray.Append(ar);
Slider = DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[0]);
btnStart = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[1]);
btnStop = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[2]);
SliderLine = (CMyRibbonSlider*)DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[3]); //and HERE!
TmpLable = DYNAMIC_DOWNCAST(CMFCRibbonLabel, RibbonElementsArray[4]);
also I have these event handlers in Mainframe class and they work:
ON_UPDATE_COMMAND_UI(ID_SLIDER_LINE, &CMainFrame::OnUpdateSliderLine)
ON_COMMAND(ID_SLIDER_LINE, &CMainFrame::OnSliderLine)
SliderLine->GetPos() also returns right slider position, so I think initialization is right...
It is seem like the CMFCRibbonSlider control isn't added correctly to CMFCRibbonPanel and therefore CMainFrame class does not expose slider’s messages through message map.
Try to use a method described in the following article:
Walkthrough: Creating a New Ribbon Application By Using MFC
The code will be look like below.
MyRibbonSlider.h
#include "afxribbonslider.h"
#pragma once
class CMyRibbonSlider : public CMFCRibbonSlider
{
DECLARE_DYNCREATE(CMyRibbonSlider)
public:
CMyRibbonSlider();
CMyRibbonSlider(UINT nID, int nWidth = 100);
// Implementation
public:
virtual ~CMyRibbonSlider();
virtual void OnLButtonUp(CPoint point);
};
MyRibbonSlider.cpp
#include "stdafx.h"
#include "MyRibbonSlider.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CMyRibbonSlider, CMFCRibbonSlider)
CMyRibbonSlider::CMyRibbonSlider()
{
}
CMyRibbonSlider::CMyRibbonSlider(UINT nID, int nWidth)
: CMFCRibbonSlider(nID, nWidth)
{
}
CMyRibbonSlider::~CMyRibbonSlider()
{
}
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
TRACE("\nCMyRibbonSlider::OnLButtonUp()");
return;
}
Related declarations in the CMainFrame.h
afx_msg void OnSliderLine();
afx_msg void OnUpdateSliderLine(CCmdUI* pCmdUI);
CMainFrame.cpp
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
...
ON_COMMAND(ID_SLIDER, &CMainFrame::OnSliderLine)
ON_UPDATE_COMMAND_UI(ID_SLIDER, &CMainFrame::OnUpdateSliderLine)
END_MESSAGE_MAP()
void CMainFrame::InitializeRibbon()
{
...
bNameValid = strTemp.LoadString(*your title*);
ASSERT(bNameValid);
CMFCRibbonPanel* pPanelAdvanced = pCategoryHome->AddPanel(strTemp, m_PanelImages.ExtractIcon (*your icon*));
strTemp = _T("Slider");
CMyRibbonSlider* pRibbonSlider = new CMyRibbonSlider(ID_SLIDER);
pPanelAdvanced->Add(pRibbonSlider);
...
}
void CMainFrame::OnSliderLine()
{
// TODO
}
void CMainFrame::OnUpdateSliderLine(CCmdUI* pCmdUI)
{
// TODO
}

Signals not received using QServiceManager

I have a problem with the QServiceManager.
QServiceManager manager;
CFoo bar;
QList<QServiceInterfaceDescriptor> ServiceList = manager.findInterfaces(SERVICE_NAME);
for(int i = 0; i < ServiceList.length(); i++)
{
bool accessGranted = false;
QServiceInterfaceDescriptor descriptor = ServiceList[i];
if (descriptor.interfaceName() == INTERFACE)
{
bar = manager.loadLocalTypedInterface<IFoo>(descriptor, accessGranted);
if (NULL == bar && false == accessGranted)
{
connect(bar, SIGNAL(signal()),
this, SLOT(slot()));
}
}
}
I can do function calls specified in the interface IFoo on bar, like:
bar.function()
and I see that the remote object foo is receiving the function call, but when I send the signal remotely:
class IFoo : public QObject
{
Q_OBJECT
public:
virtual void function() = 0:
signals:
void signal();
};
class CFoo : public IFoo`
{
Q_OBJECT
void function()
{
emit signal();
}
};
it is not received. The function slot() is never called. I checked that the connect function gets called and returns TRUE. Can anybody pinpoint what I am doing wrong?
Cant use signals and slots if your class isnt qobject
#include<QObject>
class CFoo : public QObject, public IFoo
{
Q_OBJECT
signals:
void signal();
public:
void function()
{
emit signal();
}
};

Update separate thread CWinThread form with text information

I have program that has status window on separate thread. I need to make status thread form update with new text information information. What is the best way of doing that?
Main thread creates status window:
void CMainWindow::OnPushButtonClicked ()
{
CWinThread* pThread= AfxBeginThread(RUNTIME_CLASS(CMySecondUIThreadClass) );
}
UI thread:
class CMySecondUIThreadClass : public CWinThread
{
DECLARE_DYNCREATE(CMySecondUIThreadClass)
protected:
CMySecondUIThreadClass();
virtual ~CMySecondUIThreadClass();
public:
CMainWindow * v1;
virtual BOOL InitInstance();
virtual int ExitInstance();
protected:
DECLARE_MESSAGE_MAP()
};
InitInstance of UI:
BOOL CMySecondUIThreadClass::InitInstance()
{
v1 = new CMainWindow;
v1->Inform("Thread"); //Procedure that updates vi dialog form controls with text information
m_pMainWnd=v1;
ShowWindow (m_pMainWnd->m_hWnd,SW_SHOW);
m_pMainWnd->UpdateWindow ();
return TRUE;
}

Can i declare two IDD in one project?

I am using two classes in one project. First class is CClientSocketDlg and other one is CUserSpecificationDlg.
Here is the some part of the code.
class CClientSocketDlg : public CDialog
{
public:
bool StartClient();
CClientSocketDlg(CWnd* pParent = NULL);
void AppendMessage(LPCTSTR strText );
enum { IDD = IDD_CLIENTSOCKET_DIALOG };
CEdit m_ctlMsgList;
CIPAddressCtrl m_ctlIPAddress;
};
class CuserspecificationDlg : public CDialogEx
{
public:
CuserspecificationDlg(CWnd* pParent = NULL);
// Dialog Data
enum { IDD = IDD_USERSPECIFICATION_DIALOG };
CListCtrl m_List;
CString out; // For Edit control in list box having IDC_EDIT2
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
};
Can I declare them in one project ? Is it allowed? Can I use m_ctlIPAddress
in CUserspecification class ?

Set focus on a modeless dialogs hosted in an MFC view

I have an MFC view, and I have another project which implements and MFC dialog.
I want to host the dialog in my view.
My view is of class CFormView.
I did it that way in my view code:
m_myDialog->Create(myDialog::IDD, this);
Now, I see my dialog, but I can't set focus on it and can't use it.
What do I have to change in order to host my dialog in my view, and be able to use it and set focus to it, just as part of the view?
Thanks
I know this is a few weeks old, but you need to provide more code or a better context of what is taking place.
I had a similar problem to yourself & found this hard to find info on when I first tried this. Following is an abstract of something I've used. I'm sure there's probably a better way to do this, but I find it works the way I want;
//MyApp.h
class MyDialogClass;
class MyApp : public CWinAppEx
{
public:
MyApp();
virtual BOOL InitInstance();
//code etc
MyDialogClass *p_myDlg;
};
//MyApp.cpp
#include "MyApp.h"
#include "CMyView.h"
#include "mydialogclass.h"
BOOL MyApp::InitInstance()
{
//code etc
p_myDlg = CMyView::GetView()->p_myDlg;
//can be used here or elsewhere. I have mine linked with a button
p_myDlg->ShowWindow(true);
};
//CMyView.h
class MyDialogClass;
class CMyView : public CFormView
{
protected: // create from serialization only
CMyView();
DECLARE_DYNCREATE(CMyView)
public:
enum{ IDD = IDD_CMyView_VIEW };
static CMyView* GetView();
MyDialogClass *p_myDlg;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};
//CMyView.cpp
#include "MyApp.h"
#include "CMyView.h"
#include "mydialogclass.h"
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
p_myDlg = new MyDialogClass(this);
return 0;
}
void CMyView::DisplayDialogFoo()
{
//can be used here or elsewhere. I have mine linked with a button
p_myDlg->ShowWindow(true);
}
//mydialogclass.h
class MyDialogClass : public CDialog
{
DECLARE_DYNAMIC(MyDialogClass)
public:
MyDialogClass(CWnd* pParent /*= NULL*/);
enum { IDD = IDD_MyDialog_DLG };
};
//mydialogclass.cpp
#include "mydialogclass.h"
MyDialogClass::MyDialogClass(CWnd* pParent /*=NULL*/)
: CDialog(MyDialogClass::IDD, pParent)
{
Create(IDD, pParent);
}
There's also an article here I just found:
http://www.codeproject.com/Articles/1651/Tutorial-Modeless-Dialogs-with-MFC