窗口靠边吸附的效果dock

zhhyit 11天前 164

搬运与大家分享

使用方法:复制后保存成dock库文件,放lib里,调用使用 import dock;

class dock{
    ctor(winform, acts=10/*每过程动作次数*/, isTop=false/*置顶*/, isDock=true/*吸附*/, margin=false/*留边*/){
        assert(winform[["hwnd"]], "参数@1必须是窗体对象");
        acts = ..math.abs(tonumber(acts) : 1);
        
        //this = win.form(); this.messageOnly();
        this = winform;
        this.site, this.msIn = "", 0;
        var scrw, scrh = win.getScreen();
        
        var wndGdi, alSign = _wndGdi();
        var wndAlpha = function(v = false, w, h){
            alSign = !!v;
            if(!alSign){
                this.transparent(false);
                //this.hide = 1; this.hide = 0;
                //this.redraw();
                _redrawWindow(this.hwnd, , , 0x400/*_RDW_FRAME*/ | 0x1/*_RDW_INVALIDATE*/ | 0x4/*_RDW_ERASE*/)
                return;
            }
            this.transparent(true);
            var col = margin ? 0xaad2d2d2 : 0x01d2d2d2//0xaad2d2d2 : 0x01d2d2d2
            wndGdi(this.hwnd, w, h, function(mdc, w, h){
                var gph = gdip.graphics(mdc)
                var gBru = gdip.solidBrush(col)
                gph.fillRectangle(gBru, 0, 0, w, h)
                gBru.delete()
                gph.delete()
                gdi.updateLayeredWindow(this.hwnd, mdc, ::SIZE(w, h), gdi.blendFunction(255/*透明度*/))
            })
        }
        
        var ap = {}; //aTimer动作定时器运行时参数
        var aTimer = win.timer(, 10);
        aTimer.onTimer = function(hwnd,msg,id,tick){
            var c = true;
            if(ap[["site"]] == "top"){
                ap.y += ap.v;
                c = ap.msIn ? !(ap.y<0) : !(ap.y>4-ap.h);
                if(c) ap.y = !ap.msIn ? 4-ap.h : 0;
            }
            elseif(ap[["site"]] == "left"){
                ap.x += ap.v;
                c = ap.msIn ? !(ap.x<0) : !(ap.x>4-ap.w);
                if(c) ap.x = !ap.msIn ? 4-ap.w : 0;
            }
            elseif(ap[["site"]] == "right"){
                ap.x -= ap.v;
                c = ap.msIn ? !(ap.x>scrw-ap.w) : !(ap.x<scrw-4);
                if(c) ap.x = ap.msIn ? scrw-ap.w : scrw-4;
            }
            this.setPos(ap.x, ap.y);
            if(c){
                if(#ap[["site"]] && !ap.msIn){
                    wndAlpha(1, ap.w, ap.h);
                    if(!isTop) win.setTopmost(this.hwnd);
                }
                elseif(!isTop) win.setTopmost(this.hwnd, false);
                owner.disable();
            }
            elseif(alSign) wndAlpha(, ap.w, ap.h);
        }
        
        var msPos = ::POINT();
        var mTimer = win.timer(, 10);
        mTimer.onTimer = function(hwnd,msg,id,tick){
            var x, y, w, h = this.getPos();
            if(w >= scrw) return;
            
            //**判断窗口停靠位置
            var site = ""
            if(x <= 0) site = "left";
            elseif(x+w >= scrw) site = "right";
            elseif(y <= 0) site = "top";
            
            if(this.site != site){
                this.site = site
                ::PostMessage(this.hwnd, 0x503, 0, 0)
            }
            //**/
            
            //**检测鼠标进出窗口 左键状态 判断是否动作
            _getMsPos(msPos)
            var msIn = _msIn(msPos.x, msPos.y) ? 1 : 0
            var v = _getAsyncKeyState(1)
            if(this.msIn != msIn){
                this.msIn = msIn
                ::PostMessage(this.hwnd, 0x5A3, 0, 0)
            }
            elseif(!v) return;
            if(!#site || v) return;
            //**/
            
            //**执行动作
            v = (site == "top") ? ..math.ceil(h/acts) : ..math.ceil(w/acts);
            v = msIn ? v : -v;
            ap.site,ap.msIn,ap.x,ap.y,ap.w,ap.h,ap.v = site,msIn,x,y,w,h,v;
            aTimer.enable();
            //**/
        }
        
        this.wndMargin = function(v = false){
            margin = !!v
        }
        
        //**窗口呼出
        this.wndDisplay = function(){
            var x, y, w, h = owner.getPos();
            if(x<0) x = 0
            elseif(x+w>scrw) x = scrw-w
            if(y<0) y = 0
            elseif(y+h>scrh) y = scrh-h
            owner.setPos(x, y)
            owner.transparent(false)
        }
        this.wndDisplay()
        //**/
        
        //**窗口置顶 避免与aTimer里的win.setTopmost冲突
        this.wndTopmost = function(v){
            isTop = !!v
            win.setTopmost(owner.hwnd, isTop)
            return isTop;
        }
        this.wndTopmost(isTop)
        //**/
        
        //**窗口吸附
        this.wndDock = function(v = true){
            isDock = !!v
            if(isDock) mTimer.enable();
            else { mTimer.disable(); owner.wndDisplay() }
            return isDock;
        }
        this.wndDock(isDock)
        //**/
        
        this.wndproc = {
            [0x7E/*_WM_DISPLAYCHANGE 屏幕分辨率改变*/] = function(hwnd,message,wParam,lParam){
                scrw, scrh = win.getScreen();
                owner.wndDisplay()
            }
        }
        ::PostMessage(this.hwnd, 0x5A3, 0, 0);
    };
}
namespace dock{
    import win.timer;
    import gdip.graphics;
    import gdip.solidBrush;
    import gdi;
   
    _getMsPos = ::User32.GetCursorPos;
    _redrawWindow = ::User32.RedrawWindow;
    _fromPoint = ::User32.WindowFromPoint;
    _getAsyncKeyState = ::User32.GetAsyncKeyState;
    _getWindowThreadProcessId = ::User32.GetWindowThreadProcessId;
    _msIn = function(x, y){
        var hwnd = _fromPoint(x, y);
        return _getWindowThreadProcessId(hwnd, 0) == ..thread.getId();
    }
    _wndGdi = function(){
        var hdc, mdc, hbmp;
        var create = function(hwnd, w, h){
            hdc = ::GetWindowDC(hwnd);
            mdc = ::CreateCompatibleDC();
            hbmp = ::CreateCompatibleBitmap(hdc, w, h);
            ::SelectObject(mdc, hbmp);
        }
        var delete = function(hwnd){
            ::ReleaseDC(hwnd, hdc);
            ::DeleteDC(mdc);
            ::DeleteObject(hbmp);
        }
        return function(hwnd, w, h, draw, ...){
            create(hwnd, w, h);
            if(type(draw) == "function") draw(mdc, w, h, ...);
            delete(hwnd);
        }
    }
}

已知问题(希望光大能帮助优化下):

1、窗体贴边影藏之后,无法通过点击状态栏程序图标激活,必须鼠标放到贴边位置,有时候找不到,需要鼠标围着桌面贴边找一圈;

2、贴边程序不稳定,有时候锁屏之后,再打开电脑,发现程序界面变得透明,甚至到找不到了,完全透明了;

纯属搬运,非原创

上传的附件:
最新回复 (0)
返回
发新帖