拖拽被莫名禁止
首先,告诉大家,这不是描述的一个实现拖拽的功能,而是再有拖拽功能的程序里,再保证代码无误但是有时候功能又实现不了的一种情况的讲解。
请大家选择性继续向下查看。
故事事这样的,有一天我发现一个windows Form 程序有个拖拽的功能无法拖拽了,但是如果重启电脑了就没问题。
然而我在在我的程序里面操作其他功能后,拖拽的功能又不行了,于是,一步一步的核查这些操作的功能,核查了一天多基本没什么成果。
核查第一步结果:通过观察发现,在我拖动的函数 DoDragDrop()在鼠标还没有松开,就已经返回了DragDropEffects.none,在重启电脑发现,如果功能正常的话,我需要返回DragDropEffects.Move。
核查第二步结果:检查代码里面是不是把windows的消息禁止了,无法使我的鼠标来实现左键一直按住。进过核查,我是可以选择文本框里面的文字的,所以排除此问题。
核查第三步结果:windows不会有临时禁止拖拽的功能影响吧? 的确有,但是通过查看配置,我发现的确没错,也没有被我的代码改动过的痕迹。
核查第四步结果:突然上天来了一个天使给我了一个灵感,我试试拖动一下我的桌面快捷键的位置,悲剧呀,居然连桌面文件位置都不能拖动了。
漫漫的悲剧中,发现了程序员的悲哀!
核查第五步结果:再把程序的底层消息函数过滤一遍把。花费了大量的精力全局查找核实。
最后终于看到了希望:最终把需要核实的函数找了出来,它就是随时大家喜欢用到的 keybd_event;
函数原型:
VOID
keybd_event(
BYTE
bVk,
// virtual-key code
BYTE
bScan,
// hardware scan code
DWORD
dwFlags,
// flags specifying various function options
DWORD
dwExtraInfo
// additional data associated with keystroke
);
从原型可以看出,Keybd_event()共有四个参数:
第一个为按键的虚拟键值,如回车键为vk_return, tab键为vk_tab(其他具体的参见附录:常用模拟键的键值对照表);
第二个参数为扫描码,一般不用设置,用0代替就行;
第三个参数为选项标志,如果为keydown则置0即可,如果为keyup则设成"KEYEVENTF_KEYUP";
第四个参数一般也是置0即可
我的代码局部:
public void HHHH()
{
……
keybd_event(27, 0, 0, 0); //这里27是指键盘的Esc案件。
……
}
就这样一行对其他多数功能还真没什么影响,但是,对拖动那是影响大大的。当然对界面Form的拖动也无影响。
按照函数说面:这行代码就是把键盘的Esc按下去了。
试问,有松开操作吗?
如果大家对windows的消息机制比较熟悉,键盘,鼠标都可以用代码来全套模拟实现按下,松开,拖动等操作。
其实找到问题了,要解决就非常简单了,
keybd_event(27, 0, 0, 0); //按下
keybd_event(27, 0, 2, 0); //松开。
这才是一个正常的操作了,
所以技术真不是玩虚的,不懂真的慎用,懂也更要慎用!!!!!!!!!!!!!!!!!!!!!!!!
给大家一个小实验,你按住你键盘的Esc键不松开,你能拖动桌面的文件吗?