在 F# (PInvoke) 中扩展 Aero Glass

发布于 2024-10-12 19:57:59 字数 1779 浏览 3 评论 0原文

我正在开发 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);

来自 Form_Load 事件的 API 调用:

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

来自 Form_Load 事件的 API 调用:

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

我一直在搜索但我在 F# 中找不到任何有关使用 ref 参数的信息。我知道用 C# 编写会容易得多,但用 int F# 编写表单背后的代码会更容易,因为它是一种函数式编程语言,而且我正在编写的整个程序都是围绕函数进行的。我知道这纯粹是装饰性的,但请帮忙。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沐歌 2024-10-19 19:57:59

一般来说,extern(又名

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

这可以是使用方式如下:

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

请注意,定义 MARGINS 的方式与 C# 定义不太相似。各种 val 定义是不可变的,实际上是属性而不是字段(尽管它们由字段支持,所以这可能不是什么大问题)。如果您希望它们成为可变字段,则可以在每个字段的 val 之后添加 mutable 关键字:(

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

我还使用了 Struct attribute 而不是 struct ... end,但这只是为了简洁起见)。您可以像在 C# 中那样初始化它,或者使用 F# 的命名参数:

let mutable margin = MARGINS(cxRightWidth = 100)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文