《制作“浮动窗”心得》
《制作“浮动窗”心得》
最近编了一个软件,无敌剪贴板,为了使其功能更多,于是我想到了加入netants,flashget之类的浮动窗,选中网页上的字,然后拖入浮动窗,一开始我不知道怎样制作,于是开始查葵花宝典,试了试,在我的系统(win2000)下根本行不通,在任务栏上有按钮,于是我又去论坛搜索,询问别人,谁知众说纷纭,我挨个的试,最后终于让我找到了自己的答案(集众人所长,加入自己的总结)
好了,闲话少说,切入正题:
举一个简单的例子,我有2个Form,smain(主窗体),fly(浮动窗),其实只要重载CreateParams就可以了,源码如下:
PROCEDURE Tsmain.CreateParams(VAR Params: TCreateParams);
BEGIN
INHERITED CreateParams(Params);
Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW; {让主窗体出现在任务栏}
SetWindowLong(application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);{关键!让程序在任务栏上的按钮消失}
END;
PROCEDURE Tfly.createparams(VAR Params: TcreateParams);
BEGIN
INHERITED CreateParams(Params);
WITH params DO
BEGIN
Style := Style XOR WS_DLGFRAME;{让窗体有边框}
Exstyle := Exstyle OR WS_EX_TOOLWINDOW OR WS_EX_TOPMOST;{WS_EX_TOOLWINDOW:让窗体的任务栏按钮消失;WS_EX_TOPMOST:让窗体总在最前}
wndParent := 0;{缺少这句点击“显示桌面”浮动窗会消失}
END;
END;
至于拖动问题,看代码:
PROCEDURE Tfly.ImageMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
BEGIN
ReleaseCapture;
self.Perform($112, $F012, 0);
END;
别以为这样就行了,其实你会发现当smain最小化时会缩到左下脚,于是我采取拦截WM_SYSCOMMAND,让最小化变为隐藏,但问题还没有完全解决,如果还有一个AboutBox(“关于”),当AboutBox执行ShowModal时,fly就不能拖动了,这是由于ShowModal时,fly.Enabled被设为false,解决方法:拦截WM_ENABLE,再用EnableWindow(handle, true);就可以了。
还有一个问题我没有完全解决,看看flashget,点击桌面上的任意文件后,把鼠标移到浮动窗上会出现"FlashGet"的提示,然而fly必须先获得焦点,才能出现提示,于是我用了一个笨办法,在MouseMove事件里加入self.SetFocus;不过这样做有一个缺点,就是当smain出现时,把鼠标移到fly上,smain会丢失焦点,而flashget却不会,后来我又试了smain.BringToFront;发现当执行“关于”时,“关于”这个Form,会被smain覆盖。