/// <summary> /// Calculates distance between rectangle and point. /// Returns 0 if point is in rectangle. /// </summary> public static double Distance(RECT r, POINT p) { r.Normalize(swap: true); if (r.Contains(p)) { return(0); } int x = p.x < r.left ? r.left : (p.x > r.right ? r.right : p.x); int y = p.y < r.top ? r.top : (p.y > r.bottom ? r.bottom : p.y); return(Distance((x, y), p)); }
/// <summary> /// 根据鼠标位置获取窗口句柄 /// </summary> /// <param name="x">x坐标</param> /// <param name="y">y坐标</param> /// <param name="hWndExcept">需要忽略的窗口句柄 通常该值为调用者窗口句柄</param> /// <param name="bVisbleOnly">是否只获取可见窗口</param> /// <param name="bTransparent">是否获取透明窗口</param> /// <returns></returns> public static IntPtr GetWindowFromPoint(int x, int y, IntPtr hWndExcept, bool bVisbleOnly, bool bTransparent) { IntPtr hParent = IntPtr.Zero; IntPtr hAfter = IntPtr.Zero; RECT rect = new RECT(); while ((hAfter = FindWindowEx(hParent, hAfter, null, null)) != IntPtr.Zero) { //如果获取出来的窗口为需要忽略的窗口 跳过 if (hAfter == hWndExcept) { continue; } //如果只需要获取可见窗口 而获取出来的为不可见窗口 跳过 if (bVisbleOnly && (Win32.GetWindowLong(hAfter, GWL_STYLE) & WS_VISIBLE) == 0) { continue; } //如果不获取透明窗口 而获取出来的窗口为透明 跳过 if (!bTransparent && (Win32.GetWindowLong(hAfter, GWL_EXSTYLE) & WS_EX_TRANSPARENT) != 0) { continue; } //这个类的窗体可以忽略掉 一般这种窗体都是隐藏的 比如开始菜单这些 但是确实有visible属性 string strClassName = Win32.GetClassName(hAfter); if (strClassName == "Windows.UI.Core.CoreWindow") { if ((GetWindowLong(hAfter, GWL_STYLE) & WS_POPUP) != 0) { continue; } continue; } GetWindowRect(hAfter, ref rect); if (rect.Contains(x, y)) { hParent = hAfter; hAfter = IntPtr.Zero; } } return(hParent); }
void _WmMousemove(POINT pc) { if (!_paintedOnce) { return; } //format text to draw below magnifier string text; using (new StringBuilder_(out var s)) { var ic = _flags & (ICFlags.Image | ICFlags.Color | ICFlags.Rectangle); if (ic == 0) { ic = ICFlags.Image | ICFlags.Color; } bool canColor = ic.Has(ICFlags.Color); if (canColor) { var color = _img.GetPixel(pc.x, pc.y).ToArgb() & 0xffffff; s.Append("Color #").Append(color.ToString("X6")).Append('\n'); } if (ic == ICFlags.Color) { s.Append("Click to capture color.\n"); } else if (ic == ICFlags.Rectangle) { s.Append("Mouse-drag to capture rectangle.\n"); } else if (!canColor) { s.Append("Mouse-drag to capture image.\n"); } else { s.Append("Mouse-drag to capture image,\nor Ctrl+click to capture color.\n"); } s.Append("More: right-click"); //" cancel: key Esc\n retry: key F3 ... F3" text = s.ToString(); } var font = NativeFont_.RegularCached(_dpi); int magnWH = Dpi.Scale(200, _dpi) / 10 * 10; //width and height of the magnified image without borders etc if (_textSize == default) { using (var tr = new FontDC_(font)) _textSize = tr.MeasureDT(text, TFFlags.NOPREFIX); } int width = Math.Max(magnWH, _textSize.width) + 2, height = magnWH + 4 + _textSize.height; using var mb = new MemoryBitmap(width, height); var dc = mb.Hdc; using var wdc = new WindowDC_(_w); //draw frames and color background. Also erase magnifier, need when near screen edges. Api.FillRect(dc, (0, 0, width, height), Api.GetStockObject(4)); //BLACK_BRUSH //copy from captured screen image to magnifier image. Magnify 5 times. int k = magnWH / 10; Api.StretchBlt(dc, 1, 1, magnWH, magnWH, wdc, pc.x - k, pc.y - k, k * 2, k * 2, Api.SRCCOPY); //draw red crosshair k = magnWH / 2; using (var pen = new Pen_(0xff)) { pen.DrawLine(dc, (k, 1), (k, magnWH + 1)); pen.DrawLine(dc, (1, k), (magnWH + 1, k)); } //draw text below magnifier var rc = new RECT(1, magnWH + 2, _textSize.width, _textSize.height); Api.SetTextColor(dc, 0x32CD9A); //Color.YellowGreen Api.SetBkMode(dc, 1); var oldFont = Api.SelectObject(dc, font); Api.DrawText(dc, text, ref rc, TFFlags.NOPREFIX); Api.SelectObject(dc, oldFont); //set magninifier position far from cursor var pm = new POINT(4, 4); _w.MapScreenToClient(ref pm); int xMove = magnWH * 3; if (_magnMoved) { pm.Offset(xMove, 0); } var rm = new RECT(pm.x, pm.y, width, height); rm.Inflate(magnWH / 2, magnWH / 2); if (rm.Contains(pc)) { Api.InvalidateRect(_w, (pm.x, pm.y, width, height)); _magnMoved ^= true; pm.Offset(_magnMoved ? xMove : -xMove, 0); } Api.BitBlt(wdc, pm.x, pm.y, width, height, dc, 0, 0, Api.SRCCOPY); }