DLLScreenCap Sample: Demonstrates a Regular DLL That Statically or Dynamically Links to MFC
The DLLScreenCap sample illustrates a dynamic-link library (DLL) version of a screen capture tool. DLLScreenCap supercedes the DLLTRACE sample, which is obsolete. DLLTRACE was introduced in MFC version 1.0 to illustrate how to write a DLL that is itself statically linked to the MFC library. DLLScreenCap provides a C-based program interface to the Microsoft Windows–based application to which it is dynamically linked. A DLL that is statically linked to the MFC library cannot successfully export member functions of any classes that are derived from MFC classes.
The technique of statically linking a DLL to the MFC library is discussed in Technical Note 11: Using MFC as Part of a DLL. The DLLScreenCap sample can also be linked to MFC dynamically, without being an extension DLL. Before you decide to implement a custom DLL by statically linking to MFC, consider implementing it as an MFC extension DLL, as explained in Technical Note 33: DLL Version of MFC and as illustrated by the DLLHUSK sample.
A non-extension DLL that is linked to the MFC library needs to have a CWinApp-derived class and a single object of that application class, as does an executable MFC application. The CWinApp object of the DLL, however, does not have a main message pump, as does the CWinApp object of an application. If the DLL opens modeless dialog boxes or has a main frame window of its own, the application's main message pump must call a routine exported by the DLL, which in turn calls the CWinApp::PreTranslateMessage member function of the DLL's application object. This is illustrated by the FilterDllMsg function exported by DLLScreenCap.dll.
ScreenCapApi.h shows that a way to provide a DLL interface to client applications is to declare functions with extern "C". The use of extern "C" has several advantages. First, it makes your DLL usable by non-C++ client applications. Second, it reduces DLL overhead, because C++ name decoration will not be applied to the exported name. Third, it makes it easier to explicitly add to a .def file (for exporting by ordinal), without having to worry about C++ name decoration.
Security Note: |
---|
This sample code is provided to illustrate a concept and should not be used in applications or Web sites, as it may not illustrate the safest coding practices. Microsoft assumes no liability for incidental or consequential damages should the sample code be used for purposes other than as intended. |
To get samples and instructions for installing them:
On the Visual Studio Help menu, click Samples.
For more information, see Visual Studio Samples.
The most recent version and complete list of samples is available online from the Visual Studio 2008 Samples page.
You can also locate samples on your computer's hard disk. By default, samples and a Readme file are copied into a folder under \Program Files\Visual Studio 9.0\Samples\. For Express editions of Visual Studio, all samples are located online.
Building and Running the Sample
The DLLScreenCap sample consists of two projects: DLLScreenCap, a DLL project, and ScreenCap, an EXE project that calls into the DLL.
Building ScreenCap from the provided solution will automatically build DLLScreenCap and copy the DLL into ScreenCap's output directory.
Note Because this sample uses a custom build step to copy a file, you should not open the solution using a UNC path; put the sample files on a directory with a drive letter.
To build and run the DLLScreenCap sample
Open the solution DllScreenCap.sln.
In Solution Explorer, right-click the ScreenCap project folder and click Set as Startup Project on the shortcut menu.
On the Build menu, click Build.
On the Debug menu, click Start Without Debugging.
The ScreenCap window displays the last screen captured after being scaled to the window's size. Click Configure Screen Capture on the File menu. This opens a dialog box to specify whether to capture the screen or the active window as well as a path to where the captured file should be saved. Click Screen Capture to create a captured file and update the client window display.
Converting DLLScreenCap to Dynamically Link with the MFC DLL
DLLScreenCap demonstrates how to create a regular DLL with an exported function that can be called to display a modal dialog box. In older versions of Visual C++, this was the only option available for regular DLLs. These kinds of DLLs were formerly known as _USRDLLs.
Now, it is possible for a regular DLL to use MFC from the shared MFCx0 DLL. Because of the potential to reduce the size of the build, you might want to build the DLLScreenCap sample using the shared MFC DLL. Supporting the shared library in DLLScreenCap.dll will reduce the size of a release-build DLL from over 100K to about 16K and will reduce the size of the debug build from over 1 megabyte to 100K. To support linking dynamically in DLLScreenCap, use the macro AFX_MANAGE_STATE to switch the global MFC module state correctly.
To verify that DLLScreenCap can be used in a shared library
In Solution Explorer, right-click the ScreenCap project node and click Properties on the shortcut menu.
The Property Pages dialog box appears.
From the Configuration drop-down menu, select Multiple Configurations. See Setting Visual C++ Project Properties for more information about the Property Pages dialog box.
Select both the Release and Debugbuilds to change their settings.
In the General Property Page for the project, verify that the Use of MFC property to use MFC in a shared DLL property is checked.
Verify that the following line of code is in the beginning of every function exported from the DLL (see Managing the State Data of MFC Modules for a discussion):
AFX_MANAGE_STATE(AfxGetStaticModuleState())
For example, DllScreenCap.dll exports four functions:
CaptureScreen
ConfigureCapture
ProcessDLLIdle
FilterDLLMsg
FilterDLLMsg should look like this in the converted form:
BOOL WINAPI FilterDllMsg(LPMSG lpMsg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
TRY
{
return AfxGetApp()->PreTranslateMessage(lpMsg);
}
END_TRY
return FALSE;
}
Keywords
This sample demonstrates the following keywords:
CDialog::DoModal, CWinApp::InitInstance, CWinApp::OnIdle, CWinApp::PreTranslateMessage, CWnd::DoDataExchange, CWnd::GetClientRect, CWnd::OnPaint, ShowWindow, UpdateWindow, CImage, AFX_MANAGE_STATE, AfxGetStaticModuleState, CWnd::GetDesktopWindow, CWnd::GetActiveWindow, CImage::Create, CImageDC, CImage::Save, SHBrowseForFolder, CImage::Load, CDC::SetStretchBltMode, CImage::StretchBlt, CWnd::OnEraseBkgnd, CWindowDC