gpt4 book ai didi

winapi - 有没有办法创建一个优雅的类成员窗口函数?

转载 作者:行者123 更新时间:2023-12-05 01:34:27 26 4
gpt4 key购买 nike

Win32 API 中的 Window-Procedure 必须是 static\global 函数,因为它不能采用类对象( this )参数。人们当然可以使用解决方法,例如 hWnd->object 字典等。

不知道 D 有一种方法可以优雅地解决它,例如为每个对象创建一个小的成员函数副本(以调用对象的真实处理程序)或我可以分配给 WNDCLASS.lpfnWndProc 的匿名函数(我知道有匿名函数,但我不能对它们使用 extern(Windows) 属性)?

我可以做这样的事情吗:

class Window {
extern (Windows)
LRESULT delegate (HWND hWnd, UINT msg, WPARAM w, LPARAM l) MyWinProcDelegate;

this() {
MyWinProcDelegate = &Events;
}

extern (Windows)
LRESULT Events (HWND hWnd, UINT msg, WPARAM w, LPARAM l) {
MessageBoxA(null , "Success!!!" , null ,0);
return DefWindowProcA(hWnd, message, wParam, lParam);
}
}

(省略注册\创建\msg-loop...)

Events() 似乎没有触发……我错过了什么吗?

最佳答案

在这里,我为您制作了这个(基于 BCS 的回答):

version (Windows)
{
import std.c.windows.windows;

void makeExecutable(ubyte[] code)
{
DWORD old;
VirtualProtect(code.ptr, code.length, PAGE_EXECUTE_READWRITE, &old);
}
}
else
version (linux)
{
import core.sys.posix.sys.mman;
import core.sys.posix.unistd;

static if (!is(typeof(&mprotect)))
extern(C) int mprotect(void*, size_t, int);

void makeExecutable(ubyte[] code)
{
auto pageSize = sysconf(_SC_PAGE_SIZE);
auto address = ((cast(size_t)code.ptr) & ~(pageSize-1));
int pageCount =
(address/pageSize == (address+code.length)/pageSize) ? 1 : 2;
mprotect(cast(void*)address, pageSize * pageCount,
PROT_READ | PROT_WRITE | PROT_EXEC);
}
}
else
static assert(0, "TODO");

R function(A) delegate2function(R, A...)(R delegate(A) d)
{
enum size_t TEMPLATE1 = cast(size_t)0x01234567_01234567;
enum size_t TEMPLATE2 = cast(size_t)0x89ABCDEF_89ABCDEF;

static R functionTemplate(A args)
{
R delegate(A) d;
d.ptr = cast(typeof(d.ptr ))TEMPLATE1;
d.funcptr = cast(typeof(d.funcptr))TEMPLATE2;
return d(args);
}

static void functionTemplateEnd() {}

static void replaceWord(ubyte[] a, size_t from, size_t to)
{
foreach (i; 0..a.length - size_t.sizeof + 1)
{
auto p = cast(size_t*)(a.ptr + i);
if (*p == from)
{
*p = to;
return;
}
}
assert(0);
}

auto templateStart = cast(ubyte*)&functionTemplate;
auto templateEnd = cast(ubyte*)&functionTemplateEnd;
auto templateBytes = templateStart[0 .. templateEnd - templateStart];

// must allocate type with pointers, otherwise GC won't scan it
auto functionWords = new void*[(templateBytes.length / (void*).sizeof) + 3];
// store context in word-aligned boundary, so the GC can find it
functionWords[0] = d.ptr;
functionWords[1] = d.funcptr;
functionWords = functionWords[2..$];

auto functionBytes = (cast(ubyte[])functionWords)[0..templateBytes.length];
functionBytes[] = templateBytes[];

replaceWord(functionBytes, TEMPLATE1, cast(size_t)d.ptr );
replaceWord(functionBytes, TEMPLATE2, cast(size_t)d.funcptr);
makeExecutable(functionBytes);

return cast(typeof(return)) functionBytes.ptr;
}

void main()
{
import std.stdio;

auto context = 42;

void del(string s)
{
writeln(s);
writeln(context);
}

auto f = delegate2function(&del);
f("I am a pretty function");
}

在 Windows 32 位和 Linux 64 位上测试。

关于winapi - 有没有办法创建一个优雅的类成员窗口函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8645323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com