异形窗口高亮[原创]
2006-10-27 14:06 老博客哈 阅读(1126) 评论(0) 编辑 收藏 举报写窗口小助手的时候用到了窗口边缘高亮的东东。之前网上搜到的一篇文章如下:
实现 SPY++ 的 FindWindow Tool 的高亮(highlight)一个应用程序的窗体或内部 Object 的边缘
方法一:
通过 SelectObject 来实现
procedure InvertTracker(hwndDest: HWND);
//画边框
var
hdcDest : HWND;
hPen : HWND;
hOldPen : HWND;
hOldBrush : HWND;
cr : HWND;
rc : TRect;
begin
GetWindowRect(hwndDest, rc);
hdcDest := GetWindowDC(hwndDest);
SetROP2(hdcDest,R2_NOT);
cr := clBlack;
hPen := CreatePen(PS_INSIDEFRAME,2,cr);
hOldPen := SelectObject(hdcDest, hPen);
hOldBrush := SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
Rectangle(hdcDest, 0, 0, rc.Right - rc.Left, rc.Bottom - rc.Top);
SelectObject(hdcDest, hOldBrush);
SelectObject(hdcDest, hOldPen);
ReleaseDC(hwndDest, hdcDest);
DeleteObject(hPen);
end;
方法二:
将边框区域颜色取反
procedure HighlightWindow(hWndWindow: HWND);
var hDCWindow: HDC;
RECT: TRect;
DINV: Integer;
begin
if (hWndWindow = 0) or (Not IsWindow(hWndWindow)) then
Exit
else begin
hDCWindow := GetWindowDC(hWndWindow);
Windows.GetWindowRect(hWndWindow, RECT);
OffsetRect(RECT, -RECT.Left,-RECT.Top);
DINV := 4;
if Not IsRectEmpty(RECT) then
begin
PatBlt(hDCWindow, RECT.Left, RECT.Top, RECT.Right - RECT.Left, DINV, DSTINVERT);
PatBlt(hDCWindow, RECT.left, RECT.bottom - DINV, DINV,
-(RECT.bottom - RECT.top - 2 * DINV), DSTINVERT);
PatBlt(hDCWindow, RECT.right - DINV, RECT.top + DINV, DINV,
RECT.bottom - RECT.top - 2 * DINV, DSTINVERT);
PatBlt(hDCWindow, RECT.right, RECT.bottom - DINV, -(RECT.right - RECT.left),
DINV, DSTINVERT);
end;
ReleaseDC(hWndWindow, hDCWindow);
end;
end;
不过这两个都无法实现异型窗体的高亮
我用的是GDI+画的, 方法和上面的方法二相似。详细代码可以到这里下载
这里我主要是想谈谈我对异形窗体的边缘高亮的做法:
先利用GetWindowRgn 获取窗口的hRgn, 然后枚举Client区域的像素点,判断其是否处于边缘,
如果是则保存该点, 最后利用SetPixel绘制边缘曲线。
核心代码如下:
{
IntPtr hRgn = this.Region.GetHrgn(g);
GetWindowRgn(this.Handle, ref hRgn);
List<Point> list = new List<Point>();
for (int i = 0; i < this.ClientRectangle.Width; i++)
{
for (int j = 0; j < this.ClientRectangle.Height; j++)
{
bool a = PtInRegion(hRgn, i - 1, j);
bool b = PtInRegion(hRgn, i + 1, j);
bool c = PtInRegion(hRgn, i, j - 1);
bool d = PtInRegion(hRgn, i, j + 1);
if ((a ^ b) || (c ^ d))
{
list.Add(new Point(i, j));
}
}
}
IntPtr hdc = g.GetHdc();
for (int k = 0; k < list.Count; k++)
{
SetPixel(hdc, list[k].X, list[k].Y, 255);
}
g.ReleaseHdc();
}
贴图如下: