| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 | 
							- /////////////////////////////////////////////////////////////////////////////
 
- // Name:        my_dll.cpp
 
- // Purpose:     Sample showing how to use wx from a DLL
 
- // Author:      Vaclav Slavik
 
- // Created:     2009-12-03
 
- // Copyright:   (c) 2009 Vaclav Slavik
 
- // Licence:     wxWindows licence
 
- /////////////////////////////////////////////////////////////////////////////
 
- // ============================================================================
 
- // declarations
 
- // ============================================================================
 
- // ----------------------------------------------------------------------------
 
- // headers
 
- // ----------------------------------------------------------------------------
 
- #include "wx/wxprec.h"
 
- #ifdef __BORLANDC__
 
-     #pragma hdrstop
 
- #endif
 
- #ifndef __WINDOWS__
 
-     #error "This sample is Windows-only"
 
- #endif
 
- #include "wx/app.h"
 
- #include "wx/dynlib.h"
 
- #include "wx/frame.h"
 
- #include "wx/panel.h"
 
- #include "wx/sizer.h"
 
- #include "wx/stattext.h"
 
- #include "wx/button.h"
 
- #include "wx/thread.h"
 
- #include "wx/msgdlg.h"
 
- #include "wx/msw/wrapwin.h"
 
- #include <process.h> // for _beginthreadex()
 
- #include "my_dll.h"
 
- // ----------------------------------------------------------------------------
 
- // GUI classes
 
- // ----------------------------------------------------------------------------
 
- class MyDllFrame : public wxFrame
 
- {
 
- public:
 
-     MyDllFrame(wxWindow *parent, const wxString& label);
 
-     void OnAbout(wxCommandEvent& event);
 
-     wxDECLARE_EVENT_TABLE();
 
- };
 
- static const int CMD_SHOW_WINDOW = wxNewId();
 
- static const int CMD_TERMINATE = wxNewId();
 
- class MyDllApp : public wxApp
 
- {
 
- public:
 
-     MyDllApp();
 
- private:
 
-     void OnShowWindow(wxThreadEvent& event);
 
-     void OnTerminate(wxThreadEvent& event);
 
- };
 
- // ============================================================================
 
- // implementation
 
- // ============================================================================
 
- // ----------------------------------------------------------------------------
 
- // MyDllFrame
 
- // ----------------------------------------------------------------------------
 
- wxBEGIN_EVENT_TABLE(MyDllFrame, wxFrame)
 
-     EVT_BUTTON(wxID_ABOUT, MyDllFrame::OnAbout)
 
- wxEND_EVENT_TABLE()
 
- MyDllFrame::MyDllFrame(wxWindow *parent, const wxString& label)
 
-     : wxFrame(parent, wxID_ANY, label)
 
- {
 
-     wxPanel *p = new wxPanel(this, wxID_ANY);
 
-     wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
 
-     sizer->Add
 
-            (
 
-                new wxStaticText
 
-                    (
 
-                        p, wxID_ANY,
 
-                        wxString::Format
 
-                        (
 
-                            "Running using %s\n"
 
-                            "wxApp instance is %p, thread ID %ld",
 
-                            wxVERSION_STRING,
 
-                            wxApp::GetInstance(),
 
-                            wxThread::GetCurrentId()
 
-                        )
 
-                    ),
 
-                wxSizerFlags(1).Expand().Border(wxALL, 10)
 
-            );
 
-     sizer->Add
 
-            (
 
-                new wxButton(p, wxID_ABOUT, "Show info"),
 
-                wxSizerFlags(0).Right().Border(wxALL, 10)
 
-            );
 
-     p->SetSizerAndFit(sizer);
 
-     wxSizer *fsizer = new wxBoxSizer(wxVERTICAL);
 
-     fsizer->Add(p, wxSizerFlags(1).Expand());
 
-     SetSizerAndFit(fsizer);
 
- }
 
- void MyDllFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxMessageBox("This window is running in its own thread,\n"
 
-                  "using private wxWidgets instance compiled into the DLL.",
 
-                  "About",
 
-                  wxOK | wxICON_INFORMATION);
 
- }
 
- // ----------------------------------------------------------------------------
 
- // MyDllApp
 
- // ----------------------------------------------------------------------------
 
- MyDllApp::MyDllApp()
 
- {
 
-     // Keep the wx "main" thread running even without windows. This greatly
 
-     // simplifies threads handling, because we don't have to correctly
 
-     // implement wx-thread restarting.
 
-     //
 
-     // Note that this only works if you don't explicitly call ExitMainLoop(),
 
-     // except in reaction to wx_dll_cleanup()'s message. wx_dll_cleanup()
 
-     // relies on the availability of wxApp instance and if the event loop
 
-     // terminated, wxEntry() would return and wxApp instance would be
 
-     // destroyed.
 
-     //
 
-     // Also note that this is efficient, because if there are no windows, the
 
-     // thread will sleep waiting for a new event. We could safe some memory
 
-     // by shutting the thread down when it's no longer needed, though.
 
-     SetExitOnFrameDelete(false);
 
-     Connect(CMD_SHOW_WINDOW,
 
-             wxEVT_THREAD,
 
-             wxThreadEventHandler(MyDllApp::OnShowWindow));
 
-     Connect(CMD_TERMINATE,
 
-             wxEVT_THREAD,
 
-             wxThreadEventHandler(MyDllApp::OnTerminate));
 
- }
 
- void MyDllApp::OnShowWindow(wxThreadEvent& event)
 
- {
 
-     wxFrame *f = new MyDllFrame(NULL, event.GetString());
 
-     f->Show(true);
 
- }
 
- void MyDllApp::OnTerminate(wxThreadEvent& WXUNUSED(event))
 
- {
 
-     ExitMainLoop();
 
- }
 
- // ----------------------------------------------------------------------------
 
- // application startup
 
- // ----------------------------------------------------------------------------
 
- // we can't have WinMain() in a DLL and want to start the app ourselves
 
- IMPLEMENT_APP_NO_MAIN(MyDllApp)
 
- namespace
 
- {
 
- // Critical section that guards everything related to wxWidgets "main" thread
 
- // startup or shutdown.
 
- wxCriticalSection gs_wxStartupCS;
 
- // Handle of wx "main" thread if running, NULL otherwise
 
- HANDLE gs_wxMainThread = NULL;
 
- //  wx application startup code -- runs from its own thread
 
- unsigned wxSTDCALL MyAppLauncher(void* event)
 
- {
 
-     // Note: The thread that called run_wx_gui_from_dll() holds gs_wxStartupCS
 
-     //       at this point and won't release it until we signal it.
 
-     // We need to pass correct HINSTANCE to wxEntry() and the right value is
 
-     // HINSTANCE of this DLL, not of the main .exe, use this MSW-specific wx
 
-     // function to get it. Notice that under Windows XP and later the name is
 
-     // not needed/used as we retrieve the DLL handle from an address inside it
 
-     // but you do need to use the correct name for this code to work with older
 
-     // systems as well.
 
-     const HINSTANCE
 
-         hInstance = wxDynamicLibrary::MSWGetModuleHandle("my_dll",
 
-                                                          &gs_wxMainThread);
 
-     if ( !hInstance )
 
-         return 0; // failed to get DLL's handle
 
-     // IMPLEMENT_WXWIN_MAIN does this as the first thing
 
-     wxDISABLE_DEBUG_SUPPORT();
 
-     // We do this before wxEntry() explicitly, even though wxEntry() would
 
-     // do it too, so that we know when wx is initialized and can signal
 
-     // run_wx_gui_from_dll() about it *before* starting the event loop.
 
-     wxInitializer wxinit;
 
-     if ( !wxinit.IsOk() )
 
-         return 0; // failed to init wx
 
-     // Signal run_wx_gui_from_dll() that it can continue
 
-     HANDLE hEvent = *(static_cast<HANDLE*>(event));
 
-     if ( !SetEvent(hEvent) )
 
-         return 0; // failed setting up the mutex
 
-     // Run the app:
 
-     wxEntry(hInstance);
 
-     return 1;
 
- }
 
- } // anonymous namespace
 
- // ----------------------------------------------------------------------------
 
- // public DLL interface
 
- // ----------------------------------------------------------------------------
 
- extern "C"
 
- {
 
- void run_wx_gui_from_dll(const char *title)
 
- {
 
-     // In order to prevent conflicts with hosting app's event loop, we
 
-     // launch wx app from the DLL in its own thread.
 
-     //
 
-     // We can't even use wxInitializer: it initializes wxModules and one of
 
-     // the modules it handles is wxThread's private module that remembers
 
-     // ID of the main thread. But we need to fool wxWidgets into thinking that
 
-     // the thread we are about to create now is the main thread, not the one
 
-     // from which this function is called.
 
-     //
 
-     // Note that we cannot use wxThread here, because the wx library wasn't
 
-     // initialized yet. wxCriticalSection is safe to use, though.
 
-     wxCriticalSectionLocker lock(gs_wxStartupCS);
 
-     if ( !gs_wxMainThread )
 
-     {
 
-         HANDLE hEvent = CreateEvent
 
-                         (
 
-                             NULL,  // default security attributes
 
-                             FALSE, // auto-reset
 
-                             FALSE, // initially non-signaled
 
-                             NULL   // anonymous
 
-                         );
 
-         if ( !hEvent )
 
-             return; // error
 
-         // NB: If your compiler doesn't have _beginthreadex(), use CreateThread()
 
-         gs_wxMainThread = (HANDLE)_beginthreadex
 
-                                   (
 
-                                       NULL,           // default security
 
-                                       0,              // default stack size
 
-                                       &MyAppLauncher,
 
-                                       &hEvent,        // arguments
 
-                                       0,              // create running
 
-                                       NULL
 
-                                   );
 
-         if ( !gs_wxMainThread )
 
-         {
 
-             CloseHandle(hEvent);
 
-             return; // error
 
-         }
 
-         // Wait until MyAppLauncher signals us that wx was initialized. This
 
-         // is because we use wxMessageQueue<> and wxString later and so must
 
-         // be sure that they are in working state.
 
-         WaitForSingleObject(hEvent, INFINITE);
 
-         CloseHandle(hEvent);
 
-     }
 
-     // Send a message to wx thread to show a new frame:
 
-     wxThreadEvent *event =
 
-         new wxThreadEvent(wxEVT_THREAD, CMD_SHOW_WINDOW);
 
-     event->SetString(title);
 
-     wxQueueEvent(wxApp::GetInstance(), event);
 
- }
 
- void wx_dll_cleanup()
 
- {
 
-     wxCriticalSectionLocker lock(gs_wxStartupCS);
 
-     if ( !gs_wxMainThread )
 
-         return;
 
-     // If wx main thread is running, we need to stop it. To accomplish this,
 
-     // send a message telling it to terminate the app.
 
-     wxThreadEvent *event =
 
-         new wxThreadEvent(wxEVT_THREAD, CMD_TERMINATE);
 
-     wxQueueEvent(wxApp::GetInstance(), event);
 
-     // We must then wait for the thread to actually terminate.
 
-     WaitForSingleObject(gs_wxMainThread, INFINITE);
 
-     CloseHandle(gs_wxMainThread);
 
-     gs_wxMainThread = NULL;
 
- }
 
- } // extern "C"
 
 
  |