Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Aero Glass in F# (PInvoke)

I'm working on a F# console application. In the properties I set the output type of application to Windows Application to hide the console. I also created a form to run in its place. Currently I only have a simple form with no controls. To make the form I added referances to System.Windows.Forms and System.Drawing and opened them along with System.Runtime.InteropServices.

The part that I don't know how to do is extending the aero-glass. There are loads of exaples on how to do it in C#. For example, here is the API call and MARGINS structure:

[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
    public int cxLeftWidth;
    public int cxRightWidth;
    public int cyTopHeight;
    public int cyBottomHeight;
}
[DllImport("dwmapi.dll")]
pubic static extend int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);

The API call from Form_Load event:

MARGINS margins = new MARGINS();
margins.cxLeftWidth = 0;
margins.cxRightWidth = 100;
margins.cyTopHeight = 0;
margins.cyBottomHeight = 0;
int result = DwmExtendFrameIntoClientArea(this.Handle, ref margins);

This is what I've got so far in F#:

The API call and MARGINS structure:

[<StructLayout(LayoutKind.Sequential)>]
type MARGINS =
    struct
        val cxLeftWidth : int
        val cxRightWidth : int
        val cyTopHeight : int
        val cyBottomHeigh t: int
        new(left, right, top, bottom) = { cxLeftWidth = left; cxRightWidth = right; cyTopHeight = top; cyBottomHeigh = bottom } (*Is there any other way to do this?*)
    end
[<DllImport("dwmapi.dll")>]
extend int DwmExtendFrameIntoClientArea(IntPtr hWnd, (*I need help here*))

The API call from Form_Load event:

let margins = new MARGINS(0, 100, 0, 0); (*Is there any other way to do this?*)
let result : int = DwmExtendFrameIntoClientArea(this.Handle, (*I need help here*))

I have been searching around but I can't find anything about using ref parameters like this in F#. I know this would be a lot easier to write in C# but the code behind the form will be easier to write int F# because it's a functional programing language and the whole program I'm writing is orientated around functions. I know this is purely decorative but please help.

like image 681
Metod Medja Avatar asked Jan 28 '26 04:01

Metod Medja


1 Answers

In general, extern (AKA P/Invoke or platform invoke) definitions in F# use C-like syntax (and note that it's extern, not extend):

[<DllImport("dwmapi.dll")>]
extern int DwmExtendFrameIntoClientArea(nativeint hWnd, MARGINS& pMarInset)

This can then be used as follows:

let mutable margin = ...
let result = DwmExtendFrameIntoClientArea(this.Handle, &margin)

Note that the way that you have defined MARGINS is not quite analogous to the C# definition. The various val definitions are not mutable, and are actually properties rather than fields (though they're backed by fields, so it's probably not a big deal). If you want them to be mutable fields, you can add the mutable keyword after val for each field:

[<Struct; StructLayout(LayoutKind.Sequential)>]
type MARGINS =  
  val mutable cxLeftWidth : int        
  val mutable cxRightWidth : int        
  val mutable cyTopHeight : int        
  val mutable cyBottomHeight: int

(I've also used the Struct attribute instead of struct ... end, but that's just for brevity). You can initialize this like you do in C#, or using F#'s named arguments:

let mutable margin = MARGINS(cxRightWidth = 100)
like image 128
kvb Avatar answered Jan 30 '26 19:01

kvb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!