Click here to Skip to main content
Click here to Skip to main content

Using a View (dialog) exported from a dynamically loaded DLL (SDI) in WTL

By , 6 Oct 2003
 

Sample Image - SDIViewWTLDLL.jpg

Introduction

In my effort to use WTL in almost all of my new personal projects I decided that I wanted to be able to load a dialog from a DLL, just like I did with MFC (see http://www.codeproject.com/docview/SdiCViewDll/[^]).

The DLL Implementation

Using Visual Studio (7.1) project wizard, I created a Win32 Application and selected the DLL and Export Symbols options. I next decided that I needed an abstract interface for my FormView classes to derive from. The abstract interface creates a generic framework that allows classes to be derived from at will and define the methods exposed in the abstract interface. If you are not familiar with abstract interfaces see the references section.

Here’s what I came up with for my abstract interface:

struct  IDLLFormView
{
    virtual ~IDLLFormView() { }
    virtual HWND     Initialize(HWND hParentWnd) = 0;
    virtual void     Destroy() = 0;
    vitrual TCHAR*     Description() = 0;
};

With our abstract interface created we are a step closer to being able to load up dialogs into our WTL applications. The next thing that we need to do is to turn our attention to the GetPlugin() function, GetPlugin() will be the only exposed function in the DLL, here’s the declaration:

TESTWTLDLL_API void __stdcall GetPlugin( IDLLFormView** ppOutput );

and the implementation:

TESTWTLDLL_API __stdcall void GetPlugin( IDLLFormView** ppOutput )
{
//Note that error checking has been removed for clarity
    *ppOutput = new CReplaceFormView;
}

Here we are simply creating an instance of our CReplaceFormView and setting our pointer pointer appropriately. If you are familiar with MFC this is exactly the same as we would have done using the CRuntimeClass.

The 'Host' Application

There are endless ways that we can set up the ‘host’ application to load up the DLLs and import the views. In this example I’m not going to do anything fancy, as I want you to understand how to accomplish the task.

Create a ALT/WTL application using the Visual Studio wizard. Under that Application Type tab select SDI and any other options that you may desire, some people like to code WTL in the .h file and others prefer the separation of interface from implementation - it’s really a mater of taste.

Under the User Interface Features in the View Type combo select Form (Dialog Base) and then click Finish. The next part is tricky and if anyone has a better way to do this let me know. What you have to do is unwire the FormView that is created with the application; of course you may want this dialog to be visible; if so leave it wired up.

The next thing that we need to do is create our dialog resource and then create a class that uses the dialog resource as it's template. Create a new ATL/WTL application using the WTL Wizard (you can find a version for VS7.1 here[^]). For the Application Type choose the SDI Application radio and under the User Interface Features choose Form(Dialog based) for the View type.

You can use a Generic window for the View type as there is just a tad bit more difficulty in doing so. But for now just choose the Form view type.

Here’s my class:
class CReplaceFormView : public IDLLFormView, public CDialogImpl
{
public:
    enum { IDD = IDD_TEST_REPLACEFORMVIEW_FORM };


    HWND Initialize(HWND hParentWnd) 
    { 
        return this->Create(hParentWnd);
    }
    void Destroy() { }      // nothing to destroy
    TCHAR* Description()
    {
        return(“Test loading Dialog from DLL”);
}
    BOOL PreTranslateMessage(MSG* pMsg)
    {
        return IsDialogMessage(pMsg);
    }

    BEGIN_MSG_MAP(CReplaceFormView)
        COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnBnClickedButton1)
    END_MSG_MAP()

LRESULT OnBnClickedButton1(WORD /*wNotifyCode*/, 
  WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
};

The next step is to create a way to load up the dialog from the DLL. I chose to place a button on the applications toolbar and when clicked load up the dialog. Here’s the code to do just that:

void CMainFrame::LoadDLLView()
{
   HINSTANCE hLibrary = (HINSTANCE)::LoadLibrary( "testWTLDLL.dll" );
   typedef void (*GETPLUGIN)( IDLLFormView** );
   GETPLUGIN pfnLoad = (GETPLUGIN)::GetProcAddress( hLibrary, "GetPlugin" );
   if(pfnLoad == NULL)        
   {
      DWORD dwLastError = ::GetLastError();
      LPVOID lpMsgBuf;
      ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
         FORMAT_MESSAGE_FROM_SYSTEM|
         FORMAT_MESSAGE_IGNORE_INSERTS, 
         NULL, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
         (LPTSTR)&lpMsgBuf, 0, NULL );
      WTL::CString msg;
      msg.Format("GetProcAddress(\"GetPlugin\") Failed\r\nError "
         "Code: %ld\r\nReason:%s",
         dwLastError, lpMsgBuf); 
      LocalFree(lpMsgBuf);
      ::MessageBox(NULL, msg, "Error", MB_OK );
      return 0;
   }
   IDLLFormView* pOutput = 0;
   pfnLoad( &pOutput );
   m_hWndClient = pOutput->Initialize(m_hWnd);
   CMainFrame::UpdateLayout();
}

This is all fairly common code to anyone that has used DLLs dynamically. If you are unfamiliar with the concepts you can find articles that explain these concepts on this site. Essentially, after we have loaded the DLL we GetProcAddress() for the only exported function in our DLL and then call that function passing in the address of our IDLLFormView*. It's probably wise to check the contents of this pointer before using the methods but in my example I have removed this error check.

Once we have called the Initialize() method of our DLL based class we simply call CMainFrame::UpdateLayout() to refresh the windows display.

Conclusion

This work is based on the work that myself and others have done under MFC. Once I got hooked on WTL I decided that I wanted to implement the same functionality in my new projects. Although I have used this method in production code with much success, it will probably find its way onto an archived CD of dead code as I (as most of you) make my way to .NET.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Dave Loeser
Web Developer
United States United States
Member
Dave has been programming for the past 20+ years first on a variety of platforms and operating systems using various languages. As a hobbyist Dave cut his teeth on the Commodore Pet and the 64 coding in basic and then moving to 6502 ASM. Dave moved to the Amiga using 68000 ASM and then C. His knowledge of the C language offered the stepping stone for him to make his hobby his profession taking a position coding C on an AIX Unix platform. Since then he has worked on many flavors of Unix, QNX, Windows (3.11 – present), and has been coding games for his Pocket PC in his spare time.
 
Dave lives in Indiana with his two teenage daughters and two cats.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralI Met Compile Error too ,Here is Fixed Source Code.memberkr.kim10 Oct '09 - 2:56 
I have been work with SDK/MFC for the 19+years also,but i am WTL beginner interesting WTL nowadays(appealing tiny size),i found same compile error too,so i fixed this some parts of source code and published it at here
 
http://www.durumul.com/baikal/pds/SDIViewWTLDLL_src(Fixed).7z
GeneralSource code doens't workmemberVincent_RICHOMME5 Sep '07 - 22:53 
Hi,
 
source code is not working!!!
It cannot even compile.
Solution project is not pointing to right project, compilations errors :
 
: error C2065: 'IDLLFormView' : undeclared identifier
: error C2065: 'ppOutput' : undeclared identifier
: warning C4229: anachronism used : modifiers on data are ignored
: error C2182: 'GetPlugin' : illegal use of type 'void'
: fatal error C1903: unable to recover from previous error(s); stopping compilation
: not all control paths return a value
 

GeneralRe: Source code doens't workmemberlroels1 Oct '07 - 4:04 
Have a look at the WTL group http://tech.groups.yahoo.com/group/wtl/. In the files section there is a WTL dll example that works fine.
GeneralRe: Source code doens't workmemberVincent_RICHOMME1 Oct '07 - 5:06 
Thanks a lot but finally I got it to work.
I will post the modified sample code as soon as possible (I am waiting to tranfer my web site).

GeneralRe: Source code doens't workmemberMattamoo19 Jan '08 - 6:39 
It would be great if you could post the fix that allowed you to compile. What did you change? Thx.
GeneralRe: Source code doens't workmemberVincent_RICHOMME20 Jan '08 - 1:26 
http://www.smartmobili.com/Downloads/SDIViewWTLDLL_src.zip
GeneralWe can't load a CSplitterWindow view from a DLL!!memberYu_Matrix2 Apr '07 - 7:57 
I want to try loading a SplitterView from a DLL, but it always crashes even we didn't create it just declared a CSplitterWindow variable in the DLL view. Can anyone help me??
 
THANKS!!!
GeneralRe: We can't load a CSplitterWindow view from a DLL!!memberlsmart15 Apr '11 - 8:10 
I meet the same question!
..........

QuestionHow to load a MFC dll to a WTL project?memberfreehawk18 Jan '04 - 15:29 
Hello
How to load a MFC dll to a WTL project? If having sample, could you send it to me by email?
 
Thank you.
-Freehawk
GeneralActiveXmemberTW9 Oct '03 - 1:59 
An ActiveX can be use across different host. Or maybe instead of embed the dialog in a DLL, the DLL can simply return the dialog template string and you can create a child form based on it.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 7 Oct 2003
Article Copyright 2003 by Dave Loeser
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid