10

I'm using the following code for my:

protected override void OnSourceInitialized(EventArgs e)
{
...
....
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
...
...
}

In some systems the "source" value comes out to be null and i cant find the reason why...

AsitK
  • 651
  • 1
  • 4
  • 14

3 Answers3

11

I think you may have to wait until the UI is rendered until you try to assign the Hwnd. Try putting it in the event handler for Window.Loaded instead.

This happened to me before, I had the Hwnd assignment after InitializeComponent() was called in the code-behind's constructor. It always came back null, which may sense when I stepped through and saw the UI hadn't appeared yet. I popped it into the _Loaded handler and voila, the UI renders before hitting that line and all of the sudden 'this' stopped being null.

WumpasTamer
  • 126
  • 2
  • 4
  • I have it so, in the `UserControl_Loaded` , and it works fine, but in some strange scenarios (app running on a remote desktop system, and you leave it running for hours without touching it), it returns null. – Zoli Mar 14 '23 at 08:35
8

Starting with .Net 4.0, you can access HwndSource without having to show the window first:

var helper = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
Jan Gassen
  • 3,406
  • 2
  • 26
  • 44
  • I still get null from `PresentationSource.FromVisual` after calling `WindowInteropHelper.EnsureHandle`. It looks like I actually have to show the window. `FromVisual` must require other internal things that are lazily created, beyond the handle. – Drew Noakes Jan 07 '18 at 13:19
  • Why don’t you use `HwndSource.FromHwnd` instead? – Jan Gassen Jan 07 '18 at 20:52
  • 1
    Because I need the presentation source to access the composition target to access the matrix to access the DPI values. – Drew Noakes Jan 08 '18 at 08:46
  • 1
    Could you maybe use `new HwndTarget(helper.EnsureHandle())` to access the composition target and continue from there? – Jan Gassen Jan 08 '18 at 13:03
  • Interesting idea. I've implemented a workaround and moved on, but I bump up against this from time to time so will try it out next time. Thanks very much. – Drew Noakes Jan 08 '18 at 19:44
5

WumpasTamer's answer is correct. I'd just like to add a quick code sample for anyone else looking for a "turnkey" solution. If you're using WPF already then window is not necessary, but if you're using Winforms and want to use PresentationSource you'll need to use this.

void Main()
{
    var window = new Window
    {
        Width = 0,
        Height = 0,
        WindowStyle = WindowStyle.None,
        ShowInTaskbar = false,
        ShowActivated = false
    };
    window.Loaded += a_Loaded;
    window.Show();
}

void a_Loaded(object sender, EventArgs e)
{
    var s = (Window) sender;
    var source = PresentationSource.FromVisual(s);
    //...
    s.Close();
}
The Muffin Man
  • 19,585
  • 30
  • 119
  • 191