WxWidget DLL modeless dialog problem Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

WxWidget DLL modeless dialog problem

Post by greg » Fri Jun 05, 2009 8:44 am

Please help - it is very important for me !!!
I'm trying to load modeless dialog from wxWidget DLL to my exec appl., but
nothing shows. I have problem when unloading dialog too.
Dialog must be non-modal! (with modal there is no problem)
and wxwidget dll dialog must be set up within my main exe dialog (not another instance)
I followed the article http://wiki.wxwindows.org/Creating_A_DL ... pplication but still having problems.
Where is the bug ?
Currently I'm using wxWidget ver. 2.8.2 on VC 6.0.
Here is my code.

test.h

Code: Select all

#pragma once

#include "wx/wx.h"

#include "windows.h"


#ifdef FROMDLL_EXPORTS
#define FROMDLL_API __declspec(dllexport)
#else
#define FROMDLL_API __declspec(dllimport)
#endif

extern "C" FROMDLL_API void DLLFunction(HWND);


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

class MyFrame: public wxFrame
{
public:
    MyFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size);
    ~MyFrame();

    void OnQuit(wxCloseEvent& event);
        void OnButton(wxCommandEvent& evt);

        DECLARE_EVENT_TABLE()

};
test.cpp

Code: Select all

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

#include "FromDLL.h"

MyFrame   *frame = NULL;

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
        EVT_BUTTON(125,MyFrame::OnButton)
    EVT_CLOSE(MyFrame::OnQuit)
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:
                wxApp::SetInstance(new wxDLLApp());
                wxInitialize();
                break;
        case DLL_PROCESS_DETACH:
                wxEntryCleanup();
                break;
        }
        return TRUE;
}

extern "C" __declspec(dllexport) void DLLFunction(HWND handle)
{
        wxWindow win;
        win.SetHWND((WXHWND)handle);
        win.Enable(false);

	frame = new MyFrame(&win, -1, "Minimal wxWindows App",
                                 wxPoint(50, 50), wxSize(450, 340));

        wxButton * pButton1 = new wxButton(frame, 125, "button 1");

        frame->Show();
    	frame->Centre();

        win.Enable(true);
        win.SetHWND(0);

}

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

void MyFrame::OnButton(wxCommandEvent& evt)
{
        wxMessageBox("You really did it.... I don't believe it!");
}

void MyFrame::OnQuit(wxCloseEvent& event)
{
//        wxMessageBox("exit!");
//Destroy();
    frame->Close(true);
}

MyFrame::~MyFrame()
{
}

MyFrame::MyFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size)
       : wxFrame(parent,-1, title, pos, size)
{
    Init();
}
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Re: WxWidget DLL modeless dialog problem

Post by tan » Fri Jun 05, 2009 10:30 am

Hi!
greg wrote:Please help - it is very important for me !!!
I'm trying to load modeless dialog from wxWidget DLL to my exec appl., but
nothing shows. I have problem when unloading dialog too.
As i understand, your app isn't wx app. For this case this code works for me:

dll.cpp

Code: Select all

#include <wx/wx.h>
#include <wx/string.h>
#include <wx/frame.h>

class CMyApp : public wxApp
{
public:
      bool OnInit();
};

IMPLEMENT_APP_NO_MAIN(CMyApp)
DECLARE_APP(CMyApp)

BOOL APIENTRY DllMain(HMODULE Module,DWORD Reason,LPVOID)
{
        if(Reason==DLL_PROCESS_DETACH)
        {
                wxEntryCleanup();
        }
        else if(Reason==DLL_PROCESS_ATTACH)
        {
                int argc = 0;
                char** argv = NULL;
                if(!wxEntryStart(argc, argv) ||
                        !wxTheApp ||
                        !wxTheApp->CallOnInit())
                {
                        return FALSE;
                }
        }
       
        return TRUE;
}

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

class MyFrame : public wxFrame
{
public:
    MyFrame(wxWindow* parent=0, const wxString& title=_("Data Base Login"));

protected:
    wxTextCtrl* m_dsn;

    void OnClose(wxCloseEvent& event);

    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
   EVT_CLOSE(MyFrame::OnClose)
END_EVENT_TABLE()

void
MyFrame::OnClose(wxCloseEvent &ev)
{
    wxMessageBox("I am destroyed!!!!!!!!!!!!!!!!!!");
//    Destroy();	// It doesn't work in wx DLL (with no wx app)
    delete this;
}

MyFrame::MyFrame(wxWindow* parent, const wxString& title )
       : wxFrame(parent, -1, title)
{
    m_dsn  = new wxTextCtrl(this, -1, "", wxPoint(10, 10), wxSize(200, -1), wxTE_MULTILINE);
}

/*============================================================================*/

extern "C"
void __declspec(dllexport)
ShowDlg()
{
    MyFrame* pframe = new MyFrame();
    pframe->Show();
}

/*============================================================================*/
WIN32 app:

Code: Select all

...
void
Test_OnAnyEvent(HWND hwnd, int x, int y, int flag, int dummy)
{
      HMODULE h = LoadLibrary("dll.dll");
      if( h )
      {
          FARPROC pf;
          pf = GetProcAddress(h, "ShowDlg");
          if( pf )
          {
              pf();
          }
      }
}
...
EDIT:
And don't create fake parent wxWindow on stack:

Code: Select all

extern "C" __declspec(dllexport) void DLLFunction(HWND handle)
{
        wxWindow* win = new wxWindow;
        win->SetHWND((WXHWND)handle);

        frame = new MyFrame(win, -1, "Minimal wxWindows App",
                                 wxPoint(50, 50), wxSize(450, 340));
...
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Fri Jun 05, 2009 12:52 pm

Tan
Thank's for Your fast answer.
As You guess, my exe appl is not xwWidget app
But still having problem ...
I want to display my modeless dialog from wxwidget DLL
but INSIDE my main exe appl., not another window
instance. I don't know if You exactly understand me (I'm from Poland), but belive me it is very important for me.
Please help me.
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Fri Jun 05, 2009 1:08 pm

greg wrote:Tan
Thank's for Your fast answer.
As You guess, my exe appl is not xwWidget app
But still having problem ...
I want to display my modeless dialog from wxwidget DLL
but INSIDE my main exe appl., not another window
instance.
What do you mean "inside my main app"? Inside the main frame?
Did you try my sample? It works.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Fri Jun 05, 2009 1:23 pm

Tan
Of course Your snippet is working.
I tried it. It works perfectly.

But there is one problem I can not solve.
I know it is difficult to explain but I will try.
I'm trying to write some app. inside Autocad/Microstation
so I want to load wxwidget dll dialog from my main Autocad/Microstation appl.
But when I'm trying to load dll dialog it is opend as another Windows instance.
I want my dll dialog be as a part of Autocad/Microstation program.
I don't know if You still understand me and don't know to expalin another way.
Maybe give You some example?
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Fri Jun 05, 2009 2:07 pm

greg wrote:Tan
Of course Your snippet is working.
I tried it. It works perfectly.

But there is one problem I can not solve.
I know it is difficult to explain but I will try.
I'm trying to write some app. inside Autocad/Microstation
so I want to load wxwidget dll dialog from my main Autocad/Microstation appl.
But when I'm trying to load dll dialog it is opend as another Windows instance.
What do you mean? It appears in the taskbar as another app? Try to create the frame with wxFRAME_NO_TASKBAR style.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Fri Jun 05, 2009 7:39 pm

I simply want to load my dll dialog within my main exe apps' window

wxWindow* parent;

Code: Select all

frame = new MyFrame(parent, -1, "Minimal wxWindows App",
                                 wxPoint(50, 50), wxSize(450, 340)); 
where parent is handle from my exe apps window.
I must pass parent variable through dll.
Do You understand me now ?
Thanks for Your previous help of course.

Can You help me now ?
:)
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Sat Jun 06, 2009 7:22 am

greg wrote:I simply want to load my dll dialog within my main exe apps' window
You mean that the dialog must move around ONLY inside the main app window? Hmm... But wx doesn't provide this behaviour (except for MDI).
greg wrote: wxWindow* parent;

Code: Select all

frame = new MyFrame(parent, -1, "Minimal wxWindows App",
                                 wxPoint(50, 50), wxSize(450, 340)); 
where parent is handle from my exe apps window.
I must pass parent variable through dll.
There isn't problem with it. You can pass HWND of the parent frame, but it will not do that you want. You have to do that yourself (e.g. handle the dialog moving and restrict the dialog position by parent window).
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Sat Jun 06, 2009 1:02 pm

Sorry
I'm a little confused. My problem is not related with wondows moving.
I try to explain You by the simple example.
Just take a look at the sample from wxwidget: sample\dialogs
Execute main appl. called dialogs.exe and then force
from menu: dialogs->searching->find dialog
opens modeless dialog from main window "wxWidget dialog example".
That's what I want to reach, but dialog called "Find dialog" I have to load from my wxwidget dll.
Am I clear now?
So are You still ready to help me?
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Sun Jun 07, 2009 6:34 am

greg wrote:Sorry
I'm a little confused. My problem is not related with wondows moving.
I try to explain You by the simple example.
Just take a look at the sample from wxwidget: sample\dialogs
Execute main appl. called dialogs.exe and then force
from menu: dialogs->searching->find dialog
opens modeless dialog from main window "wxWidget dialog example".
That's what I want to reach, but dialog called "Find dialog" I have to load from my wxwidget dll.
Hmm... may be you mean that the dialog must always be on top of its parent? Create the dialog with wxFRAME_FLOAT_ON_PARENT style.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Sun Jun 07, 2009 11:06 am

Ok we still do not understand ourselves
Let's take a look at Your first answer

You wrote

in Your sample parent arg = 0 so You create new window
independent from my main exe apps' dialog.

Code: Select all

    MyFrame(wxWindow* parent=0, const wxString& title=_("Data Base Login"));
and next

And don't create fake parent wxWindow on stack:

Code: Select all

extern "C" __declspec(dllexport) void DLLFunction(HWND handle)
{
        wxWindow* win = new wxWindow;
        win->SetHWND((WXHWND)handle);

        frame = new MyFrame(win, -1, "Minimal wxWindows App",
                                 wxPoint(50, 50), wxSize(450, 340));
...

That what I'd like to do except creating
new window (wxWindow* win = new wxWindow) but
passing win argument via HWND from my mian exe apps.
But still having problem; what am I doing wrong?
Waiting for Your answer.
:)
Regards
Greg

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Tue Jun 09, 2009 9:23 am

Sorry for the late answer. I have been very busy last days :)
greg wrote: That what I'd like to do except creating
new window (wxWindow* win = new wxWindow)
Why?
greg wrote: but
passing win argument via HWND from my mian exe apps.
But still having problem; what am I doing wrong?
What the problem? What exactly does happen? Show some code...

It works perfectly for me. Here is the code:
dll.cpp

Code: Select all

#include <wx/wx.h>
#include <wx/string.h>
#include <wx/frame.h>

class CMyApp : public wxApp
{
public:
      bool OnInit();
};

IMPLEMENT_APP_NO_MAIN(CMyApp)
DECLARE_APP(CMyApp)

BOOL APIENTRY DllMain(HMODULE Module,DWORD Reason,LPVOID)
{
        if(Reason==DLL_PROCESS_DETACH)
        {
                wxEntryCleanup();
        }
        else if(Reason==DLL_PROCESS_ATTACH)
        {
                int argc = 0;
                char** argv = NULL;
                if(!wxEntryStart(argc, argv) ||
                        !wxTheApp ||
                        !wxTheApp->CallOnInit())
                {
                        return FALSE;
                }
        }
       
        return TRUE;
}

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

class MyFrame : public wxFrame
{
public:
    MyFrame(wxWindow* parent=0, const wxString& title=_("Data Base Login"));

protected:
    wxTextCtrl* m_dsn;

    void OnClose(wxCloseEvent& event);

    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
   EVT_CLOSE(MyFrame::OnClose)
END_EVENT_TABLE()

void
MyFrame::OnClose(wxCloseEvent &ev)
{
    wxMessageBox("I am destroyed!!!!!!!!!!!!!!!!!!");
//    Destroy();	// It doesn't work in DLL
    delete this;
}

MyFrame::MyFrame(wxWindow* parent, const wxString& title )
       : wxFrame(parent, -1, title, wxDefaultPosition, wxDefaultSize,       wxDEFAULT_FRAME_STYLE|wxFRAME_NO_TASKBAR|wxFRAME_FLOAT_ON_PARENT)
{
    m_dsn  = new wxTextCtrl(this, -1, "", wxPoint(10, 10), wxSize(200, -1), wxTE_MULTILINE);
}

/*============================================================================*/

extern "C"
void __declspec(dllexport)
ShowDlg(HWND parent)
{
    wxWindow* win = new wxWindow;
    win->SetHWND((WXHWND)parent);

    MyFrame* pframe = new MyFrame(win);
    pframe->Show();
}

/*============================================================================*/
WIN32 app:

Code: Select all

...
typedef void (*PF)(HWND);

void
Test_OnMouseDbl(HWND hwnd, int x, int y, int flag, int dummy)
{
//    MessageBox(hwnd, "OK Command was recieved!", "Message", MB_OK);
      HMODULE h = LoadLibrary("dll.dll");
      if( h )
      {
          PF pf;
          (FARPROC)pf = GetProcAddress(h, "ShowDlg");
          if( pf )
          {
              pf(hwnd);
          }
      }
}
...
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

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

Post by upCASE » Tue Jun 09, 2009 11:51 am

Hi!
greg wrote:But when I'm trying to load dll dialog it is opend as another Windows instance.
I want my dll dialog be as a part of Autocad/Microstation program.
Just to clarify things a bit:
You're writing an Autcad plugin, correct?
Now, is the problem that you need the Autocad main window as the parent of your dialog, or does Autocad provide you with a window that all you controls have to reside in? In other words: Does Autocad open a window/dialog for you and passes you the HANDLE of this window? (Just asking because this is what it is like when coding VST plugins).
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

greg
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Sep 12, 2008 7:17 am

Post by greg » Fri Jun 12, 2009 6:39 am

Tan
Sorry for my silent till now, I was absent.

Thank You very much for Your accurate reply !!!
You are great and very halpful man !!!
Now Your sample works for me perfectly.
That's what I'd like to reach.
How shall I return your kindness Tan?
If I could I I'd like to stand You a beer.

Ps
And some explanation for upCASE:
I'm trying to develop some plugin for MicroStation
using wxWidget dialogs. So I need the MicroStation main window as the parent of my apps' dialog.

slytron
Earned a small fee
Earned a small fee
Posts: 11
Joined: Sun Jun 14, 2009 5:04 pm

Post by slytron » Tue Jun 30, 2009 4:56 pm

I spent several hours trying variations of the solution on wxWidgetsWiki and could not make it work. I found this solution and it worked great. THANKS. wish I had found this first.

Post Reply