-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathFloatingForm.cs
More file actions
194 lines (164 loc) · 7.46 KB
/
FloatingForm.cs
File metadata and controls
194 lines (164 loc) · 7.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
using System;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace OmenSuperHub {
public partial class FloatingForm : Form {
private PictureBox displayPictureBox;
public FloatingForm(string text, int textSize, string loc) {
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
this.ShowInTaskbar = false;
this.StartPosition = FormStartPosition.Manual;
displayPictureBox = new PictureBox();
displayPictureBox.BackColor = Color.Transparent;
displayPictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
ApplySupersampling(text, textSize);
if (loc == "left") {
SetPositionTopLeft();
} else {
SetPositionTopRight(textSize);
}
this.Controls.Add(displayPictureBox);
AdjustFormSize();
}
private void ApplySupersampling(string text, int textSize) {
// 参数校验,防止 textSize 无效导致 ArgumentException
if (string.IsNullOrEmpty(text) || textSize <= 0)
return;
string[] lines = text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
Bitmap newBitmap;
try {
newBitmap = new Bitmap(700, 300);
} catch (ArgumentException ex) {
System.Diagnostics.Debug.WriteLine($"Bitmap 创建失败: {ex.Message}");
return;
}
using (Graphics graphics = Graphics.FromImage(newBitmap)) {
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.Clear(Color.Transparent);
Color customColor = Color.FromArgb(255, 128, 0);
using (Font font = new Font("Calibri", textSize, FontStyle.Bold, GraphicsUnit.World)) {
using (Brush brush = new SolidBrush(Color.FromArgb(255, 128, 0))) {
graphics.DrawString(text, font, brush, new PointF(0, 0));
}
PointF point = new PointF(0, 0);
for (int i = 0; i < lines.Length; i++) {
string[] parts = lines[i].Split(':');
if (parts.Length > 1) {
string title = parts[0].Trim();
customColor = GetColorForTitle(title);
using (Brush brush = new SolidBrush(customColor)) {
for (int j = 1; j <= i; j++)
title = '\n' + title;
graphics.DrawString(title, font, brush, point);
}
}
}
}
}
// 先释放旧图像,再赋新值
var oldImage = displayPictureBox.Image;
displayPictureBox.Image = newBitmap;
displayPictureBox.Size = newBitmap.Size;
oldImage?.Dispose(); // Dispose 放在赋值之后,避免控件引用悬空
if (IsHandleCreated)
RenderLayered(newBitmap);
else
this.HandleCreated += (s, e) => RenderLayered(newBitmap);
}
private Color GetColorForTitle(string title) {
switch (title) {
case "CPU": return Color.FromArgb(0, 128, 192);
case "GPU": return Color.FromArgb(0, 128, 192);
case "Fan": return Color.FromArgb(0, 128, 64);
default: return Color.Black;
}
}
public void SetText(string text, int textSize, string loc) {
if (InvokeRequired) {
BeginInvoke(new Action(() => SetText(text, textSize, loc)));
return;
}
if (textSize <= 0) return;
ApplySupersampling(text, textSize);
AdjustFormSize();
if (loc == "left") {
SetPositionTopLeft();
} else {
SetPositionTopRight(textSize);
}
}
private void AdjustFormSize() {
// 根据Label的大小动态调整窗体大小
this.Size = new Size(displayPictureBox.Width + 20, displayPictureBox.Height + 20);
displayPictureBox.Location = new Point(10, 10);
}
protected override void OnMove(EventArgs e) {
base.OnMove(e);
if (displayPictureBox.Image is Bitmap bmp && IsHandleCreated)
RenderLayered(bmp);
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_LAYERED
| WS_EX_TRANSPARENT
| WS_EX_NOACTIVATE;
return cp;
}
}
public void SetPositionTopLeft() {
this.Location = new Point(10, 10);
}
public void SetPositionTopRight(int textSize) {
var screenWidth = Screen.PrimaryScreen.WorkingArea.Width;
this.Location = new Point((int)(screenWidth - textSize * screenWidth / 256 + 10), 10);
}
private void RenderLayered(Bitmap bitmap) {
if (bitmap == null) return;
IntPtr screenDC = GetDC(IntPtr.Zero);
IntPtr memDC = CreateCompatibleDC(screenDC);
IntPtr hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
IntPtr oldBitmap = SelectObject(memDC, hBitmap);
NativeSize size = new NativeSize(bitmap.Width, bitmap.Height);
NativePoint ptSrc = new NativePoint(0, 0);
NativePoint ptDst = new NativePoint(this.Left, this.Top);
BLENDFUNCTION blend = new BLENDFUNCTION {
BlendOp = AC_SRC_OVER,
BlendFlags = 0,
SourceConstantAlpha = 255,
AlphaFormat = AC_SRC_ALPHA
};
UpdateLayeredWindow(this.Handle, screenDC, ref ptDst, ref size,
memDC, ref ptSrc, 0, ref blend, ULW_ALPHA);
SelectObject(memDC, oldBitmap);
DeleteObject(hBitmap);
DeleteDC(memDC);
ReleaseDC(IntPtr.Zero, screenDC);
}
// ── 常量 ─────────────────────────────────────────────────────────────
private const int WS_EX_LAYERED = 0x80000;
private const int WS_EX_TRANSPARENT = 0x20;
private const int WS_EX_NOACTIVATE = 0x08000000;
private const int ULW_ALPHA = 0x02;
private const byte AC_SRC_OVER = 0x00;
private const byte AC_SRC_ALPHA = 0x01;
// ── 结构体 ───────────────────────────────────────────────────────────
[StructLayout(LayoutKind.Sequential)]
private struct NativeSize { public int cx, cy; public NativeSize(int x, int y) { cx = x; cy = y; } }
[StructLayout(LayoutKind.Sequential)]
private struct NativePoint { public int x, y; public NativePoint(int x, int y) { this.x = x; this.y = y; } }
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct BLENDFUNCTION { public byte BlendOp, BlendFlags, SourceConstantAlpha, AlphaFormat; }
// ── P/Invoke ─────────────────────────────────────────────────────────
[DllImport("user32.dll")] static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref NativePoint pptDst, ref NativeSize psize, IntPtr hdcSrc, ref NativePoint pptSrc, uint crKey, ref BLENDFUNCTION pblend, uint dwFlags);
[DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")] static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")] static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")] static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")] static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll")] static extern bool DeleteObject(IntPtr hObject);
}
}