Расширение Aero Glass в F # (PInvoke) - PullRequest
3 голосов
/ 19 января 2011

Я работаю над консольным приложением F #. В свойствах я установил тип вывода приложения Приложение Windows , чтобы скрыть консоль. Я также создал форму для запуска на своем месте. В настоящее время у меня есть только простая форма без элементов управления. Для создания формы я добавил ссылки на System.Windows.Forms и System.Drawing и открыл их вместе с System.Runtime.InteropServices.

Часть, которую я не знаю, как сделать это расширение аэростекла. Есть множество примеров того, как это сделать в C #. Например, вот вызов API и структура MARGINS:

[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);

Вызов API из события Form_Load:

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

Это то, что у меня так далеко в F #:

Вызов API и структура MARGINS:

[<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*))

Вызов API из события Form_Load:

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*))

Я искал вокруг, но не могу найти ничего об использовании ref параметров, подобных этому в F #. Я знаю, что было бы намного проще писать на C #, но код, стоящий за формой, будет проще писать в int F #, потому что это функциональный язык программирования, и вся программа, которую я пишу, ориентирована на функции. Я знаю, что это чисто декоративно, но, пожалуйста, помогите.

1 Ответ

5 голосов
/ 19 января 2011

Обычно определения extern (AKA P / Invoke или вызов платформы) в F # используют синтаксис, подобный C (и обратите внимание, что это extern, а не extend):

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

Это может затем использоваться следующим образом:

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

Обратите внимание, что способ, которым вы определили MARGINS, не совсем аналогичен определению C #. Различные определения val не являются изменяемыми и на самом деле являются свойствами, а не полями (хотя они поддерживаются полями, так что это, вероятно, не имеет большого значения). Если вы хотите, чтобы они были изменяемыми полями, вы можете добавить ключевое слово mutable после val для каждого поля:

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

(я также использовал атрибут Struct вместо struct ... end, но это только для краткости). Вы можете инициализировать это так же, как в C # или используя именованные аргументы F #:

let mutable margin = MARGINS(cxRightWidth = 100)
...