代码改变世界

Add custom view for expression

2006-10-19 22:21  atempcode  阅读(734)  评论(0编辑  收藏  举报

In VS2005, there are new features to display data in a specific format (read very visual) called Type Visualizer and Custom Viewer.

There are a lot of articals talking about the Type Visualizer like this, this and this. Since we are implementing a debug engine in our current project, I have a chance to implement the Custom View, approaching the same goal in a different way.

1. Implement the IDebugProperty3 for the property object. Especially the GetCustomViewerList and GetCustomViewerCount methods.

2. Regsiter the custom view using SetEEMetric.

3. Create a object implementing the IDebugCustomView interface. In the Display(...) method, you can do whatever you want to show the data to the users.

4. Set The flag DBG_ATTRIB_VALUE_CUSTOM_VIEWER in the dwAttrib field of the DEBUG_PROPERTY_INFO structure when IDebugProperty3::GetPropertyinfo called. This indicates the property has a custom view associated. Then VS will QueryInterface for the IDebugProperty3 interface.

The example MS gave demonstrate how VS get your custom view (not how you implement your cutom view):

 

IDebugCustomViewer *GetFirstCustomViewer(IDebugProperty2 *pProperty)
{
    // This string is typically defined globally.  For this example, it
    // is defined here.
    static const WCHAR strRegistrationRoot[] = L"Software\\Microsoft\\VisualStudio\\8.0Exp";
    IDebugCustomViewer *pViewer = NULL;
    if (pProperty != NULL) {
        CComQIPtr<IDebugProperty3> pProperty3(pProperty);
        if (pProperty3 != NULL) {
            HRESULT hr;
            ULONG viewerCount = 0;
            hr = pProperty3->GetCustomViewerCount(&viewerCount);
            if (viewerCount > 0) {
                ULONG viewersFetched = 0;
                DEBUG_CUSTOM_VIEWER viewerInfo = { 0 };
                hr = pProperty3->GetCustomViewerList(0,
                                                     1,
                                                     &viewerInfo,
                                                     &viewersFetched);
                if (viewersFetched == 1) {
                    CLSID clsidViewer = { 0 };
                    CComPtr<IDebugCustomViewer> spCustomViewer;
                    // Get the viewer's CLSID from the registry.
                    ::GetEEMetric(viewerInfo.guidLang,
                                  viewerInfo.guidVendor,
                                  viewerInfo.bstrMetric,
                                  &clsidViewer,
                                  strRegistrationRoot);
                    if (!IsEqualGUID(clsidViewer,GUID_NULL)) {
                        // Instantiate the custom viewer.
                        spCustomViewer.CoCreateInstance(clsidViewer);
                        if (spCustomViewer != NULL) {
                            pViewer = spCustomViewer.Detach();
                        }
                    }
                }
            }
        }
    }
    return(pViewer);
}

But an important point was missed: before QueryInterface for the IDebugProperty3 interface, VS will call GetPropertyinfo to see if the flag DBG_ATTRIB_VALUE_CUSTOM_VIEWER in the dwAttrib field is set. If not, it will just goes away. This costs me an afternoon to find out.