Added a configurable font size and window width to the gadget.

This commit is contained in:
Michael Möller
2010-09-13 22:34:08 +00:00
parent 7752670742
commit 53cc1cc75a
5 changed files with 327 additions and 133 deletions
+29 -10
View File
@@ -76,16 +76,21 @@ namespace OpenHardwareMonitor.GUI {
}
}
protected virtual Size Size {
public virtual Size Size {
get {
return window.Size;
}
set {
if (window.Size != value) {
DisposeBuffer();
this.window.Size = value;
CreateBuffer();
}
set {
this.window.Size = value;
}
}
public event EventHandler SizeChanged {
add {
window.SizeChanged += value;
}
remove {
window.SizeChanged -= value;
}
}
@@ -98,12 +103,12 @@ namespace OpenHardwareMonitor.GUI {
}
}
public bool LockPosition {
public bool LockPositionAndSize {
get {
return window.LockPosition;
return window.LockPositionAndSize;
}
set {
window.LockPosition = value;
window.LockPositionAndSize = value;
}
}
@@ -125,6 +130,15 @@ namespace OpenHardwareMonitor.GUI {
}
}
public event HitTestEventHandler HitTest {
add {
window.HitTest += value;
}
remove {
window.HitTest -= value;
}
}
private void CreateBuffer() {
this.buffer = new Bitmap(window.Size.Width, window.Size.Height,
PixelFormat.Format32bppArgb);
@@ -160,6 +174,11 @@ namespace OpenHardwareMonitor.GUI {
}
public void Redraw() {
if (window.Size != buffer.Size) {
DisposeBuffer();
CreateBuffer();
}
OnPaint(new PaintEventArgs(graphics,
new Rectangle(Point.Empty, window.Size)));
window.Update(buffer);
+153 -74
View File
@@ -42,10 +42,11 @@ using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace OpenHardwareMonitor.GUI {
public class GadgetWindow : NativeWindow {
private bool visible = false;
private bool lockPosition = false;
private bool lockPositionAndSize = false;
private bool alwaysOnTop = false;
private byte opacity = 255;
private Point location = new Point(100, 100);
@@ -100,9 +101,9 @@ namespace OpenHardwareMonitor.GUI {
protected virtual CreateParams CreateParams {
get {
CreateParams cp = new CreateParams();
cp.Width = size.Width;
cp.Height = size.Height;
CreateParams cp = new CreateParams();
cp.Width = 4096;
cp.Height = 4096;
cp.X = location.X;
cp.Y = location.Y;
cp.ExStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW;
@@ -112,57 +113,92 @@ namespace OpenHardwareMonitor.GUI {
protected override void WndProc(ref Message message) {
switch (message.Msg) {
case WM_COMMAND:
// need to dispatch the message for the context menu
if (message.LParam == IntPtr.Zero)
commandDispatch.Invoke(null, new object[] {
message.WParam.ToInt32() & 0xFFFF });
break;
case WM_NCHITTEST:
// all pixels of the form belong to the caption
message.Result = HTCAPTION;
break;
case WM_NCLBUTTONDBLCLK:
message.Result = IntPtr.Zero; break;
case WM_NCRBUTTONDOWN:
message.Result = IntPtr.Zero; break;
case WM_NCRBUTTONUP:
if (contextMenu != null)
ShowContextMenu(new Point(
(int)((uint)message.LParam & 0xFFFF),
(int)(((uint)message.LParam >>16) & 0xFFFF)));
message.Result = IntPtr.Zero;
break;
case WM_WINDOWPOSCHANGING:
WindowPos wp = (WindowPos)Marshal.PtrToStructure(
message.LParam, typeof(WindowPos));
// add the nomove flag if position is locked
if (lockPosition)
wp.flags |= SWP_NOMOVE;
// prevent the window from leaving the screen
if ((wp.flags & SWP_NOMOVE) == 0) {
Rectangle rect = Screen.GetWorkingArea(new Point(wp.x, wp.y));
const int margin = 20;
wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin);
wp.x = Math.Min(wp.x, rect.Right - margin);
wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin);
wp.y = Math.Min(wp.y, rect.Bottom - margin);
// raise the event if location changed
if (location.X != wp.x || location.Y != wp.y) {
location = new Point(wp.x, wp.y);
if (LocationChanged != null)
LocationChanged(this, EventArgs.Empty);
case WM_COMMAND: {
// need to dispatch the message for the context menu
if (message.LParam == IntPtr.Zero)
commandDispatch.Invoke(null, new object[] {
message.WParam.ToInt32() & 0xFFFF });
} break;
case WM_NCHITTEST: {
message.Result = (IntPtr)HitResult.Caption;
if (HitTest != null) {
Point p = new Point(
(int)((uint)message.LParam & 0xFFFF) - location.X,
(int)(((uint)message.LParam >> 16) & 0xFFFF) - location.Y);
HitTestEventArgs e = new HitTestEventArgs(p, HitResult.Caption);
HitTest(this, e);
message.Result = (IntPtr)e.HitResult;
}
}
} break;
case WM_NCLBUTTONDBLCLK: {
message.Result = IntPtr.Zero;
} break;
case WM_NCRBUTTONDOWN: {
message.Result = IntPtr.Zero;
} break;
case WM_NCRBUTTONUP: {
if (contextMenu != null)
ShowContextMenu(new Point(
(int)((uint)message.LParam & 0xFFFF),
(int)(((uint)message.LParam >> 16) & 0xFFFF)));
message.Result = IntPtr.Zero;
} break;
case WM_WINDOWPOSCHANGING: {
WindowPos wp = (WindowPos)Marshal.PtrToStructure(
message.LParam, typeof(WindowPos));
if (!lockPositionAndSize) {
// prevent the window from leaving the screen
if ((wp.flags & SWP_NOMOVE) == 0) {
Rectangle rect = Screen.GetWorkingArea(new Point(wp.x, wp.y));
const int margin = 16;
wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin);
wp.x = Math.Min(wp.x, rect.Right - margin);
wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin);
wp.y = Math.Min(wp.y, rect.Bottom - margin);
}
Marshal.StructureToPtr(wp, message.LParam, false);
message.Result = IntPtr.Zero;
break;
default:
base.WndProc(ref message); break;
// update location and fire event
if ((wp.flags & SWP_NOMOVE) == 0) {
if (location.X != wp.x || location.Y != wp.y) {
location = new Point(wp.x, wp.y);
if (LocationChanged != null)
LocationChanged(this, EventArgs.Empty);
}
}
// update size and fire event
if ((wp.flags & SWP_NOSIZE) == 0) {
if (size.Width != wp.cx || size.Height != wp.cy) {
size = new Size(wp.cx, wp.cy);
if (SizeChanged != null)
SizeChanged(this, EventArgs.Empty);
}
}
// update the size of the layered window
if ((wp.flags & SWP_NOSIZE) == 0) {
NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero,
IntPtr.Zero, ref size, IntPtr.Zero, IntPtr.Zero, 0,
IntPtr.Zero, 0);
}
// update the position of the layered window
if ((wp.flags & SWP_NOMOVE) == 0) {
NativeMethods.SetWindowPos(Handle, IntPtr.Zero,
location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOZORDER | SWP_NOSENDCHANGING);
}
}
// do not forward any move or size messages
wp.flags |= SWP_NOSIZE | SWP_NOMOVE;
Marshal.StructureToPtr(wp, message.LParam, false);
message.Result = IntPtr.Zero;
} break;
default: {
base.WndProc(ref message);
} break;
}
}
@@ -185,20 +221,24 @@ namespace OpenHardwareMonitor.GUI {
newHBitmap = bitmap.GetHbitmap(Color.Black);
oldHBitmap = NativeMethods.SelectObject(memory, newHBitmap);
Size size = bitmap.Size;
Point pointSource = Point.Empty;
Point topPos = Location;
BlendFunction blend = CreateBlendFunction();
NativeMethods.UpdateLayeredWindow(Handle, screen, ref topPos,
NativeMethods.UpdateLayeredWindow(Handle, screen, IntPtr.Zero,
ref size, memory, ref pointSource, 0, ref blend, ULW_ALPHA);
} finally {
NativeMethods.ReleaseDC(IntPtr.Zero, screen);
// make sure the window is at the right location
NativeMethods.SetWindowPos(Handle, IntPtr.Zero,
location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOZORDER | SWP_NOSENDCHANGING);
} finally {
if (newHBitmap != IntPtr.Zero) {
NativeMethods.SelectObject(memory, oldHBitmap);
NativeMethods.DeleteObject(newHBitmap);
}
NativeMethods.DeleteDC(memory);
NativeMethods.ReleaseDC(IntPtr.Zero, screen);
}
}
@@ -237,13 +277,13 @@ namespace OpenHardwareMonitor.GUI {
}
}
// if locked, the window can not be moved
public bool LockPosition {
// if locked, the window can not be moved or resized
public bool LockPositionAndSize {
get {
return lockPosition;
return lockPositionAndSize;
}
set {
lockPosition = value;
lockPositionAndSize = value;
}
}
@@ -274,23 +314,29 @@ namespace OpenHardwareMonitor.GUI {
set {
if (size != value) {
size = value;
NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 0, 0, size.Width,
size.Height, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER |
SWP_NOSENDCHANGING);
NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
ref size, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, 0);
if (SizeChanged != null)
SizeChanged(this, EventArgs.Empty);
}
}
}
public event EventHandler SizeChanged;
public Point Location {
get {
return location;
}
set {
NativeMethods.SetWindowPos(Handle, IntPtr.Zero, value.X, value.Y, 0,
0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);
location = value;
if (LocationChanged != null)
LocationChanged(this, EventArgs.Empty);
if (location != value) {
location = value;
NativeMethods.SetWindowPos(Handle, IntPtr.Zero,
location.X, location.Y, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);
if (LocationChanged != null)
LocationChanged(this, EventArgs.Empty);
}
}
}
@@ -305,6 +351,8 @@ namespace OpenHardwareMonitor.GUI {
}
}
public event HitTestEventHandler HitTest;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct BlendFunction {
public byte BlendOp;
@@ -357,8 +405,6 @@ namespace OpenHardwareMonitor.GUI {
public const int TPM_RIGHTBUTTON = 0x0002;
public const int TPM_VERTICAL = 0x0040;
public readonly IntPtr HTCAPTION = (IntPtr)2;
private enum WindowAttribute : int {
DWMWA_NCRENDERING_ENABLED = 1,
DWMWA_NCRENDERING_POLICY,
@@ -380,10 +426,16 @@ namespace OpenHardwareMonitor.GUI {
private const string GDI = "gdi32.dll";
public const string DWMAPI = "dwmapi.dll";
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
IntPtr pptDst, ref Size psize, IntPtr hdcSrc, IntPtr pprSrc,
int crKey, IntPtr pblend, int dwFlags);
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc,
IntPtr pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc,
int crKey, ref BlendFunction pblend, int dwFlags);
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
@@ -425,4 +477,31 @@ namespace OpenHardwareMonitor.GUI {
WindowAttribute dwAttribute, ref bool pvAttribute, int cbAttribute);
}
}
public enum HitResult {
Transparent = -1,
Nowhere = 0,
Client = 1,
Caption = 2,
Left = 10,
Right = 11,
Top = 12,
TopLeft = 13,
TopRight = 14,
Bottom = 15,
BottomLeft = 16,
BottomRight = 17,
Border = 18
}
public delegate void HitTestEventHandler(object sender, HitTestEventArgs e);
public class HitTestEventArgs : EventArgs {
public HitTestEventArgs(Point location, HitResult hitResult) {
Location = location;
HitResult = hitResult;
}
public Point Location { get; private set; }
public HitResult HitResult { get; set; }
}
}
+122 -42
View File
@@ -49,13 +49,20 @@ namespace OpenHardwareMonitor.GUI {
private Image back = Utilities.EmbeddedResources.GetImage("gadget.png");
private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png");
private Image barblue = Utilities.EmbeddedResources.GetImage("barblue.png");
private const int topBorder = 4;
private const int bottomBorder = 6;
private const int topBorder = 6;
private const int bottomBorder = 7;
private const int leftBorder = 6;
private const int rightBorder = 6;
private const int iconSize = 11;
private const int hardwareLineHeight = 12;
private const int sensorLineHeight = 10;
private const int rightBorder = 7;
private float fontSize;
private int iconSize;
private int hardwareLineHeight;
private int sensorLineHeight;
private int rightMargin;
private int leftMargin;
private int topMargin;
private int bottomMargin;
private int progressWidth;
private IDictionary<IHardware, IList<ISensor>> sensors =
new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
@@ -63,11 +70,12 @@ namespace OpenHardwareMonitor.GUI {
private PersistentSettings settings;
private UserOption hardwareNames;
private UserOption alwaysOnTop;
private UserOption lockPosition;
private UserOption lockPositionAndSize;
private Font largeFont;
private Font smallFont;
private Brush darkWhite;
private StringFormat stringFormat;
private StringFormat trimStringFormat;
private StringFormat alignRightStringFormat;
@@ -77,18 +85,20 @@ namespace OpenHardwareMonitor.GUI {
this.unitManager = unitManager;
this.settings = settings;
computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
this.largeFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f,
FontStyle.Bold);
this.smallFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f);
this.darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
this.stringFormat = new StringFormat();
this.stringFormat.FormatFlags = StringFormatFlags.NoWrap;
this.trimStringFormat = new StringFormat();
this.trimStringFormat.Trimming = StringTrimming.EllipsisCharacter;
this.trimStringFormat.FormatFlags = StringFormatFlags.NoWrap;
this.alignRightStringFormat = new StringFormat();
this.alignRightStringFormat.Alignment = StringAlignment.Far;
this.alignRightStringFormat.FormatFlags = StringFormatFlags.NoWrap;
this.Location = new Point(
settings.GetValue("sensorGadget.Location.X", 100),
@@ -97,12 +107,37 @@ namespace OpenHardwareMonitor.GUI {
settings.SetValue("sensorGadget.Location.X", Location.X);
settings.SetValue("sensorGadget.Location.Y", Location.Y);
};
SetFontSize(settings.GetValue("sensorGadget.FontSize", 7.5f));
Resize(settings.GetValue("sensorGadget.Width", Size.Width));
ContextMenu contextMenu = new ContextMenu();
MenuItem hardwareNamesItem = new MenuItem("Hardware Names");
contextMenu.MenuItems.Add(hardwareNamesItem);
MenuItem fontSizeMenu = new MenuItem("Font Size");
for (int i = 0; i < 4; i++) {
float size;
string name;
switch (i) {
case 0: size = 6.5f; name = "Small"; break;
case 1: size = 7.5f; name = "Medium"; break;
case 2: size = 9f; name = "Large"; break;
case 3: size = 11f; name = "Very Large"; break;
default: throw new NotImplementedException();
}
MenuItem item = new MenuItem(name);
item.Checked = fontSize == size;
item.Click += delegate(object sender, EventArgs e) {
SetFontSize(size);
settings.SetValue("sensorGadget.FontSize", size);
foreach (MenuItem mi in fontSizeMenu.MenuItems)
mi.Checked = mi == item;
};
fontSizeMenu.MenuItems.Add(item);
}
contextMenu.MenuItems.Add(fontSizeMenu);
contextMenu.MenuItems.Add(new MenuItem("-"));
MenuItem lockItem = new MenuItem("Lock Position");
MenuItem lockItem = new MenuItem("Lock Position and Size");
contextMenu.MenuItems.Add(lockItem);
contextMenu.MenuItems.Add(new MenuItem("-"));
MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
@@ -128,7 +163,6 @@ namespace OpenHardwareMonitor.GUI {
hardwareNamesItem, settings);
hardwareNames.Changed += delegate(object sender, EventArgs e) {
Resize();
Redraw();
};
alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false,
@@ -136,13 +170,30 @@ namespace OpenHardwareMonitor.GUI {
alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
this.AlwaysOnTop = alwaysOnTop.Value;
};
lockPosition = new UserOption("sensorGadget.LockPosition", false,
lockItem, settings);
lockPosition.Changed += delegate(object sender, EventArgs e) {
this.LockPosition = lockPosition.Value;
lockPositionAndSize = new UserOption("sensorGadget.LockPositionAndSize",
false, lockItem, settings);
lockPositionAndSize.Changed += delegate(object sender, EventArgs e) {
this.LockPositionAndSize = lockPositionAndSize.Value;
};
Resize();
HitTest += delegate(object sender, HitTestEventArgs e) {
if (lockPositionAndSize.Value)
return;
if (e.Location.X < leftBorder) {
e.HitResult = HitResult.Left;
return;
}
if (e.Location.X > Size.Width - 1 - rightBorder) {
e.HitResult = HitResult.Right;
return;
}
};
SizeChanged += delegate(object sender, EventArgs e) {
settings.SetValue("sensorGadget.Width", Size.Width);
Redraw();
};
}
public override void Dispose() {
@@ -156,6 +207,9 @@ namespace OpenHardwareMonitor.GUI {
darkWhite.Dispose();
darkWhite = null;
stringFormat.Dispose();
stringFormat = null;
trimStringFormat.Dispose();
trimStringFormat = null;
@@ -228,7 +282,6 @@ namespace OpenHardwareMonitor.GUI {
new Identifier(sensor.Identifier, "gadget").ToString(), true);
Resize();
Redraw();
}
}
@@ -249,22 +302,45 @@ namespace OpenHardwareMonitor.GUI {
}
}
Resize();
Redraw();
}
private Font CreateFont(float size, FontStyle style) {
return new Font(SystemFonts.MessageBoxFont.FontFamily, size,
style);
}
private void SetFontSize(float size) {
fontSize = size;
largeFont = CreateFont(fontSize, FontStyle.Bold);
smallFont = CreateFont(fontSize, FontStyle.Regular);
iconSize = (int)Math.Round(1.5 * fontSize);
hardwareLineHeight = (int)Math.Round(1.66 * fontSize);
sensorLineHeight = (int)Math.Round(1.33 * fontSize);
leftMargin = leftBorder + (int)Math.Round(0.3 * fontSize);
rightMargin = rightBorder + (int)Math.Round(0.3 * fontSize);
topMargin = topBorder;
bottomMargin = bottomBorder + (int)Math.Round(0.3 * fontSize);
progressWidth = (int)Math.Round(5.3 * fontSize);
Resize((int)Math.Round(17.3 * fontSize));
}
private void Resize() {
int y = topBorder + 1;
Resize(this.Size.Width);
}
private void Resize(int width) {
int y = topMargin;
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
if (hardwareNames.Value) {
if (y > topBorder + 1)
y += 2;
if (y > topMargin)
y += hardwareLineHeight - sensorLineHeight;
y += hardwareLineHeight;
}
y += pair.Value.Count * sensorLineHeight;
}
y += bottomBorder + 3;
y += bottomMargin;
y = Math.Max(y, topBorder + bottomBorder + 10);
this.Size = new Size(130, y);
this.Size = new Size(width, y);
}
private void DrawBackground(Graphics g) {
@@ -318,26 +394,27 @@ namespace OpenHardwareMonitor.GUI {
int h = Size.Height;
g.Clear(Color.Transparent);
DrawBackground(g);
int x;
int y = topBorder + 1;
int y = topMargin;
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
if (hardwareNames.Value) {
if (y > topBorder + 1)
y += 2;
if (y > topMargin)
y += hardwareLineHeight - sensorLineHeight;
x = leftBorder + 1;
g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
new Rectangle(x, y + 1, iconSize, iconSize));
x += iconSize + 1;
g.DrawString(pair.Key.Name, largeFont, Brushes.White,
new Rectangle(x, y - 1, w - rightBorder - x, 15));
new Rectangle(x, y - 1, w - rightBorder - x, 0),
stringFormat);
y += hardwareLineHeight;
}
foreach (ISensor sensor in pair.Value) {
int restWidth;
int remainingWidth;
if (sensor.SensorType != SensorType.Load &&
sensor.SensorType != SensorType.Control)
@@ -370,24 +447,27 @@ namespace OpenHardwareMonitor.GUI {
formattedValue = string.Format(format, sensor.Value);
}
int rightMargin = 8;
g.DrawString(formattedValue, smallFont, darkWhite,
new RectangleF(-1, y - 1, w - rightMargin + 2, 15),
new RectangleF(-1, y - 1, w - rightMargin + 3, 0),
alignRightStringFormat);
restWidth = w - (int)Math.Floor(g.MeasureString(formattedValue,
remainingWidth = w - (int)Math.Floor(g.MeasureString(formattedValue,
smallFont, w, StringFormat.GenericTypographic).Width) -
rightMargin;
} else {
restWidth = 80;
DrawProgress(g, restWidth, y + 4, w - restWidth - 9, 6,
0.01f * sensor.Value.Value);
} else {
DrawProgress(g, w - progressWidth - rightMargin,
y + 4, progressWidth, 6, 0.01f * sensor.Value.Value);
remainingWidth = w - progressWidth - rightMargin;
}
int leftMargin = 8;
g.DrawString(sensor.Name, smallFont, darkWhite,
new RectangleF(leftMargin - 1, y - 1, restWidth - leftMargin + 2,
15), trimStringFormat);
remainingWidth -= leftMargin + 2;
if (remainingWidth > 0) {
g.DrawString(sensor.Name, smallFont, darkWhite,
new RectangleF(leftMargin - 1, y - 1, remainingWidth, 0),
trimStringFormat);
}
y += sensorLineHeight;
}