I have written a demo program about the dll which encapsulates a subclass of wxDialog, and it is ok, but who I invoke the dll in a win32 application, it has a problem who I close the dialog, the functions is all right, can you help me to see what happens and how to fix it ? thanks for your correcting.
Platform: windows XP, wxwidgets 2.6.0, vs 2005
This is my Dll files:
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 DLLFunction(HWND);
extern "C" DLLFUNCTIONS_API void TestReport(HWND handle);
//extern "C" DLLFUNCTIONS_API void TestDialog(HWND handle);
class wxDLLApp : public wxApp
{
bool OnInit();
void OnButton(wxCommandEvent& evt);
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);
};
// 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_BUTTON(123,wxDLLApp::OnButton)
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;
}
// extern "C" so we don't need a DEF file
// This is the function to be called from the host app
extern "C" DLLFUNCTIONS_API void DLLFunction(HWND handle)
{
// Create a dummy wxWindow so we can use the HWND passed from the
// host application
wxWindow win;
win.SetHWND((WXHWND)handle);
win.Enable(false);
wxDialog dlg(&win, -1, wxT("wxDialog in DLL"), wxDefaultPosition, wxSize(150,150));
wxButton b(&dlg, 123,wxT("Press me please"));
dlg.ShowModal();
// Clean up else the caller can't use its window
win.Enable(true);
win.SetHWND(0);
}
extern "C" DLLFUNCTIONS_API void TestReport(HWND handle)
{
wxWindow win;
win.SetHWND((WXHWND)handle);
win.Enable(false);
/* wxDialog dlg(&win, wxID_ANY, wxString(_("About")), wxDefaultPosition, wxSize(400,180));
wxHtmlWindow html1(&dlg,wxID_ANY, wxDefaultPosition, wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
html1.SetPage(wxT("<html><body><h1>Error</h1>Some error occurred )</body></hmtl>"));
dlg.ShowModal();
*/
MLC3Dlg dlg(&win, wxID_ANY, wxString(_("About")), wxDefaultPosition, wxSize(400,180));
dlg.ShowModal();
// Clean up else the caller can't use its window
win.Enable(true);
win.SetHWND(0);
}
bool wxDLLApp::OnInit()
{
return true;
}
void wxDLLApp::OnButton(wxCommandEvent& evt)
{
wxMessageBox(wxT("You really did it.... I don't believe it!"));
}
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("Load 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 DllDialog Button!") );
}
Code: Select all
// EXE.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "EXE.h"
#include <assert.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
typedef void (*DLLFunctionPtr) (HWND);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_EXE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EXE));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EXE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EXE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONUP:
{
// Load up the DLL and call DLLFunction(
HMODULE hModule = LoadLibrary(_TEXT("TestDll.dll"));
//assert(hModule);
DLLFunctionPtr pProc = (DLLFunctionPtr)GetProcAddress(hModule, "DLLFunction");
assert(pProc);
(pProc)(hWnd);
FreeLibrary(hModule);
}
break;
case WM_RBUTTONUP:
{
// Load up the DLL and call DLLFunction(
HMODULE hModule = LoadLibrary(_TEXT("TestDll.dll"));
assert(hModule);
DLLFunctionPtr pProc = (DLLFunctionPtr)GetProcAddress(hModule, "TestReport");
assert(pProc);
(pProc)(hWnd);
FreeLibrary(hModule);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}