Click here to load reader
Jan 31, 2016
VSL Deep DiveJosh Heitzman - Senior Software Design Engineer
VSL isAcronym for Visual Studio LibraryModern C++ library targeting the Visual Studio Platform.Styled after ATL and WTL.Comprised only of header files. No binaries.Extensible and customizable (macros can be overriden to change core behavior).Not a framework like MFC, MPF, .Net Framework, etc..Not a complete offering for the entire VS Platform
VSL Effect
Resources\VisualStudioIntegration\Common\Source\CPP\VSLVSLArchitecture.htm class diagramsInclude VSL header filesMockInterfaces Windows and Visual Studio Platform Interface mocksUnitTest\VSLUnitTest.sln solution with all of the VSL unit tests.
Questions/Issues:http://forums.microsoft.com/msdn/showforum.aspx?forumid=57&siteid=1Prefix post title with VSL
Feedback/Suggestions:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=123359&SiteID=1
Blog:http://blogs.msdn.com/josh_heitzman/
VSL Design PrinciplesMinimize couplingAvoid feature creepExploit the C++ language and the Microsoft Visual C++ compilerFacilitate unit testingRe-use without obstructionResponsive to requests
Minimize couplingNarrowly scoping the functionality of classes:Implement one interfaceWrap one VS ServiceWrap one related set of Win32 APIs
Use of C++ templates to reduce hard dependencies between classes.templateclass IVsWindowPaneImpl : public IVsWindowPane
template class IExtensibleObjectImpl : public IExtensibleObject
Avoid feature creepOnly the functionality required for the task at hand is implemented.
Avoid investing resources in features that may not be needed.class VsOutputWindowUtilities{ void OutputMessage( const wchar_t* const szMessage); void OutputMessageWithPreAndPostBarsOfEquals( const wchar_t* const szMessage);};
Exploit the C++ language and the Visual C++ compilerWhen possible, fail at compile time rather then runtimeMake use of C++ exceptionsUse C++ templates and when necessary C pre-processor macros to minimize code redundancy and maximize reuseUse of an extended version of the Resource Allocation Is Initialization paradigmtemplate class StaticArray{ C_ASSERT( NumberOfElements_T > 0);__if_exists(Derived_T::GetViewObject){__if_exists(Derived_T:: GetLocalRegistryCLSIDViewObject) { // Can't speceify both an object and // a clsid C_ASSERT(0); } pViewObject = rDerived.GetViewObject();}
Resource Allocation Is Initialization (RAII)RAII is used with all resources to ensure their lifetime is properly managed in the face of exceptions.template class Resource{ ResourceType m_Resource; Resource(): m_Resource(Values::GetNullValue()) {} Resource(ResourceType resource): m_Resource(resource) {} ~Resource() { Free(); } void Free(); ResourceType Detach(); operator CastType() const;};
eXtendened Resource Allocation Is Initialization (XRAII)RAII is extended to any set of calls that need balancing.class Suspend{ Suspend(This& rThis): m_rThis(rThis) { m_rThis.SendMessage(WM_SETREDRAW, FALSE, 0); m_dwMaskToRestore = static_cast(m_rThis.SendMessage( EM_SETEVENTMASK, 0, ENM_NONE)); } ~SuspendDrawAndNotifications() { m_rThis.SendMessage( EM_SETEVENTMASK, 0, m_dwMaskToRestore); m_rThis.SendMessage(WM_SETREDRAW, TRUE, 0); } This& m_rThis; DWORD m_dwMaskToRestore;};
Facilitate unit testingMocks for nearly all VS Platform interfacesMocks for many Windows Platform interfacesWrapper classes around some sets of Win32 APIsMocks for those classesCursorCursorMockFileFileMockKeyboardKeyboardMockWindowWindowMock
Re-use without obstructionMany classes take template parametersAllows you to provide your own custom implementation for a dependencySome template defaults will be correct for 99% of cases
A couple of classes using policy based designa smart pointer and a smart resource
Optional statically bound call backs into a derived classThis is accomplished via __if_exists and __if_notexists
Numerous macros that can be overridden
Responsive to requestsVS SDK release cycle is shortCTP monthlyRTW every 4 months
Designs are never perfect the first timeEven more so when on short cycle
Breaking changes will be made as the demand arisesShort cycle means there wont be a lot of BCs with any given release
VSL provides help withError and exception handlingUnit testingFunctors and delegatesComparing various thingsManaging resourcesThe basics necessary to create a VS PackageCommand handlingVS Service consumptionCreating a VS Window that hosts a dialog or Win32 controlCreating a VS Document / VS EditorAutomation and VS Macro recordingVS Hierarchies
Error and exception handlingError handling macros that convert errors to exceptions
Exception handling macros that catch and convert exceptions to HRESULTs
VSL_BEGIN_MSG_MAP message map that catches exceptions
Header files:VSLErrorHandlers.hVSLExceptionHandlers.hVSL_STDMETHODTRY{
VSL_CHECKHANDLE_GLE(::GetDC(hWnd));
}VSL_STDMETHODCATCH()
return VSL_GET_STDMETHOD_HRESULT();
Unit testingUnit testing frameworkMocks for nearly all VS Platform interfacesMocks for many Windows Platform interfacesMocks for wrapper classes around some sets of Win32 APIsIncluding some of ATL::CWindow
Header files:VSLUnitTest.hclass UnitTest : public UnitTestBase{ UnitTest( const char* const szTestName): UnitTestBase(szTestName) { UTCHK(false); }};
int _cdecl _tmain(int, _TCHAR*){ UTRUN(UnitTest); return VSL::FailureCounter::Get();}
Functors and delegatesClasses:FunctorFunctionPointerFunctorMemberFunctionPointerFunctorDelegate
Header Files:VSLCommon.hFunctionPointerFunctor functor(&OnEvent1);
Delegate event1;
event1 += functor;event1();event1 -= functor();
Comparing various thingsImplemented primarily for the interface mocksIsStringLessThen can be used with STL algorithms
Header files:VSLComparison.h
Managing resourcesPolicy based resource managers:PointerResource
Header files:VSLCommon.hVSLFont.htypedef Pointer CoTaskMemPointer;
CoTaskMemPointer pBuffer = ::CoTaskMemAlloc(iBufferByteSize);
CHKPTR(static_cast(pBuffer), E_OUTOFMEMORY);
CHK(0 == ::memcpy_s(pBuffer, iBufferByteSize, GetFileName(), iBufferByteSize), E_FAIL);
*ppszFilename = static_cast(pBuffer.Detach());
The basics necessary to create a VS PackageClasses:IVsPackageImplIVsInstalledProductImpl
Registry map macros
Header files:VSLPackage.hclass Package : public IVsPackageImpl< Package, &CLSID_Package>, public IVsInstalledProductImpl< IDS_PRODUCT_NAME, IDS_PRODUCT_IDENTIFIER, IDS_PRODUCT_DETAILS, IDI_ LOGO>{VSL_BEGIN_REGISTRY_MAP(IDR_PACKAGE_RGS)...VSL_END_REGISTRY_MAP()
VsSiteCacheCan be local or global
IVsPackageImpl uses the global VsSiteCache by defaultOnce a package is sited anything can then use the global cache by creating an instance of VsSiteCacheGlobal or utilizing the static methods of VsIServiceProviderUtilities directly or via the macros:VSQS - VsIServiceProviderUtilities::QueryServiceVSQCS - VsIServiceProviderUtilities::QueryCachedService
IVsPaneWindow uses the local VsSiteCache by defaultOnce window is sited can correctly get context sensitive services like SID_STrackSelection and SID_SVsWindowFrame
Command handlingClasses:IOleCommandTargetImplCommand map macrosVsFontCommandHandling
Header files:VSLCommandTarget.h
Samples:Menus and CommandsServicesTool WindowSingle View Editorclass MenuAndCommandsPackage : ... public IOleCommandTargetImpl< MenuAndCommandsPackage>,...VSL_BEGIN_COMMAND_MAP() VSL_COMMAND_MAP_ENTRY( GUID_MenuAndCommandsCmdSet, cmdidMyCommand, NULL, &MenuCommandCallback) VSL_COMMAND_MAP_ENTRY_WITH_FLAGS( GUID_MenuAndCommandsCmdSet, cmdidDynVisibility2, NULL, &MenuVisibilityCallback, OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_INVISIBLE)VSL_END_VSCOMMAND_MAP()...
VS Service consumptionWrapped VS Services:VsOutputWindowUtilitiesProfferServiceUtilitiesOleComponentUIManagerUtilities
Can use global or local VsSiteCache.OleComponentUIManagerUtilities::ShowMessage( L"Title", L"Message");Header files:VSLPackage.h
Samples:Menus and CommandServicesTool WindowSingle View Editor
Creating a VS Window that hosts a dialogClasses:IVsWindowPaneImplWindowVsWindowPaneFromResource
Header files:VSLWindows.hclass Form : public VsWindowPaneFromResource< Form, MAKEINTRESOURCE(IDD_DLG)>
Creating a VS Window that hosts a Win32 controlClasses:IVsWindowPaneImplWindowListViewWin32ControlRichEditWin32ControlWin32ControlContainer
Header files:VSLControls.hVSLWindows.hclass Document : public Win32ControlContainer< RichEditWin32Control >
class Report : public Win32ControlContainer< ListViewWin32Control< ReportViewTraits< false, false> > >
Fully integrating a VS WindowClassesVsWindowFrameEventSinkISelectionContainerImplISelectionContainerSingleItemImpl
Header filesVSLWindows.hclass WindowPane : public IVsWindowPaneImpl, public VsWindowFrameEventSink, public ISomeInterface, public ISelectionContainerSingleItemImpl< WindowPane, ISomeInterface>
Creating a VS Document / VS EditorClasses:IVsEditorFactoryImplIVsFindTargetImplSingleViewFindInFilesOutputWindowIntegrationImplFileDocumentPersistanceBase
Header Files:VSLFile.hVSLFindAndReplace.hVSLWindow.h
Samples:Single View Editor
Automation and VS Macro recordingClass