我们知道,aardio的窗体封装了winform.onDropFiles事件,可以很方便地响应文件拖放。但是一般的控件并没有封装这个函数。那么如何让这些控件也响应文件拖放呢?
简单的,我们可以伪装。仍然让窗体去接收事件,然后根据鼠标位置,判断对应哪个控件。比如:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=317)
winform.add(
edit={cls="edit";left=386;top=49;right=715;bottom=264;autohscroll=false;edge=1;multiline=1;z=2};
richedit={cls="richedit";left=30;top=49;right=364;bottom=269;autohscroll=false;edge=1;multiline=1;z=1}
)
/*}}*/
import winex
import mouse
winform.onDropFiles = function(files){
var x,y=mouse.getPos()
var hwnd=winex.fromPointReal(x,y)
if !string.match(win.getClass(hwnd),"@@edit") return ;
win.setText(hwnd,table.tostring(files))
}
winform.show();
win.loopMessage();
但其实我们也有更好的办法,就是在控件的回调函数中去捕获WM_DROPFILES消息。
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=700;bottom=307)
winform.add(
button={cls="button";text="启用文本框的文件拖放功能";left=67;top=238;right=297;bottom=275;z=2};
button3={cls="button";text="禁用文本框的文件拖放功能";left=384;top=233;right=614;bottom=270;z=3};
edit={cls="edit";left=39;top=28;right=669;bottom=204;autohscroll=false;edge=1;multiline=1;z=1}
)
/*}}*/
winform.button.oncommand = function(id,event){
//使用代码在程序运行时启用/禁用文本框的文件拖放功能,比使用属性设置更灵活
::Shell32.DragAcceptFiles(winform.edit.hwnd,true);
}
winform.button3.oncommand = function(id,event){
::Shell32.DragAcceptFiles(winform.edit.hwnd,false);
}
winform.onDropFiles = function(files){
//虽然窗体属性没有启用文件拖放,但设置这个函数后就相当于启用了。
//注意:如果窗体上的控件已经响应文件拖放事件,则在该区域内窗体的文件拖放事件不再执行。
win.msgbox("拖放文件到窗体")
}
winform.edit.wndproc = function(hwnd,message,wParam,lParam){
select(message) {
case 0x233/*_WM_DROPFILES*/ {
var files=win.getDropFile(wParam)
winform.edit.print(files)
win.msgbox("拖放文件到控件")
}
}
}
winform.show();
win.loopMessage();
注意,在窗体和控件都响应文件拖放的情况下,控件所在区域优先由控件响应,窗体不会重复响应。
在以前,我不知道win.getDropFile函数的时候,我是这样比较笨地通过API获取文件信息的:
var m=::Shell32.DragQueryFileW(wParam,0xFFFFFFFF,null,0) //文件数
var files={}
for (i=1;m){
var n=::Shell32.DragQueryFileW(wParam,i-1,null,0)//文件名字符数
var buf=raw.buffer(n*2)
::Shell32.DragQueryFileW(wParam,i-1,buf,n+1)//
files[i]=string.fromUnicode(buf)
}
相当于我把这个函数的源码自己折腾了一遍 ,就算是学习api了吧。