处理窗口消息 | 这两个 API 需遵守无声明调用原生 API 规则
//窗口程序 - 消息回调
//处理窗口消息: https://www.aardio.com/zh-cn/docs/library-guide/std/win/ui/msg.html
import win.ui;
import win.ui.atom;
/*DSG{{*/
var winform = win.form(text="aardio form";right=758;bottom=423)
winform.add(
btnMessageView={cls="button";text="打开 Windows 消息大全";left=509;top=354;right=702;bottom=400;z=3};
btnSendMessage={cls="button";text="发送消息";left=358;top=354;right=485;bottom=400;z=1};
edit={cls="edit";left=37;top=33;right=732;bottom=342;edge=1;multiline=1;z=2}
)
/*}}*/
/*
窗体或控件都可以定义 wndproc 函数处理窗口消息(窗口子类化)。
添加消息回调函数有 2 种不同的方法:
1. 追加消息回调函数:将窗口对象的 wndproc 属性赋值为函数时,
总是追加新的消息回调函数,不会覆盖之前已经添加的的消息回调函数。
这与 adjust 属性的赋值机制几乎是一样的。
> winform.tailWndproc 与 wndproc 的作用相同,
> 但总是会最后调用最后赋值给 tailWndproc 的回调函数。
> 而最后赋值给 wndproc 的回调函数总是最先被调用。
2. 添加到消息回调函数表:如果将窗口对象的 wndproc 属性赋值为表对象。
则 aardio 总是将表内的所有键值对添加到 wndproc 属性存储的消息回调函数表。
新的键值总会覆盖旧的键值,相同消息 ID 的处理函数将被替换,不同消息 ID 的处理函数将被合并与保留。
上面 2 种方式添加的消息回调函数是分开存储的,不会相互覆盖。
如果要添加很多不同消息 ID 的处理函数,方式 2(添加到消息回调函数表)是更好的选择。
因为查表是极快的。但如果不希望覆盖之前的相同消息处理函数,或者不希望被蜇换则应使用方式 1(追加消息回调函数)。
如果将 wndproc 赋值为 null ,则会安全地删除所有消息回调函数。
可以在 wndproc 回调内将 wndproc 赋值为 null ,这只会阻止下次消息回调,不会影响当前调用。
*/
//1. 追加消息回调函数,不会替换之前赋值给 wndproc 属性的调函数对象
winform.wndproc = function(hwnd,message,wParam,lParam){
if(message==0xD/*_WM_GETTEXT*/){
var wstr = '这是通过窗口消息返回的窗口标题'u;
if(wParam>#wstr){
raw.copy(topointer(lParam),wstr);
return #wstr/2;
}
}
//无返回值(或返回 null )则继续调用消息处理函数,返回非 null 值则不会继续调用默认消息处理函数
}
// 2. 添加到消息回调函数表
winform.wndproc = {
/*
aardio 总是合并新旧消息回调表,
相同消息 ID 的处理函数将会被替换,不同消息 ID 的处理函数会被保留。
如果要添加很多消息回调,使用消息回调函数表更快,负担也更小。
但这种方式添加的消息回调是可以被替换的。
在这里,之前的消息回调表里的 _WM_LBUTTONUP 处理函数将被替换为新的函数。
*/
[0x202/*_WM_LBUTTONUP*/] = function(hwnd,message,wParam,lParam){
var x,y = win.getMessagePos(lParam);
print("左键按下",x,y)
//无返回值(或返回 null )则继续调用消息处理函数
}
}
/*
可使用以下函数发送消息:
::User32.SendMessage(hwnd,message,wParam,lParam)
::User32.PostMessage(hwnd,message,wParam,lParam)
参数 hwnd 为目标窗口句柄,参数 message 为消息ID
wParam,lParam 的用法每个消息可能不一样,可查阅相关消息文档
这两个 API 需遵守无声明调用原生 API 规则: https://www.aardio.com/zh-cn/docs/library-guide/builtin/raw/directCall.html
无声明调用可接受各种类型的参数,但使用时应遵守所发送的控件消息约定的参数规则。
win 标准库也提供了
::PostMessage,::SendMessage,::SendMessageInt ... 等声明了参数类型的 API 函数。
或通过控件的以下方法向控件自身发送消息
ctrl.sendMessage(msg,wParam,lParam) //内部调用 ::User32.SendMessage
ctrl.postMessage(msg,wParam,lParam) //内部调用 ::User32.PostMessage
*/
winform.btnSendMessage.oncommand = function(id,event){
//发送 _WM_GETTEXT 消息获取文本,等价于读取 winform.text 属性
var ret,text = winform.btnSendMessage.sendMessage(0xD/*_WM_GETTEXT*/,200,{WORD value[100]});
winform.edit.text = text.value;
}
winform.btnMessageView.oncommand = function(id,event){
import ide;
ide.createProcess("~\tools\GUI\message.aardio");
}
winform.show();
win.loopMessage();
Markdown 格式