none
Creating window in regular DLL that link MFC through a entry point function RRS feed

  • Question

  • I tried sample MFC code.
    This DLL's entry point is My_Entry() which is exported by MFCDLL.DEF file for other application to call it and removed existing DllEntry() because I will add initialize code in the CMyApp.InitInstance().

    // MFCDLL.def LIBRARY EXPORTS ; Explicit exports can go here DS_Entry ------------------------------------------------------------------------- // MFCDLL.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <afxwin.h> class CMyApp : public CWinApp { public: virtual BOOL InitInstance (); }; class CMainWindow : public CFrameWnd { public: CMainWindow(); protected: afx_msg void OnPaint (); DECLARE_MESSAGE_MAP() }; CMyApp myApp; BOOL CWinApp::InitInstance() { m_pMainWnd = new CMainWindow; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() CMainWindow::CMainWindow() { Create (NULL, _T("The Hello Window")); } void CMainWindow::OnPaint() { CPaintDC dc (this); CRect rect; GetClientRect(&rect); dc.DrawText(_T("Hello, MFC"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); } void FAR PASCAL My_Entry( ) { // How to initialize MFC here to show Hello, MFC window?

    // I tried following function here but nothing happened

    // AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);

    }

    This is a typical MFC hello program except My_Entry which is the entry point of this DLL and called from other application program.
    MFC class interfaces cannot be exported and for some other reason, this DLL should have this kind of structure.
    I want to know how to add code in the My_Entry() to show Hello window.
    What should I do in the My_Entry()?


    • Edited by Jeff0803 Friday, September 18, 2015 12:54 AM
    Thursday, September 17, 2015 4:30 PM

Answers

  • The answer is in the solution that I posted at http://1drv.ms/1gHUyhm

    The exported function uses MFC to spin up a UI thread that has it's own message pump for the frame window that gets created.

    If you already have a message pump running then you need to structure the MFC DLL and it's exported functions to conform to the guidance I previously posted, repeated here:

    "Regular DLLs must have a CWinApp-derived class and a single object of that application class, as does an MFC application. However, the CWinApp object of the DLL does not have a main message pump, as does the CWinApp object of an application.

    Note that the CWinApp::Run mechanism does not apply to a DLL, because the application owns the main message pump. If your DLL brings up modeless dialogs or has a main frame window of its own, your application's main message pump must call a DLL-exported routine that calls CWinApp::PreTranslateMessage."

    • Edited by RLWA32 Saturday, September 26, 2015 7:53 PM
    • Marked as answer by Jeff0803 Saturday, September 26, 2015 11:10 PM
    Saturday, September 26, 2015 7:45 PM

All replies

  • My_Entry which is the entry point of this DLL

    Do you mean dllmain function? For MFC regular dll, there is a internal dllmain function to initialize MFC. And the MFC-provided DllMain function calls InitInstance when your DLL is loaded and it calls ExitInstance before the DLL is unloaded. So you should not use you own DllMain in your MFC regular dll.

    I don't know what you want to do, export a dialog class, or export some function to show a dialog? I made a simple test for MFC regular dll.

    Create a MFC regular dll by MFC project template.

    Add a class derive from CDialog. Check below code snippet:

    Note: AFX_MANAGE_STATE(AfxGetStaticModuleState());

    "If you have an exported function in a DLL, such as one that launches a dialog box in the DLL, this template is actually stored in the DLL module. You need to switch the module state for the correct handle to be used."

    class CMyDlg : public CDialog
    {
    	DECLARE_DYNAMIC(CMyDlg)
    
    public:
    	CMyDlg(CWnd* pParent = NULL);   // standard constructor
    	virtual ~CMyDlg();
    	static void __stdcall ShowDlg();
    // Dialog Data
    	enum { IDD = IDD_MYDLG };
    
    protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    
    	DECLARE_MESSAGE_MAP()
    public:
    	afx_msg void OnPaint();
    };
    
    ....cpp file
    
    void CMyDlg::ShowDlg()
    {
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
    	CMyDlg dlg;
    	dlg.DoModal();
    }
    
    void CMyDlg::OnPaint()
    {
    	CPaintDC dc(this); // device context for painting
    	// TODO: Add your message handler code here
    	// Do not call CDialog::OnPaint() for painting messages
    	dc.TextOutW(10, 10, L"this is a dialog from dll");
    }

    Export the ShowDlg function in .def file:

    EXPORTS
        ; Explicit exports can go here
    	ShowDlg @1

    Now you will get a dll.

    You could test it in a Console project. MFC_RegularDlg.dll is a MFC regular dll.

    #include "stdafx.h"
    #include "windows.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HINSTANCE hInst = LoadLibrary(L"MFC_RegularDlg.dll");
    	if (hInst == NULL)
    	{
    		printf("dll" could not be loaded.");
    
    	}
    
    	void(__stdcall *ShowDlg)();
    	ShowDlg = (void(__stdcall *)()) GetProcAddress(hInst, "ShowDlg");
    	ShowDlg();
    	return 0;
    }

    Now you could get a dialog from dll.

    If you want to export a MFC dialog class from a dll, I suggest you create a MFC extension dll.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, September 18, 2015 4:34 AM

  • Do you mean dllmain function? 

    No, I don't mean dllmain.

    In case of regular DLL that link MFC, DllMain is hidden in the MFC class.

    I mean a application programs calls MyEntry() function of this DLL and the MyEntry() should do something to create a Hello MFC window.

    (Other application program call MyEntry() of DLL=>MyEntry() make MFC window creation)

    I already tried following calls in the MyEntry() but still couldn't create window.

      myApp.InitInstance(); // failed
      AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); // failed   

     




    • Edited by Jeff0803 Friday, September 18, 2015 8:50 PM
    Friday, September 18, 2015 8:33 PM
  • The OP's use of the term "entry point" is  confusing.  It is unclear if he intends to merely call an exported function or if he wants an actual entry point function, called during process and thread attach/detach.  If the former, it seems he is looking for code that will export a function from a DLL which will create a frame window. If the latter, it's probably not a good idea since one is supposed to avoid calling into User32.DLL or Gdi32.dll from within an entry point function.
    Friday, September 18, 2015 9:34 PM
  • Yes RLWA32 is right. entry point may make reader confused.

    Please ignore entry point.

    I just mean the function which is exported and called from other application program.

    In this function(I'll use MyFunc() instead of My_Entry() to avoid confusing), I have to  somehow make run AppWin::InitInstance and Create Window.

    Shu Hu's code works fine.

    However I want to create Window derived CFrameWnd, not CDialog.

    Can somebody add or modify the code I posted upper?

    • Edited by Jeff0803 Friday, September 18, 2015 11:41 PM
    Friday, September 18, 2015 11:11 PM
  • The MFC online documentation refers to two sample applications that demonstrate how to create and use MFC DLLs.  They are DLLHUSK and DLLScreenCap.  I did not find them available for download online but I have uploaded them and they are available for you to download and study.  Be advised that they are from an older version of Visual Studio/Visual C++ and will need to be converted for use in modern versions.  The MFC code they contain is equally old, but informative.

    You can obtain them from the following links:

    DLLHUSK sample

    DLLScreenCap sample

    Saturday, September 19, 2015 11:08 AM
  • Thanks.

    I'll look into this sample coded.

    Saturday, September 19, 2015 8:18 PM
  • DLLHUSK is fit to my case because it's a MFC extension DLL which is called only from  MFC and my DLL should be called from any type of application.

    DLLScreenCap is not fit to my case too.

     
    Sunday, September 20, 2015 2:11 AM
  • I never said they were the answer to your particular circumstance. 

    They were samples that show how MFC DLLs function and were meant to further your understanding.

    Here's some additional things for you to think about;

    A regular DLL dynamically linked to MFC is a DLL that uses MFC internally, and the exported functions in the DLL can be called by either MFC or non-MFC executables. As the name describes, this kind of DLL is built using the dynamic-link library version of MFC (also known as the shared version of MFC). Functions are usually exported from a regular DLL using the standard C interface.

    You must add the AFX_MANAGE_STATE macro at the beginning of all the exported functions in regular DLLs that dynamically link to MFC to set the current module state to the one for the DLL.

    Regular DLLs must have a CWinApp-derived class and a single object of that application class, as does an MFC application. However, the CWinApp object of the DLL does not have a main message pump, as does the CWinApp object of an application.

    Note that the CWinApp::Run mechanism does not apply to a DLL, because the application owns the main message pump. If your DLL brings up modeless dialogs or has a main frame window of its own, your application's main message pump must call a DLL-exported routine that calls CWinApp::PreTranslateMessage.

    • Edited by RLWA32 Sunday, September 20, 2015 3:06 AM
    Sunday, September 20, 2015 2:58 AM
  • I posted a VS2015 Solution at http://1drv.ms/1gHUyhm

    The solution contains two projects.  One is an MFC regular DLL that exports a function which will create a frame window.  The other is a simple console app that loads the DLL and calls the exported fuction,  I used a console app because it doesn't have a message pump but the DLL creates a UI thread of its own to pump messages to the frame window.

    As usual, it's only proof of concept coding and error checking is almost completely omitted.


    • Proposed as answer by RLWA32 Thursday, September 24, 2015 4:15 PM
    Monday, September 21, 2015 11:10 PM
  • I'm continuing with Win32 because I couldn't delay development any longer.

    First I'll try the sample you posted and if it's applicable to my project, I'll switch my Win32 DLL to MFC DLL.

    Thanks,

    Thursday, September 24, 2015 4:11 PM
  • Even if you switch to a Win32 DLL you will still need a message pump for any ordinary (non-dialog) window that gets created.  I assume that all of this is related to your TWAIN driver project.  Will the caller into your DLL provide the message pump?
    Thursday, September 24, 2015 4:18 PM
  • My Win32 DLL has my own message pump.

    After do some initial TWAIN process, this TWAIN driver create thread which has a message pump and have a WndProc which process all messages.

    I succeeded for application to call my TWAIN driver and display TWAIN driver window, and read some image file and return image to the calling application.

    I will add hardware interface logic instead of reading image file and finish first prototype.

    After that I want to convert it to MFC based DLL but still I don't know the equivalent of Win32's CreateThread on MFC to create message pump.

    Saturday, September 26, 2015 7:40 PM
  • The answer is in the solution that I posted at http://1drv.ms/1gHUyhm

    The exported function uses MFC to spin up a UI thread that has it's own message pump for the frame window that gets created.

    If you already have a message pump running then you need to structure the MFC DLL and it's exported functions to conform to the guidance I previously posted, repeated here:

    "Regular DLLs must have a CWinApp-derived class and a single object of that application class, as does an MFC application. However, the CWinApp object of the DLL does not have a main message pump, as does the CWinApp object of an application.

    Note that the CWinApp::Run mechanism does not apply to a DLL, because the application owns the main message pump. If your DLL brings up modeless dialogs or has a main frame window of its own, your application's main message pump must call a DLL-exported routine that calls CWinApp::PreTranslateMessage."

    • Edited by RLWA32 Saturday, September 26, 2015 7:53 PM
    • Marked as answer by Jeff0803 Saturday, September 26, 2015 11:10 PM
    Saturday, September 26, 2015 7:45 PM
  • Your solution might be what I am looking for but the link "http://1drv.ms/1gHUyhm" is not working for me. Can you repost it?

    Thank you!

    Thursday, May 26, 2016 7:15 PM
  • Your solution might be what I am looking for but the link "http://1drv.ms/1gHUyhm" is not working for me. Can you repost it?

    Thank you!

    Instead of appending to a closed thread from 8 months ago I suggest you start a new thread with whatever your question might be.
    Thursday, May 26, 2016 7:37 PM
  • The link no longer works.  Can you please post the code in the post or put it somewhere where it'll not get wiped?

    Thanks,

    A


    I don't mind someone marking a post as "Proposed as answer", but DO NOT mark it as "Answered". If I am the OP, I will decide if a post actually answers my post or not. Thank you.

    Thursday, September 19, 2019 8:29 PM
  • Sorry, but that example code was deleted some time ago.
    Thursday, September 19, 2019 8:38 PM
  • That's unfortunate.  Best to have a copy (full or excerpt) of the referenced stuff in the thread and then have a reference link to keep dead links from making useful questions have useless answers.  This is a requirement on SO for just this reason.

    I don't mind someone marking a post as "Proposed as answer", but DO NOT mark it as "Answered". If I am the OP, I will decide if a post actually answers my post or not. Thank you.

    Thursday, October 17, 2019 5:48 PM