How to get a dialog object from a existing Dll

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
james.chengguangwang
Knows some wx things
Knows some wx things
Posts: 38
Joined: Wed Aug 02, 2006 4:59 am

How to get a dialog object from a existing Dll

Post by james.chengguangwang » Thu Aug 31, 2006 9:01 am

Hi All,

Is there some methods to load a dialog object from a dll, at present I can show the dialog, but I can't get the dialog object from the dll, or can we create a object in the host program which is defined in a dll? thanks very much!

regards
James

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Re: How to get a dialog object from a existing Dll

Post by upCASE » Thu Aug 31, 2006 9:47 am

james.chengguangwang wrote:Is there some methods to load a dialog object from a dll, at present I can show the dialog, but I can't get the dialog object from the dll, or can we create a object in the host program which is defined in a dll? thanks very much!
It depends on what you want to do and what build setup you use.
I suppose you could create a function that would "export"/return a pointer to a dialog from the DLL. Note that when using static builds the DLL will have to delete the dialog, not the host.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

james.chengguangwang
Knows some wx things
Knows some wx things
Posts: 38
Joined: Wed Aug 02, 2006 4:59 am

Post by james.chengguangwang » Thu Aug 31, 2006 10:02 am

Do you have some sample code? the host is a MFC application, and the Dll header File:

Code: Select all

// wxDLL is a simple DLL which demonstrates how to use 
// wxWindows in a DLL which is called from another 
// application (not using wxWindows) 
// 
// 
// Tony Edgecombe 
// (C) 2004 Frogmore Computer Services 
// www.frogmorecs.com 
// Edited by upCASE 

#pragma once 

#include "wx/wx.h" 

#include "windows.h" 

#ifdef DLLFUNCTIONS_EXPORTS 
#define DLLFUNCTIONS_API __declspec(dllexport) 
#else 
#define DLLFUNCTIONS_API __declspec(dllimport) 
#endif 

extern "C" DLLFUNCTIONS_API void TestDialog(); 
extern "C" DLLFUNCTIONS_API void TestDialogHWnd(WXHWND hWnd); 

class wxDLLApp : public wxApp 
{ 
        bool OnInit(); 
        DECLARE_EVENT_TABLE() 
};

/////////////// User Define Dialog ///////////////////////////////

class MLC3Dlg : public wxDialog
{
	public:
		MLC3Dlg(wxWindow *parent, wxWindowID id = 1, 
			const wxString &title = wxT("MLC3"), 
			const wxPoint& pos = wxDefaultPosition, 
			const wxSize& size = wxDefaultSize, 
			long style = wxDEFAULT_DIALOG_STYLE );
		virtual ~MLC3Dlg();
	
	public:
		//Do not add custom control declarations
		//wxDev-C++ will remove them. Add custom code after the block.
		////GUI Control Declaration Start
		wxButton *WxButtonDllDialog;
		wxButton *wxBtSubmit;
		wxTextCtrl *wxEdMail;
		wxRadioButton *wxRbAcceptWithMail;
		wxRadioButton *wxRbAccept;
		wxRadioButton *wxRbDeny;
		////GUI Control Declaration End
		
	public:
		//Note: if you receive any error with these enum IDs, then you need to
		//change your old form code that are based on the #define control IDs.
		//#defines may replace a numeric value for the enum names.
		//Try copy and pasting the below block in your old form header files.
		enum
		{
			////GUI Enum Control ID Start
			ID_WXBUTTONDLLDIALOG = 1007,
			ID_WXBTSUBMIT = 1005,
			ID_WXEDIT_MAIL = 1004,
			ID_WXRBACCEPTWITHMAIL = 1003,
			ID_WXRBACCEPT = 1002,
			ID_WXRBDENY = 1001,
			////GUI Enum Control ID End
			ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
		}; //End of Enum
	
	public:
		void MLC3DlgClose(wxCloseEvent& event);
		void CreateGUIControls(void);
		void wxBtSubmitClick(wxCommandEvent& event);
		void wxBtDllDialogClick(wxCommandEvent& event);
};
the Dll .cpp file:

Code: Select all

// wxDLL is a simple DLL which demonstrates how to use 
// wxWindows in a DLL which is called from another 
// application (not using wxWindows) 

// Edited by upCASE 

#include "wx/wx.h" 

#include "wxDLL.h" 
#include "wx/wxhtml.h" 

// We use IMPLEMENT_APP_NO_MAIN so we can start the app from DllMain 
// as we don't have a WinMain or main entry point 
// 
BEGIN_EVENT_TABLE(wxDLLApp, wxApp) 
		EVT_CLOSE(MLC3Dlg::MLC3DlgClose)
		EVT_BUTTON(MLC3Dlg::ID_WXBTSUBMIT,MLC3Dlg::wxBtSubmitClick)
		EVT_BUTTON(MLC3Dlg::ID_WXBTSUBMIT,MLC3Dlg::wxBtSubmitClick)
		EVT_BUTTON(MLC3Dlg::ID_WXBUTTONDLLDIALOG,MLC3Dlg::wxBtDllDialogClick)
END_EVENT_TABLE() 

IMPLEMENT_APP_NO_MAIN(wxDLLApp) 

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved 
                                         ) 
{ 
    switch (ul_reason_for_call) 
    { 
        case DLL_PROCESS_ATTACH: 
		{       
			//use wxInitialize() if you don't want GUI instead of the following 12 lines 
            wxSetInstance((HINSTANCE)hModule); 
            int argc = 0; 
            char **argv = NULL; 
            wxEntryStart(argc, argv); 
            if ( !wxTheApp || !wxTheApp->CallOnInit() ) 
				return FALSE; 
        } 
        break; 

        case DLL_THREAD_ATTACH: 
        break; 

        case DLL_THREAD_DETACH: 
        break; 

        case DLL_PROCESS_DETACH: 
         wxEntryCleanup(); //use wxUninitialize() if you don't want GUI 
        break; 
    } 
    return TRUE; 
} 

bool wxDLLApp::OnInit() 
{ 
        return true; 
} 

MLC3Dlg::MLC3Dlg(wxWindow *parent, wxWindowID id, 
	const wxString &title, const wxPoint &position, 
	const wxSize& size, long style)
	: wxDialog(parent, id, title, position, size, style)
{
    CreateGUIControls();
}

MLC3Dlg::~MLC3Dlg() {} 

void MLC3Dlg::CreateGUIControls(void)
{
    //Do not add custom code here
	//wxDev-C++ designer will remove them.
	//Add the custom code before or after the blocks
	////GUI Items Creation Start

	this->SetSize(8,8,299,222);
	this->SetTitle(wxT("MLC3"));
	this->Center();
	this->SetIcon(wxNullIcon);
	

	WxButtonDllDialog = new wxButton(this, ID_WXBUTTONDLLDIALOG, wxT("Dll Dialog"), 
		wxPoint(70,140), wxSize(90,27), 0, wxDefaultValidator, wxT("WxButtonDllDialog"));

	wxBtSubmit = new wxButton(this, ID_WXBTSUBMIT, wxT("Submit"), wxPoint(168,139), 
		wxSize(90,27), 0, wxDefaultValidator, wxT("wxBtSubmit"));

	wxEdMail = new wxTextCtrl(this, ID_WXEDIT_MAIL, wxT(""), wxPoint(62,108), 
		wxSize(194,21), 0, wxDefaultValidator, wxT("wxEdMail"));

	wxRbAcceptWithMail = new wxRadioButton(this, ID_WXRBACCEPTWITHMAIL, 
		wxT("Yes, I would like to participate & Autodesk may contact me"), 
		wxPoint(62,62), wxSize(193,33), 0, wxDefaultValidator, wxT("wxRbAcceptWithMail"));

	wxRbAccept = new wxRadioButton(this, ID_WXRBACCEPT, wxT("Yes, I would like to participate"), 
		wxPoint(61,39), wxSize(190,17), 0, wxDefaultValidator, wxT("wxRbAccept"));

	wxRbDeny = new wxRadioButton(this, ID_WXRBDENY, wxT("No, Thank You"), 
		wxPoint(60,12), wxSize(113,17), 0, wxDefaultValidator, wxT("wxRbDeny"));
	////GUI Items Creation End
}

void MLC3Dlg::MLC3DlgClose(wxCloseEvent& event)
{
    Destroy();
}
 

/*
 * wxBtSubmitClick
 */
void MLC3Dlg::wxBtSubmitClick(wxCommandEvent& event)
{
	// insert your code here
	wxMessageBox( wxT("You have pressed The Submit Button!") );
}

/*
 * wxBtDllDialogClick
 */
void MLC3Dlg::wxBtDllDialogClick(wxCommandEvent& event)
{
	// insert your code here
	wxMessageBox( wxT("You have pressed The Dll Dialog Button!") );
}


// extern "C" so we don't need a DEF file 
extern "C" DLLFUNCTIONS_API void TestDialog() 
{ 
	MLC3Dlg dlg(NULL, wxID_ANY, wxString(_("MLC3 Dialog")), 
					wxDefaultPosition, wxSize(400,180)); 
	dlg.ShowModal(); 
} 
// extern "C" so we don't need a DEF file 
extern "C" DLLFUNCTIONS_API void TestDialogHWnd(WXHWND hWnd) 
{ 
	wxWindow win; 
	win.SetHWND((WXHWND)hWnd); 
	win.Enable(false);

	MLC3Dlg dlg(&win, wxID_ANY, wxString(_("MLC3 Dialog")), 
					wxDefaultPosition, wxSize(400,180)); 
	dlg.ShowModal();

	win.Enable(true); 
	win.SetHWND(0);
} 
the host MFC dialog header file:

Code: Select all

// MFCDemoDlg.h : header file
//

#pragma once

#include "wx/wx.h" 

// CMFCDemoDlg dialog
class CMFCDemoDlg : public CDialog
{
// Construction
public:
	CMFCDemoDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	enum { IDD = IDD_MFCDEMO_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support

	typedef void (*DllFunctionHWnd)(WXHWND);
	typedef void (*DllFunction)();

// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButtonDllDialogWithHandle();
public:
	afx_msg void OnBnClickedButtonDllDialogWithoutHandle();
};
the host dialog .cpp file:

Code: Select all

// MFCDemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFCDemo.h"
#include "MFCDemoDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CMFCDemoDlg dialog




CMFCDemoDlg::CMFCDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMFCDemoDlg::IDD, pParent)
{
	m_hIcon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
}

void CMFCDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCDemoDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_DLL_DIALOG_HWND, &CMFCDemoDlg::OnBnClickedButtonDllDialogWithHandle)
	ON_BN_CLICKED(IDC_BUTTON_DLL_DIALOG_NO_HANDLE, &CMFCDemoDlg::OnBnClickedButtonDllDialogWithoutHandle)
END_MESSAGE_MAP()


// CMFCDemoDlg message handlers

BOOL CMFCDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMFCDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMFCDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMFCDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CMFCDemoDlg::OnBnClickedButtonDllDialogWithHandle()
{
	// TODO: Add your control notification handler code here
	HINSTANCE hDll; 
	hDll = LoadLibrary(_TEXT("Dll.dll"));
	DllFunctionHWnd dllFunc=(DllFunctionHWnd)GetProcAddress(hDll,"TestDialogHWnd"); 
	dllFunc(this->m_hWnd);
	FreeLibrary(hDll);
}

void CMFCDemoDlg::OnBnClickedButtonDllDialogWithoutHandle()
{
	// TODO: Add your control notification handler code here
	HINSTANCE hDll; 
	hDll = LoadLibrary(_TEXT("Dll.dll"));
	DllFunction dllFunc=(DllFunction)GetProcAddress(hDll,"TestDialog"); 
	dllFunc();
	FreeLibrary(hDll);
}
The program works fine, but I want to create a dialog object in the host program, how can I do it? thanks very much!

Post Reply