aardio 官方社区

 找回密码
 注册会员

QQ登录

只需一步,快速开始

搜索
查看: 22193|回复: 13

再接再厉,发个‘悬浮窗体’ 的库,继续支持aardio~

  [复制链接]

39

主题

163

回帖

1351

积分

四级会员

积分
1351
发表于 2011-1-9 22:35:25 | 显示全部楼层 |阅读模式
本帖最后由 wudijushi 于 2011-1-9 22:37 编辑

今晚再写了个库,就像很多软件都使用悬浮窗体基本框架,其实还可以实现一些如:利用图片生成异形窗体、透明窗体  之类
忙了一晚,还有点不舒服,先发给大家测试一下(有太多需要完善的),大家跟贴提建议!!我先去休息了,明天还要上课.....
jacen等大大们可以尽情批点吧!(上次的动画窗体库,jacen重写后让我学到很多...,所以如果大大们有更好的实现方法,这个也可以完全重写的,我不介意!)
智能提示写得有点问题,还不是很熟练....

11.jpg //<-测试图片
/*
大家这样进行测试:
import win.floatwindow;
var fw = win.floatwindow.createfloatwindow(winform,$"c:\1.jpg",true);  //传入张50*50的图片,或根据智能提示自定义悬浮窗体的大小
*/

//悬浮窗口
/************************************
Author      : wudijushi
Date        : 2011.01.09
************************************/


namespace win.floatwindow;

import win.ui;
import win.animate;
import win.ui.menu;

class  createfloatwindow{
   
ctor( parentwinform, linkimage, shownow=true, tab){
   
if(!tab){ arg = {bottom=50;right=50};   }
   
else { arg = tab; }
   
   
this.winform = ..win.form(parent=parentwinform; exmode="none";title=false;min=false;max=false;
            sysmenu=
false;image=linkimage;border="none";bottom=arg["bottom"];right=arg["right"];mode="popup" );
   
this.winform.add(  );
   
this.hwnd = this.winform.hwnd;
   
//创建右键弹出菜单
    this.winform.popmenu = ..win.ui.popmenu(this.winform);//创建弹出菜单
    this.winform.popmenu.add('隐藏/显示 悬浮窗口',function(id){
        
this.showme(!..win.isVisible( this.winform.hwnd ));
    });
   
this.winform.popmenu.add();//分隔线
    this.winform.popmenu.add('退出程序',function(id){ this.winform.parent.close() })
   
   
//窗体消息
    this.winform.wndproc = function(hwnd,message,wparam,lparam){
        
select(message) {//判断消息类型
            case 0x10/*_WM_CLOSE窗口关闭消息*/{
               
            }
            
case 0x205/*_WM_RBUTTONUP 鼠标右键弹起,弹出菜单*/begin
               
var x,y = ::LOWORD(lparam), ::HIWORD(lparam)
               
this.winform.popmenu.popup(x,y);//弹出菜单
            end
            
case 0x201/*_WM_LBUTTONDOWN*/{
               
this.winform.hitCaption();
            }
            
case 0x203/*_WM_LBUTTONDBLCLK*/{
               
this.showparent(!..win.isVisible( this.winform.parent.hwnd ));
            }
            
else{
               
            }
        }
   
//无返回值则继续调用默认回调函数
    }
   
   
//悬浮置顶
    ..win.setTopmost( this.winform.hwnd );
   
//调整位置
    ..win.setPos( this.winform.hwnd,
                ::GetSystemMetrics(0x10
/*_SM_CXFULLSCREEN*/) - (this.winform.rect.right - this.winform.rect.left) - 80,
                ::GetSystemMetrics(0x11
/*_SM_CYFULLSCREEN*/) /10,
               
this.winform.rect.right - this.winform.rect.left,
               
this.winform.rect.right - this.winform.rect.left
    );
   
//显示窗口
    if( shownow ){  ..win.animate.show( this.winform.hwnd )  }
   
   }  
//end ctor
   
    showme =
function(flag=true){
        
if( flag ){
            ..win.animate.show(
this.winform.hwnd);
        }
        
else {
            ..win.animate.hide(
this.winform.hwnd);
        }
    }
   
    showparent =
function(flag=true){
        
if( flag ){
            ..win.animate.show(
this.winform.parent.hwnd);
        }
        
else {
            ..win.animate.hide(
this.winform.parent.hwnd);
        }
    }


}

/*intellisense()
win.floatwindow.createfloatwindow(.(parentwinform, linkimage, shownow=true,{可选项} ) ={可选项}\n{buttom=50;\nright=50}
!floatwindow.showme(.(true显示 / false隐藏)
!floatwindow.showparent(.(true显示 / false隐藏 )
!floatwindow.hwnd = 悬浮窗句柄
!floatwindow.winform = 窗体对象
?win.floatwindow.createfloatwindow = !floatwindow.
end intellisense*/


52

主题

1268

回帖

7276

积分

荣誉会员

积分
7276
发表于 2011-1-9 22:49:31 | 显示全部楼层
wudijushi 也是一个好学生呀,谢谢你又写了一个的有特色窗口库

点评

同意: 3.0
同意: 3
: )  发表于 2011-1-10 10:25

117

主题

1103

回帖

6572

积分

六级会员

积分
6572
发表于 2011-1-10 00:12:34 | 显示全部楼层

点评

同意: 4.0
同意: 4
还要完善,大家可以提意见,或建议 :)  发表于 2011-1-10 10:26

166

主题

2153

回帖

1万

积分

管理员

积分
13056
发表于 2011-1-10 00:50:37 | 显示全部楼层
我试了一下程序写的很棒,很简单就实现了悬浮窗体。
但是作为库来说,要求就高些,所以我还是要找点麻烦:

作为一个类用createfloatwindow这个做名字不是很好。  
另外命名注意第二个单词开始首字母要大小,作为库的命名也应尽可能简洁。
类名建议用 win.util.float 实际上这已经表示了createfloatwindow的全部意思。例如:

namespace win.util
class float{
   
//实例成员
}

namespace float{
   
//静态成员
}

库之间也应注意尽可能的互不相关,减少相互的依赖.尤其是编写库更应当注意这一点。
你只能封装不太可能变化的代码,而把可能变化的代码留给用户,
这里不是很有必要在库里导入win.animate来显示动画窗口。

如果你要在库里显示窗口,你大可只是调用winform.show.
因为具体到窗口,他使用的时候,他可以选择是不是用动画,大可以这么用:

//重写winform.show函数
import win.animate
winform.show =
function(show){
   
if(show===null || show)
        win.animate.show(winform.hwnd,-2);
   
else  
        win.animate.hide(winform.hwnd)
   
}

winform.show();


至于菜单,最好是不要在库里写任何菜单,而是预留一个popmenu这样的成员变量 ,
由用户来指定是否显示菜单,显示什么样的菜单。写库应当尽可能的抽象,减少对具体实现的依赖关系。

var floatWindow = win.util.float(winform)
floatWindow.popmenu = win.ui.popmenu(winform);
//输入的时候自动输入实现菜单的模板
//库根本不用管菜单,而让用户来实现具体的菜单,这样不是更好更灵活? 而库的逻辑也会简单的多,代码也会更少


在库里面,可以这样写

var x,y = ::LOWORD(lparam), ::HIWORD(lparam)
if( this.popmenu ) //如果用户定义了弹出菜单
      this.popmenu.popup(x,y);//弹出菜单



39

主题

163

回帖

1351

积分

四级会员

积分
1351
 楼主| 发表于 2011-1-10 22:32:27 | 显示全部楼层
回复 jacen 的帖子

按着jacen的建议,重新写了,应该比上一次好点了。
还是太菜了,搞了很久。希望jacen可以继续指点修正有个问题是父窗体最小化时,悬浮窗体跟着消失,还没找到方法解决!


测试代码:
//创建悬浮窗体
var floatWindow;
floatWindow = win.util.float(winform, $"C:\Documents and Settings\Administrator\桌面\11.bmp",false,{bottom=50;right=50;color= gdi.RGB( 0, 0, 0)});//使黑色透明
//自定义菜单方式
floatWindow.popmenu = win.ui.popmenu(floatWindow.winform);//创建弹出菜单
floatWindow.popmenu.add('&open',function(id){
        //在下面输入菜单响应代码
        
});
floatWindow.popmenu.add();//分隔线
floatWindow.popmenu.add('&exit',function(id){ winform.close() })
//显示窗体的方法

floatWindow.showme(true);


//提供的属性
hWnd = 悬浮窗句柄     //要应用动画窗体的这样写     win.animate.show(floatWindow.hWnd);
winform = 悬浮窗体对象
popmenu = 右键菜单



测试图片:(本机效果)
88.png
如果要测试图片生成不规则窗体的话,自己在系统画板里随便画一个,用黑色做背景,保存  .bmp文件!!



晕,有字数限制,分几楼咯.....
11.jpg

点评

m_前缀这种命名法不提倡,这里最好直接用 hwnd 或 popmenu  发表于 2011-1-10 22:42

39

主题

163

回帖

1351

积分

四级会员

积分
1351
 楼主| 发表于 2011-1-10 22:33:22 | 显示全部楼层
本帖最后由 wudijushi 于 2011-1-10 23:00 编辑

回复 wudijushi 的帖子

//悬浮窗口
/************************************
Author      : wudijushi
Date        : 2011.01.09
************************************/


namespace win.util;

import win.ui;
import gdip;
import gdip.bitmap;

class  float{
   
ctor( parentwinform, linkimage, shownow, tab){
   
if(!tab){ arg = {bottom=50;right=50;imgPathWnd=false;color=null};  }
   
else { arg = tab; }
   
   
this.winform = ..win.form(parent=parentwinform; exmode="none";title=false;min=false;max=false;
                                sysmenu=
false;image=linkimage;border="none";bottom=arg["bottom"];right=arg["right"];mode="popup" );
   
this.winform.add(  );
   
   
//成员变量
    this.hWnd = this.winform.hwnd;
   
   
//窗体消息
    this.winform.wndproc = function(hwnd,message,wparam,lparam){
        
select(message) {//判断消息类型
            case 0x10/*_WCLOSE窗口关闭消息*/{

        }
            
case 0x2/*_WDESTROY*/{
               
//释放区域对象
                if( this.hRgn){
                    ::DeleteObject(
topointer(this.hRgn));
                    
this.hRgn = null;
                }
               
//释放位图相关对象
                if ( this.hMemDC){
                    ::SelectObject(
this.hMemDC, this.hOldBmp);
                    ::DeleteDC(
topointer(this.hMemDC));
                    
this.hMemDC = null;
                    
this.hOldBmp = null;
                }
            }
            
case 0x14/*_WERASEBKGND*/{  
                    
if(this.hMemDC){
                        
var rect = ::RECT();
                        ::GetClientRect(
this.hWnd, rect);
                        
var hdc = ::GetDC(this.hWnd);
                        ::BitBlt(hdc, 0, 0, rect.right, rect.bottom,
this.hMemDC, 0, 0, 0xCC0020/*_SRCCOPY*/);
                        ::ReleaseDC(
this.hWnd, hdc);
                        
return true;
                    }
            }
            
case 0x205/*_WRBUTTONUP 鼠标右键弹起,弹出菜单*/begin
               
var x,y = ::LOWORD(lparam), ::HIWORD(lparam)
               
if( this.popmenu ) //如果用户定义了弹出菜单
                    this.popmenu.popup(x,y);//弹出菜单
            end
            
case 0x201/*_WLBUTTONDOWN*/{
               
this.winform.hitCaption();
            }
            
case 0x203/*_WLBUTTONDBLCLK*/{
                ..win.show(
this.winform.parent.hwnd,!..win.isVisible( this.winform.parent.hwnd ));
            }
            
else{
               
            }
        }
   
//无返回值则继续调用默认回调函数
    }
   
   
//悬浮置顶
    ..win.setTopmost( this.hWnd );
   
//调整位置
    ..win.setPos( this.hWnd,
                ::GetSystemMetrics(0x10
/*_SCXFULLSCREEN*/) - (this.winform.rect.right - this.winform.rect.left) - 80,
                ::GetSystemMetrics(0x11
/*_SCYFULLSCREEN*/) /10,
               
this.winform.rect.right - this.winform.rect.left,
               
this.winform.rect.right - this.winform.rect.left
    );
   

  

39

主题

163

回帖

1351

积分

四级会员

积分
1351
 楼主| 发表于 2011-1-10 22:33:50 | 显示全部楼层
回复 wudijushi 的帖子

   //图片路径画窗体
    if( arg["color"] !=null ){
            
//创建一个内存兼容DC
            var hdc          = ::GetDC( this.hWnd );
            
this.hMemDC   := ::CreateCompatibleDC( hdc );
            ::ReleaseDC(
this.hWnd, hdc);
            
//将内存DC和位图关联
            this.hOldBmp    := ::SelectObject(this.hMemDC, this.winform.hBkbitmap);
            
//根据位图生成区域对象
            //循环中用到的临时变量
            var hRgn = null;
            
var hRgnTemp = null;
            
//循环检测位图,将非透明点增加到最终区域。
            var img = ..gdip.bitmap(this.winform.image);
            
for(x=0; img.width-1; 1){
               
for(y=0; img.height-1; 1){
                    
var cr = ::GetPixel(this.hMemDC, x, y);
                    
if (cr != arg["color"]){        
                        hRgnTemp = CreateRectRgn(x, y, x+1, y+1);
                        
if (hRgn){
                            CombineRgn(hRgn, hRgn, hRgnTemp, 0x2
/*_RGN_OR*/);
                            ::DeleteObject(
topointer(hRgnTemp));
                        }
                        
else{
                            hRgn = hRgnTemp;
                        }
                    }
                }
            }
            
this.hRgn := hRgn;
            
//将区域设置到窗体
            SetWindowRgn(this.hWnd, this.hRgn, 0x1/*_TRUE*/);
    }
   
//显示窗口
    if( shownow ){ this.winform.show(); }
   
   }  
//end ctor
   
   
//成员函数
    showme = function( flag ){
        
if( flag ){
            ..win.show(
this.hWnd, flag);
        }

      else {
            ..win.show(this.hWnd, flag);
        }
    }

}

namespace float{
    SetWindowRgn = ::User32.api(
"SetWindowRgn","int(int hWnd,int hRgn,int bRedraw)");
    GetObjectAPI = ::Gdi32.api(
"GetObjectA","int(int hObject,int nCount,pointer& lpObject)");
    CreateRectRgn = ::Gdi32.api(
"CreateRectRgn","int(int X1,int Y1,int X2,int Y2)");
    CombineRgn = ::Gdi32.api(
"CombineRgn","int(int hDestRgn,int hSrcRgn1,int hSrcRgn2,int nCombineMode)");      
}

/*intellisense()
win.util.float(.(parentwinform, linkimage, shownow(true|false),{可选项} ) ={可选项}\n{buttom=50;\nright=50;\ncolor= gdi.RGB( 0, 0, 0)若传入,侧使你指定的颜色透明,但是请确保是.bmp后缀的图片做背景! }
!float.showme(.(true显示 / false隐藏)
!float.hWnd = 悬浮窗句柄
!float.winform = 悬浮窗体对象
!float.popmenu = 右键菜单
?win.util.float = !float.
end intellisense*/

点评

大括号有的在行尾,有的在行首,不是很规范,建议一律写为 行尾 + { + 换行 ........  发表于 2011-1-10 22:46

6

主题

57

回帖

387

积分

荣誉会员

积分
387
发表于 2011-1-11 09:34:34 | 显示全部楼层
太棒了

3

主题

21

回帖

135

积分

一级会员

积分
135
发表于 2011-1-11 22:07:19 | 显示全部楼层
高人,貌似很复杂,没看明白

1

主题

15

回帖

124

积分

新手入门

积分
124
发表于 2012-4-2 21:12:35 | 显示全部楼层
发库最好把简单的示列代码也发一份{:soso_e120:}

3

主题

19

回帖

140

积分

一级会员

积分
140
发表于 2016-5-1 14:04:46 | 显示全部楼层
wudijushi 发表于 2011-1-10 22:33
回复 wudijushi 的帖子

//悬浮窗口

第一行打错字了:“namespace win.util;”应该为:“namespace win.floatWindow;”否则无法运行

0

主题

7

回帖

37

积分

新手入门

积分
37
发表于 2016-5-18 19:00:32 | 显示全部楼层
这个很好,什么时候我也能达到这样的水平

3

主题

19

回帖

140

积分

一级会员

积分
140
发表于 2016-6-4 19:20:04 | 显示全部楼层
MC肥羊 发表于 2016-5-1 14:04
第一行打错字了:“namespace win.util;”应该为:“namespace win.floatWindow;”否则无法运行

好吧是我看错啦

0

主题

5

回帖

40

积分

新手入门

积分
40
发表于 2016-7-14 18:15:21 | 显示全部楼层
哎呀,对我这个小白来说,这个就比较复杂了,不行的话直接抄来用了……
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|aardio.com|aardio 官方社区 ( 皖ICP备09012014号 )

GMT+8, 2025-7-17 20:05 , Processed in 0.072423 second(s), 28 queries .

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表