如何创建可以覆盖所有 windows 的文本,如 Windows 激活水印?
How does one create text that can overlay all windows like the Windows Activation Watermark?
我想创建一个倒计时计时器,它显示在屏幕的右下角,带有稍微透明的文本,无论您在屏幕上有什么,都可以看到。想想当您的 windows 副本未激活时出现的 windows 未激活水印消息。它显示在右下角,覆盖所有 windows 并“卡在”屏幕上。
有没有办法通过程序来做到这一点? C# 首选。
到目前为止,在我的研究中,我只遇到了 Deskbands,它允许你在任务栏中放置一些东西,但不能放在任务栏之外。
注意: 下面的答案创建了一个正常的 semi-transparent 最上面的形状,边缘平滑。它并不完全像 windows 激活文本,例如它位于工具提示 windows 或菜单后面,但它位于其他 non-topmost windows.[=21= 之上]
您可以创建一个 Layered Window by setting WS_EX_LAYERED style, then you can assign a smooth-edge transparent region to the window. You can also set WS_EX_TRANSPARENT
for the window, then it will ignore the mouse event. Then to make it always on top set its TopMost
to true
. And finally if you want to make it semi-transparent use suitable Opacity
值。
例子
在下面的示例中,我创建了一个始终位于顶部并显示时间的叠加表单:
1 - 将以下 class 添加到您的项目中,其中包含所需的本机方法:
using System;
using System.Runtime.InteropServices;
public class NativeMethods
{
public const int WS_EX_LAYERED = 0x80000;
public const int HTCAPTION = 0x02;
public const int WM_NCHITTEST = 0x84;
public const int ULW_ALPHA = 0x02;
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
public const int WS_EX_TRANSPARENT = 0x20;
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public POINT(int x, int y)
{ this.x = x; this.y = y; }
}
[StructLayout(LayoutKind.Sequential)]
public struct SIZE
{
public int cx;
public int cy;
public SIZE(int cx, int cy)
{ this.cx = cx; this.cy = cy; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
ref POINT pptDst, ref SIZE psize, IntPtr hdcSrc, ref POINT pprSrc,
int crKey, ref BLENDFUNCTION pblend, int dwFlags);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject(IntPtr hObject);
}
2 - 添加以下 class,它是 semi-transparent smooth-edge windows 形式的基础 class:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using static NativeMethods;
public class PerPixelAlphaForm : Form
{
public PerPixelAlphaForm()
{
this.FormBorderStyle = FormBorderStyle.None;
this.ShowInTaskbar = false;
this.TopMost = true;
}
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
if (!DesignMode)
createParams.ExStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
return createParams;
}
}
public void SelectBitmap(Bitmap bitmap, int opacity = 255)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ApplicationException(
"The bitmap must be 32bpp with alpha-channel.");
}
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr hOldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
hOldBitmap = SelectObject(memDc, hBitmap);
SIZE newSize = new SIZE(bitmap.Width, bitmap.Height);
POINT sourceLocation = new POINT(0, 0);
POINT newLocation = new POINT(this.Left, this.Top);
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = (byte)opacity;
blend.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(this.Handle, screenDc, ref newLocation,
ref newSize, memDc, ref sourceLocation, 0, ref blend, ULW_ALPHA);
}
finally
{
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
SelectObject(memDc, hOldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
}
}
3 - 然后添加以下 class 这是一个表格,有一个显示时间的计时器:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Windows.Forms;
public partial class Form1 : PerPixelAlphaForm
{
private IContainer components = null;
private Timer timer1;
private Bitmap image;
public Form1()
{
this.components = new Container();
this.timer1 = new Timer(this.components);
this.timer1.Enabled = true;
this.timer1.Interval = 500;
this.timer1.Tick += new EventHandler(this.timer1_Tick);
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(300, 300);
this.Size = new Size(800, 500);
this.image = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
}
private void timer1_Tick(object sender, EventArgs e)
{
using (var g = Graphics.FromImage(image))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.DrawString(DateTime.Now.ToString("HH:mm:ss"),
new Font(this.Font.FontFamily, 60, FontStyle.Bold), Brushes.Black,
ClientRectangle, StringFormat.GenericDefault);
SelectBitmap(image, 150);
}
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
if (disposing && image != null)
image.Dispose();
base.Dispose(disposing);
}
}
您可以在以下帖子中找到更多信息:
我想创建一个倒计时计时器,它显示在屏幕的右下角,带有稍微透明的文本,无论您在屏幕上有什么,都可以看到。想想当您的 windows 副本未激活时出现的 windows 未激活水印消息。它显示在右下角,覆盖所有 windows 并“卡在”屏幕上。
有没有办法通过程序来做到这一点? C# 首选。
到目前为止,在我的研究中,我只遇到了 Deskbands,它允许你在任务栏中放置一些东西,但不能放在任务栏之外。
注意: 下面的答案创建了一个正常的 semi-transparent 最上面的形状,边缘平滑。它并不完全像 windows 激活文本,例如它位于工具提示 windows 或菜单后面,但它位于其他 non-topmost windows.[=21= 之上]
您可以创建一个 Layered Window by setting WS_EX_LAYERED style, then you can assign a smooth-edge transparent region to the window. You can also set WS_EX_TRANSPARENT
for the window, then it will ignore the mouse event. Then to make it always on top set its TopMost
to true
. And finally if you want to make it semi-transparent use suitable Opacity
值。
例子
在下面的示例中,我创建了一个始终位于顶部并显示时间的叠加表单:
1 - 将以下 class 添加到您的项目中,其中包含所需的本机方法:
using System;
using System.Runtime.InteropServices;
public class NativeMethods
{
public const int WS_EX_LAYERED = 0x80000;
public const int HTCAPTION = 0x02;
public const int WM_NCHITTEST = 0x84;
public const int ULW_ALPHA = 0x02;
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
public const int WS_EX_TRANSPARENT = 0x20;
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public POINT(int x, int y)
{ this.x = x; this.y = y; }
}
[StructLayout(LayoutKind.Sequential)]
public struct SIZE
{
public int cx;
public int cy;
public SIZE(int cx, int cy)
{ this.cx = cx; this.cy = cy; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
ref POINT pptDst, ref SIZE psize, IntPtr hdcSrc, ref POINT pprSrc,
int crKey, ref BLENDFUNCTION pblend, int dwFlags);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject(IntPtr hObject);
}
2 - 添加以下 class,它是 semi-transparent smooth-edge windows 形式的基础 class:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using static NativeMethods;
public class PerPixelAlphaForm : Form
{
public PerPixelAlphaForm()
{
this.FormBorderStyle = FormBorderStyle.None;
this.ShowInTaskbar = false;
this.TopMost = true;
}
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
if (!DesignMode)
createParams.ExStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
return createParams;
}
}
public void SelectBitmap(Bitmap bitmap, int opacity = 255)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ApplicationException(
"The bitmap must be 32bpp with alpha-channel.");
}
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr hOldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
hOldBitmap = SelectObject(memDc, hBitmap);
SIZE newSize = new SIZE(bitmap.Width, bitmap.Height);
POINT sourceLocation = new POINT(0, 0);
POINT newLocation = new POINT(this.Left, this.Top);
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = (byte)opacity;
blend.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(this.Handle, screenDc, ref newLocation,
ref newSize, memDc, ref sourceLocation, 0, ref blend, ULW_ALPHA);
}
finally
{
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
SelectObject(memDc, hOldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
}
}
3 - 然后添加以下 class 这是一个表格,有一个显示时间的计时器:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Windows.Forms;
public partial class Form1 : PerPixelAlphaForm
{
private IContainer components = null;
private Timer timer1;
private Bitmap image;
public Form1()
{
this.components = new Container();
this.timer1 = new Timer(this.components);
this.timer1.Enabled = true;
this.timer1.Interval = 500;
this.timer1.Tick += new EventHandler(this.timer1_Tick);
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(300, 300);
this.Size = new Size(800, 500);
this.image = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
}
private void timer1_Tick(object sender, EventArgs e)
{
using (var g = Graphics.FromImage(image))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.DrawString(DateTime.Now.ToString("HH:mm:ss"),
new Font(this.Font.FontFamily, 60, FontStyle.Bold), Brushes.Black,
ClientRectangle, StringFormat.GenericDefault);
SelectBitmap(image, 150);
}
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
if (disposing && image != null)
image.Dispose();
base.Dispose(disposing);
}
}
您可以在以下帖子中找到更多信息: