0

I am trying to change the rectangle in which windows are minimized with a shell hook to HSHELL_GETMINRECT in my C# WPF application.

Following this Win32 C API for redirecting minimize animation I was able to marshal the structure returned in the lParam parameter, but i can't change it's value so that windows gets the new rectangle.

This is my WndProc method so far.

public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // If windows sends the HSHELL_GETMINRECT event, a window in the taskbar is minimizing or maximizing.
    if (wParam.ToInt32() == WindowInterop.HSHELL_GETMINRECT)
    {
        var param = Marshal.PtrToStructure<WindowInterop.MinRectParam>(lParam);
        var icon = FindIcon(param.hWnd);
        var rect = new WindowInterop.SRect
        {
            Bottom = (short)(icon.Y + icon.Height),
            Left = (short)icon.X,
            Right = (short)(icon.X + icon.Width),
            Top = (short)icon.Y
        };
        var newParam = new WindowInterop.MinRectParam
        {
            hWnd = param.hWnd,
            Rect = rect
        };
        // As I understand it, this will only create a new IntPtr pointing to the structure,
        // it won't write the new structure to the existing pointer's location.
        Marshal.StructureToPtr(newParam, lParam, true);
        handled = true;
    }
    return IntPtr.Zero;
}
Community
  • 1
  • 1
Dominic Lacaille
  • 220
  • 1
  • 10
  • 1
    Actually, `Marshal.StructureToPtr` will copy to the location where the pointer points to, so it will not create a new pointer. You shouldn't pass true to this method. Try to change this to false. This is needed for sure but you might have more problems. – Yacoub Massad Oct 04 '15 at 19:25
  • Just tried it, it didn't work right away but when i also added ```return new IntPtr(1);``` it worked! Thank you. – Dominic Lacaille Oct 04 '15 at 19:45
  • @YacoubMassad I don't understand why it shouldn't be true... The struct that was fetched is a new instance, so if we marshal it back, shouldn't the old one (that lParam was pointing to) be destroyed to avoid memory leaks? Shouldn't it be false if the pointer was not pointing at any data, which is not the case here? – Shahin Dohan Jan 13 '22 at 16:06
  • 1
    @ShahinDohan, based on my understanding: (1) true makes sense only when the object we are marshalling contains certain kinds of reference types that we need the runtime to keep track of (see docs for StructureToPtr). In the case of the question, simple data is copied. (2) We cannot assume anything about the data object behind lParam. WndProc is invoked by the operating system. It could be giving us a different pointer each time. The structure we marshal into lParam should be a simple data object that requires no reference count maintenance by the runtime. – Yacoub Massad Jan 18 '22 at 09:12
  • @YacoubMassad So if the MinRectParam struct contained any reference types, then we should pass true? What happens if I pass true anyway, could that lead to potential bugs? – Shahin Dohan Jan 18 '22 at 13:09
  • 1
    @ShahinDohan, based on the docs, only certain reference types, not all. I don't know what happens if you pass true anyway. Does it act the same way as false because there are no reference types of the kinds the docs talk about? Because what is behind lParam is managed by the OS, I wouldn't pass true. – Yacoub Massad Jan 18 '22 at 17:03

1 Answers1

0

I needed to add return new IntPtr(1); for Windows to use the new structure.

Dominic Lacaille
  • 220
  • 1
  • 10