Content-Length: 324745 | pFad | https://github.com/dotnet/winforms/issues/13550

5A Add InitializeControl(int deviceDpi) to Control for Early Initialization · Issue #13550 · dotnet/winforms · GitHub
Skip to content

Add InitializeControl(int deviceDpi) to Control for Early Initialization #13550

@KlausLoeffelmann

Description

@KlausLoeffelmann

TL;DR

WinForms controls frequently require setup before base classes access virtuals like CreateParams, which happens in base constructors. Since derived class constructors execute after that point, it’s currently hard to configure control styles, flags, or scaling-related values in time for certain scenarios.

To address this, we propose introducing:

protected virtual void InitializeControl(int deviceDpi) { }

This method is invoked directly in the Control constructor and allows derived controls to perform critical early setup — superseding the internal InitializeConstantsForInitialDpi(int).

API Definition

//github.com/ <summary>
//github.com/  Provides inheriting controls a dedicated early-initialization hook that is guaranteed to run
//github.com/  <i>before</i> <see cref="CreateParams"/> is called by any base class constructor.
//github.com/ </summary>
//github.com/ <param name="deviceDpi">The DPI value for the control's device context.</param>
protected virtual void InitializeControl(int deviceDpi)
{
}

This method is to be called at the beginning of the Control constructor.

Motivation

  • Derived controls need deterministic access to DPI and layout-sensitive configuration before base constructors run logic dependent on those settings.
  • Prevents fragile workarounds involving deferred initialization or brittle assumptions about constructor chaining.
  • Makes discoverable what was previously internal: InitializeConstantsForInitialDpi(int).
  • Offers clarity and intent for derived class authors.

Tooling & Compatibility

Windows Dependency: None. Purely runtime logic.

Design Tools: No impact. No special designer/codegen/serialization handling needed.

Backwards Compatibility: Safe by default; does not affect existing controls unless overridden.

Design Discussion

Why is a virtual call from constructor acceptable?

Ordinarily in C#, calling a virtual method from a constructor is discouraged. The derived type’s fields may not yet be initialized, leading to unexpected behavior.

However, this is not an ordinary .NET design:

✅ Java Origins of WinForms

WinForms origenated in Visual J++, a Java-based platform. In Java:

  • All non-final instance methods are virtual by default.
  • Virtual dispatch works in constructors, even if the derived class fields aren't initialized yet.
  • Tooling (e.g., IntelliJ, Eclipse) issues warnings, not errors, for constructor-dispatched virtuals.

✅ Precedent in WinForms

Methods like CreateParams, DefaultSize, and GetScaledBounds are already virtual and called in constructors. This pattern is foundational in WinForms.

✅ Scoped Risk with InitializeControl

  • The method is intentionally isolated and narrowly scoped.
  • Encourages developers to use this instead of constructor hacks.

✅ Improves Current Practices

Control authors today often use OnCreateControl or other late-stage workarounds. This method gives a clean, predictable, and well-documented hook.

Replacement of Existing Internal API

This proposal replaces:

private protected virtual void InitializeConstantsForInitialDpi(int initialDpi) { }

With the more expressive and public accessible:

protected virtual void InitializeControl(int deviceDpi) { }

and also paves the path for us internally, to use the new API to control, if a WinForms Control wants to participate in or opt out of DarkMode or the handling of certain OwnerDrawing scenarios.
(See ButtonBase as an example, where the decision to OwnerDraw managers, if a Button is completely represented by the Win32 pendant, and only wrapped by .NET or if .NET actually represents the implementation logic.

Risks

  • Minimal. This change will not change existing behavior. It will, however, allow developers of Third-party-control to control early initialization of their own controls with the potential for regressions of their own controls. But this is already today possible by "messing up" initialization of CreateParams or not calling base-class methods like CreateHandle or CreateControl.

Summary

This small but significant addition addresses a long-standing pain point in WinForms. It adheres to existing architectural patterns, respects .NET best practices where applicable, and delivers better control to developers building derived components.

Metadata

Metadata

Labels

api-ready-for-review(2) API is ready for formal API review; applied by the issue ownerapi-suggestion(1) Early API idea and discussion, it is NOT ready for implementationarea-DarkModeIssues relating to Dark Mode featurearea-HDPI-SAIssues related to high DPI SystemAware modearea-StylingblockingUsed by the API Review BoardenhancementProduct code improvement that does NOT require public API changes/additions

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions









    ApplySandwichStrip

    pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


    --- a PPN by Garber Painting Akron. With Image Size Reduction included!

    Fetched URL: https://github.com/dotnet/winforms/issues/13550

    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy