使用嵌套函数作为Windows API函数的回调吗?

时间:2018-10-01 20:31:11

标签: function winapi callback window d

我有以下代码,可以正常工作。

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void*[] hWndList;

extern (Windows) int callback(void* hWnd, long /* lParams */ ) nothrow {
    hWndList ~= hWnd;

    return true;
}

void main() {
    EnumWindows(&callback, 0);

    writeln(hWndList);
}

我希望可以使用类似于JavaScript语法的内容:(void* hWnd, long) => {}

我尝试了此操作,但签名出现错误,它表示该函数是委托,并且Windows API显然不能接受委托。

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void main() {
    void*[] hWndList;

    EnumWindows((void* hWnd, long /* lParams */ ) nothrow {
        hWndList ~= hWnd; return true;
    }, 0);

    writeln(hWndList);
}

我什至不会粘贴编译器错误,因为我非常清楚地以错误的方式进行处理。

当然,将每个回调定义为单独的函数没有错,但是随之而来的是命名它们的问题。我也不喜欢它使我的代码看起来像这样。

谢谢。

1 个答案:

答案 0 :(得分:1)

我发现我可以将委托(或lambda)转换为MSDN文档为EnumWindowsProc指定的正确签名。

我也没有意识到,通过从全局范围隐式使用hWndList来访问D程序的框架是一种非常糟糕的做法。

这就是我用来创建正确签名的方法。

alias EnumWindowsProc = extern (Windows) int function(HWND, LPARAM) nothrow;

然后我发现别名在{2}行的ENUMWINDOWSPROC的MinGW标头中已经以core.sys.windows.windows的形式存在(在撰写本文时)。

extern (Windows) nothrow {
    ...
    alias BOOL function(HWND, LPARAM) ENUMWINDOWSPROC;
    ...
}

为解决隐式传递D帧的问题,我在EnumWindows中将cast(LPARAM) &hWndList用作lParam

这成为现在使用指针的问题。我知道这可能很糟糕,欢迎提出任何建议,但我将其强制转换为指针。

*(cast(HWND[]*) lParam)

完整的代码如下所示。显然,这只是开始的一个最小示例,因此您可能需要将强制转换的指针分配给某些对象,这样在使用lParams中的变量时就不会造成混淆。

import core.sys.windows.windows: EnumWindows, ENUMWINDOWSPROC;
import std.stdio: writeln;

void main() {
    HWND[] hWndList;

    EnumWindows(cast(ENUMWINDOWSPROC) (HWND hWnd, LPARAM lParam) {
        *(cast(HWND[]*) lParam) ~= hWnd;
        return true;
    }, cast(LPARAM) &hWndList);

    writeln(hWndList);
}

我希望这对某人有帮助,因为这让我感到困惑(仍然不确定我是否了解指针逻辑)。

感谢D论坛上的Boris-Barboris给我一些帮助。

https://forum.dlang.org/post/xxklxaajptppockvazeo@forum.dlang.org