You’ve clicked inside that left-hand panel in SolidWorks thousands of times. Every time you create an extrude, add a fillet, define a mate, or configure a sheet metal feature, the Property Manager Page slides in from the left with its groups, checkboxes, selection boxes, and blue highlight fields. It looks like a standard Windows control panel. But it isn’t.

If you’ve ever tried to build your own PMP through the SolidWorks API, you’ve noticed something strange: you don’t create Windows controls. You call AddControl with a type enum and get back a COM interface. You can’t set a font. You can’t subclass the window. You can’t attach a debugger to the control’s HWND the way you would with a normal Windows button. The PMP controls don’t behave like anything else on Windows.

We decompiled the SolidWorks interop DLLs, inspected exported symbols from native C++ libraries, and examined the internal class hierarchy to understand what Property Manager Pages are actually made of — the same approach we used when investigating how SolidWorks drawing files store geometry and what happens behind the scenes when you export a DXF. Here’s what we found.

The API Surface: What You See

When you build a Property Manager Page through the SolidWorks API, you interact with a layered set of COM interfaces. The entry point is ISldWorks::CreatePropertyManagerPage, which takes a title string, option flags, and a handler object:

PropertyManagerPage2 page = swApp.ICreatePropertyManagerPage(
    "My Feature",
    (int)swPropertyManagerPageOptions_e.swPropertyManagerOptions_OkayButton,
    handler,
    out int errors
);

The handler must implement IPropertyManagerPage2Handler9 — the latest version, which defines 37 callback methods covering everything from checkbox clicks to keystroke interception to 3D selection validation. The handler versions evolved over SolidWorks releases, each adding new callbacks on top of the previous:

Handler VersionAdded Callbacks
Handler (v1)OnClose, AfterClose, OnHelp, basic control events
Handler2OnComboboxEditChanged
Handler3AfterActivation, OnSubmitSelection, OnActiveXControlCreated
Handler4OnPreviousPage, OnNextPage, OnPreview, OnUndo, OnRedo, OnTabClicked
Handler5OnSliderPositionChanged, OnSliderTrackingCompleted
Handler6OnKeystroke(Wparam, Message, Lparam, Id), popup menu events
Handler7OnSelectionboxCalloutCreated, OnSelectionboxCalloutDestroyed
Handler8OnGainedFocus, OnLostFocus
Handler9 (current)OnWindowFromHandleControlCreated, OnListboxRMBUp, OnNumberBoxTrackingCompleted

Controls are added to the page through IPropertyManagerPage2::AddControl, which takes an integer ID, a control type from swPropertyManagerPageControlType_e, and option flags. The API provides 15 built-in control types:

Control TypeInterfaceWhat It Does
TextboxIPropertyManagerPageTextboxSingle or multi-line text input
CheckboxIPropertyManagerPageCheckboxBoolean toggle (supports indeterminate state)
NumberboxIPropertyManagerPageNumberboxNumeric input with unit awareness and slider support
ComboboxIPropertyManagerPageComboboxDropdown selection with optional edit field
ListboxIPropertyManagerPageListboxMulti-item selection list
SelectionboxIPropertyManagerPageSelectionboxThe blue highlight fields for picking geometry in the 3D viewport
OptionIPropertyManagerPageOptionRadio button
ButtonIPropertyManagerPageButtonPush button
LabelIPropertyManagerPageLabelRich text with per-character formatting
BitmapIPropertyManagerPageBitmapStatic image
BitmapButtonIPropertyManagerPageBitmapButtonImage toggle button
SliderIPropertyManagerPageSliderRange slider control
TabIPropertyManagerPageTabMulti-page tab container
ActiveXIPropertyManagerPageActiveXEmbedded COM/ActiveX control
WindowFromHandleIPropertyManagerPageWindowFromHandleEmbedded HWND — any window you create

The last two are the escape hatches. IPropertyManagerPageActiveX lets you embed any ActiveX control by CLSID. IPropertyManagerPageWindowFromHandle goes further — you create your own Win32 window (WPF, WinForms, anything) and pass the HWND to SolidWorks, which hosts it inside the PMP. Both have 32-bit and 64-bit handle variants.

All controls inherit from IPropertyManagerPageControl, which provides common properties: Visible, Enabled, Tip, Left, Width, Top, TextColor, BackgroundColor. Controls are organized into collapsible IPropertyManagerPageGroup sections and optional IPropertyManagerPageTab containers.

This is what the API shows you. What it doesn’t show is how these controls are actually rendered.

What’s Actually Inside: The DVE System

The PMP system is internally called DVE — Dialog View Editor. We found the evidence in slduiu.dll, a native C++ library with 19,749 exported symbols that contains the core UI infrastructure.

The class hierarchy reveals that PMPs are built on MFC’s CPropertyPage — Microsoft Foundation Classes, the C++ framework that dominated Windows development in the 1990s:

CPropertyPage (MFC)
  └─ uiDveDialogTemplate_c
       └─ uiDveDialog_c
            └─ uiDvePage_c
                 └─ uiDynamicDvePage_c

The constructors tell the story. uiDvePage_c takes a DLGTEMPLATE* as its first argument — a Win32 dialog template structure. This is how Windows has created dialog boxes since the early 1990s. The DLGTEMPLATE defines the layout, and MFC’s CPropertyPage wraps it in a property sheet tab.

// From exported symbol signatures in slduiu.dll
uiDvePage_c(DLGTEMPLATE*, uiModelDoc_c*, uoSelRequest_c*, blockType_e, ...)
uiDynamicDvePage_c(DLGTEMPLATE*, uiModelDoc_c*, ...)

The controls you interact with through the API are not standard Windows common controls. They’re custom MFC classes that SolidWorks draws itself:

  • uiDveButton_c — the PMP button control
  • uiDveCheckBox_c — the PMP checkbox
  • uiDveRadioButton_c — radio buttons
  • uiDveStaticCtrl_c — labels and static text
  • uiDveFeaturePage_c — feature-specific PMP pages
  • uiDveMessageDlg_c / uiDveSketchMessageDlg_c — the yellow message panel at the top

For numeric input, SolidWorks uses custom controls from SLDMFCU.dll (the SolidWorks MFC utility layer, 9,178 exports):

  • CNumericControl / CNumericControlCallBack — the unit-aware numeric input
  • CEquationControl / CEquationNumericControl — equation-capable number fields
  • CCheckBoxBitmapCombo — the combined checkbox/bitmap/combo control

The dynamic DVE system adds typed property controls:

  • uiDynamicDvePropertyBoolean_c
  • uiDynamicDvePropertyColor_c
  • uiDynamicDvePropertyDouble_c
  • uiDynamicDvePropertyEnum_c
  • uiDynamicDvePropertyFilePath_c
  • uiDynamicDvePropertyInteger_c
  • uiDynamicDvePropertyString_c
  • uiDynamicDvePropertyDivider_c

These map to the dynamic controls that the API exposes. When you call AddControl(id, swControlType_Numberbox, ...), SolidWorks creates a uiDynamicDvePropertyDouble_c internally, wraps it in the DVE container, and hands you back a COM interface.

The Docking Framework: Codejock ToolkitPro

The PMP panel doesn’t dock itself. We found that DockingPaneHelperU.dll depends on ToolkitProVC141x64U.dll — Codejock Software’s Xtreme ToolkitPro, a commercial MFC extension library. SolidWorks uses it for:

  • CXTPDockingPane — the docking pane framework (how PMPs attach to the left side)
  • CXTPCommandBar — the command/toolbar system
  • CXTPTaskPanel — task panel framework

SolidWorks wraps Codejock’s infrastructure with its own classes: CSWDockingPaneManager, CDockingPaneHelper, CDockerAppBridge, CDockerUIBridge. This is why the PMP docking behavior feels slightly different from Visual Studio’s docking — it’s a different library underneath.

The WPF Migration Nobody Talks About

Here’s the most surprising finding. SolidWorks is actively migrating Property Manager Pages to WPF.

We found these DLLs in the SolidWorks installation directory:

DLLPurpose
propertiesManagerWPF.dllWPF PropertyManager implementation (.NET assembly)
WPFSupport.dllC++/CLI bridge between native MFC and managed WPF
WPFRes.dllWPF resources and styles
AnnotationWPF.dllAnnotation feature PMPs in WPF
FeatureWPF.dllGeneral feature PMPs in WPF
SketchWPF.dllSketch feature PMPs in WPF
SheetMetalWPF.dllSheet metal feature PMPs in WPF
EnvironmentWPF.dllEnvironment settings PMPs in WPF
RefPlaneWPF.dllReference plane PMPs in WPF

WPFSupport.dll is the critical piece — it’s a mixed-mode C++/CLI assembly with both a native entry point and CLR metadata. It links to both mfc140u.dll and mscoree.dll (the .NET CLR host). Inside, we found WPFDve_c, the managed wrapper class that bridges the native uiDvePage_c MFC page to a managed DVEPage_c WPF page.

The bridge mechanism works through System.Windows.Interop.HwndSource:

  1. DVEPage_c extends System.Windows.Controls.Page (a standard WPF Page)
  2. It has a set_ParentHwnd(IntPtr) method that creates a new HwndSource
  3. The HwndSource creates a Win32 HWND from the WPF visual tree
  4. That HWND gets parented into the native MFC DVE container

The native uiDvePage_c base class has a virtual method isWPFPage() that returns a boolean. This is the runtime switch — when SolidWorks creates a PMP page, it checks whether to instantiate an MFC-based DVE page or a WPF-based one. Both render inside the same docking container.

The WPF side has its own control vocabulary in propertiesManagerWPF.dll:

PMCheckBox, PMComboBox, PMNumeric3DCC, PMLabel3DCC, PMCheckBox3DCC, PMComboBox3DCC, PMActionButton, PMIconicActionButton, PMStyleActionButton, PMStyleToggleButton, PMIconicRadioButton, PMExpander, PMMessageExpander, PMColumn, PMControlRow, PMHeaderRow, PMIcon, PMIconLabel, PMFilter, PMDocument, PMRulesSet, PMActiveState, PMDefault, PMCase, PMCaseOperand

These are WPF-native controls that replace the MFC uiDve* controls for migrated pages. The “3DCC” suffix likely stands for “3D Context Controls” — controls that interact with the 3D viewport.

A .NET assembly called Controls.dll provides a binding/dependency system (BoolBinding, ComboBoxBinding, ColorBinding) that likely drives the data-binding for WPF PMP controls — the same MVVM pattern that WPF was designed for.

Why Not WinForms? Why Not WPF From the Start?

SolidWorks was founded in 1993. The first version shipped in November 1995. At that time, there was no .NET Framework (released 2002), no WinForms, no WPF (released 2006). MFC was the standard way to build Windows applications in C++, and SolidWorks’ founding vision was to build exclusively for Windows, leveraging standard Windows capabilities.

By the time WinForms arrived in 2002, SolidWorks had millions of lines of MFC code and a COM-based API that third-party developers had built against. The SolidWorks API uses Single-Threaded Apartment (STA) COM — all objects live in an STA, meaning only the creating thread can access them. This provides automatic synchronization without requiring components to manage thread safety, but it’s also why SolidWorks is fundamentally single-threaded for modeling operations.

WinForms was skipped entirely — it’s essentially a managed wrapper around Win32 controls, offering nothing that MFC didn’t already provide. The overhead of the .NET runtime for UI that was already working in native C++ made no sense.

WPF was more interesting but came with serious technical problems for CAD:

  1. GPU texture churn. WPF creates a new GPU texture every frame and destroys it afterward — one of the slowest GPU operations. CAD viewports need persistent GPU resources for real-time rotation of complex assemblies.

  2. CPU-based tessellation. WPF tessellates vector graphics on the CPU before sending them to the GPU. For complex engineering drawings with thousands of entities, this creates bottlenecks.

  3. Multiple draw calls for simple shapes. A single stroked ellipse in WPF generates three separate draw calls. Multiply that by the thousands of geometric primitives in a CAD viewport.

  4. Vertex buffer locking. WPF locks vertex buffers in a way that causes CPU-GPU synchronization stalls — the GPU waits for the CPU, or vice versa. CAD needs both running in parallel.

  5. Threading model mismatch. WPF’s Dispatcher model dispatches work to the UI thread asynchronously. SolidWorks’ STA COM model requires that the same thread that created an object executes its methods. These two models fight each other.

None of this means WPF is bad — it’s excellent for business applications, dashboards, and data-heavy UIs. But for a CAD application that needs to render 100,000 tessellated faces at 60fps while the user drags a dimension, WPF’s rendering pipeline is the wrong tool.

What SolidWorks did instead was pragmatic: keep MFC for the 3D viewport and legacy UI, but gradually introduce WPF for the panel controls where its data-binding and styling capabilities outweigh the rendering overhead. The isWPFPage() toggle lets them migrate one PMP at a time without a rewrite.

How FreeCAD Does It Differently

FreeCAD solves the same problem — a side panel for feature parameters — using a completely different architecture. Where SolidWorks uses COM interfaces and MFC, FreeCAD uses Qt widgets inside a QDockWidget.

The framework is managed by ControlSingleton, a C++ singleton that enforces a one-dialog-per-document policy. When you double-click a feature, FreeCAD creates a TaskDialog subclass, populates it with TaskBox containers (collapsible sections, equivalent to SolidWorks groups), and slides it into the dock panel.

The key architectural differences:

Layout design: FreeCAD developers design PMP layouts visually in Qt Designer, producing .ui XML files. SolidWorks developers write API calls — AddGroupBox, AddControl, SetRange — in code. There’s no visual editor for SolidWorks PMPs.

Control ownership: In FreeCAD, you create actual Qt widgets (QComboBox, QSpinBox, QCheckBox) and hand them to the framework. In SolidWorks, you call AddControl and the framework creates the control and gives you a COM interface to it. You never touch the underlying window.

Selection integration: FreeCAD uses an Observer pattern — task panels inherit SelectionObserver and override onSelectionChanged(const SelectionChanges& msg) to receive push notifications. SolidWorks uses COM callbacks — your handler receives OnSelectionboxFocusChanged and OnSubmitSelection events. The FreeCAD approach lets the panel decide what to do with selection changes. The SolidWorks approach is more constrained but handles edge cases (like filtering by selection marks) automatically.

Extensibility: FreeCAD task panels are Python-scriptable through TaskDialogPython. SolidWorks exposes PMPs through COM, accessible from VBA, VSTA, and any .NET language. Both approaches work, but FreeCAD’s is far more transparent — you can read the source code for any built-in task panel.

The tradeoff is that FreeCAD’s Qt approach is cross-platform and fully open, while SolidWorks’ proprietary approach gives tighter integration with the rest of the application at the cost of being opaque to developers.

What This Means for Add-In Developers

If you’re building SolidWorks add-ins, understanding the PMP architecture explains some common frustrations:

Why you can’t style PMP controls. The built-in controls are custom MFC classes rendered by SolidWorks. The COM interface exposes TextColor and BackgroundColor, but that’s it. No fonts, no custom drawing, no templates. If you need custom UI, use IPropertyManagerPageWindowFromHandle to embed your own WPF or WinForms window.

Why the LockedPage option matters. The API docs warn that you must specify swPropertyManagerOptions_LockedPage when creating your PMP. Without it, if a handler callback triggers code that closes the PMP, SolidWorks can crash because the MFC dialog template gets destroyed while the callback is still on the stack. This is a classic MFC lifetime issue — the uiDvePage_c destructor runs while the handler is executing.

Why properties can only be set before Show(). The DVE system reads control properties from the DLGTEMPLATE and internal state during page creation. Once the page is displayed, the MFC dialog template is already instantiated. Changing properties after display would require recreating the native window, which the COM wrapper doesn’t support.

Why IPropertyManagerPage::GetDialogWindow returns an HWND. The original IPropertyManagerPage (v1) exposed GetDialogWindow and GetDialogWindowx64, which return the actual Win32 HWND of the dialog. This was removed from IPropertyManagerPage2, probably because exposing the raw HWND let developers make direct Win32 calls that could destabilize the DVE system. The WindowFromHandle control type is the sanctioned replacement.

The Handler9 Callback Reference

For developers implementing IPropertyManagerPage2Handler9, here’s the complete callback list with the Win32 message-level detail that the API docs don’t always make clear:

#CallbackWhen It Fires
1AfterActivation()Page finished opening and is fully visible
2OnClose(int Reason)Page closing — Reason is swPropertyManagerPageCloseReasons_e
3AfterClose()Page fully closed and destroyed
4OnHelp()Help button clicked — return true to suppress default help
5-6OnPreviousPage() / OnNextPage()Multi-page navigation — return true to cancel
7OnPreview()Preview toggled
8-9OnWhatsNew() / OnUndo() / OnRedo()Edit operations
10OnTabClicked(int Id)Tab selected — return true to cancel switch
11-12OnGroupExpand / OnGroupCheckGroup collapsed/expanded or checked
13-17Control value callbacksOnCheckboxCheck, OnOptionCheck, OnButtonPress, OnTextboxChanged, OnNumberboxChanged
18-20Combobox/ListboxOnComboboxEditChanged, OnComboboxSelectionChanged, OnListboxSelectionChanged
21-22Selection boxOnSelectionboxFocusChanged, OnSelectionboxListChanged
23-24CalloutOnSelectionboxCalloutCreated / Destroyed
25OnSubmitSelection(Id, Selection, SelType, ref ItemText)Validate a selection — return false to reject
26OnActiveXControlCreated(Id, Status)ActiveX control ready
27-28SliderOnSliderPositionChanged, OnSliderTrackingCompleted
29OnKeystroke(Wparam, Message, Lparam, Id)Raw Win32 keyboard message — return true to consume
30-31Popup menuOnPopupMenuItem, OnPopupMenuItemUpdate
32-33FocusOnGainedFocus, OnLostFocus
34OnWindowFromHandleControlCreated(Id, Status)HWND-hosted control ready
35OnListboxRMBUp(Id, PosX, PosY)Right-click in listbox
36OnNumberBoxTrackingCompleted(Id, Value)Numberbox slider drag finished

The OnKeystroke callback is revealing — it passes raw WM_KEYDOWN/WM_KEYUP parameters (Wparam, Message, Lparam), confirming that the control system sits directly on top of the Win32 message pump.

How CadShift Uses This Knowledge

CadShift automates SolidWorks workflows including batch DXF export and file conversions. Understanding the PMP architecture matters for our add-in development because it determines how we build our configuration interfaces.

For simple settings, we use the built-in PMP controls — they match SolidWorks’ visual language and handle keyboard navigation, DPI scaling, and theme changes automatically. For complex configuration (file mapping tables, preview panels, batch operation queues), we embed WPF controls via IPropertyManagerPageWindowFromHandle, giving us full MVVM data binding while staying inside the SolidWorks panel system.

The isWPFPage() discovery also tells us where SolidWorks is heading. As more built-in PMPs migrate to WPF, the visual language will evolve, and add-ins that embed WPF controls will blend in better over time.

Takeaways

  • Property Manager Pages are not standard Windows controls. They’re custom MFC classes (the “DVE” system) built on CPropertyPage and DLGTEMPLATE structures, with the controls owner-drawn by SolidWorks in slduiu.dll.

  • SolidWorks is migrating PMPs to WPF, one page at a time. WPFSupport.dll bridges MFC and WPF via HwndSource, and isWPFPage() on the native uiDvePage_c class is the runtime switch.

  • WinForms was never used internally. SolidWorks went from MFC directly to WPF for managed UI, bypassing WinForms entirely.

  • The docking framework is Codejock ToolkitPro, a commercial MFC extension library — not a SolidWorks-built system.

  • Two escape hatches exist for custom UI: IPropertyManagerPageActiveX (embed any COM control by CLSID) and IPropertyManagerPageWindowFromHandle (embed any HWND). If you need UI beyond the 15 built-in control types, these are your options.

  • The 37-callback handler interface (IPropertyManagerPage2Handler9) reveals the control system’s Win32 roots — raw Wparam/Lparam message parameters, HWND handles, and COM dispatch interfaces all the way down.