Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // FloatingTextNotifier.cs
- // .NET Framework 4.x, WinForms, C# 5-compatible (no C# 6 syntax)
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Text;
- using System.Windows.Forms;
- namespace FloatingTextNotifier
- {
- static class Program
- {
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new TrayAppContext());
- }
- }
- internal sealed class TrayAppContext : ApplicationContext
- {
- private const string TextFilePath = @"C:\texts.txt";
- private readonly NotifyIcon _notifyIcon;
- private readonly ContextMenuStrip _menu;
- private readonly ToolStripMenuItem _showItem;
- private readonly ToolStripMenuItem _exitItem;
- private readonly FloatingTextForm _form;
- private readonly Timer _hourTimer;
- private readonly Random _rng = new Random();
- public TrayAppContext()
- {
- _form = new FloatingTextForm();
- _form.RequestHide += (s, e) => _form.Hide();
- _showItem = new ToolStripMenuItem("Показать текст", null, (s, e) => ShowNewText());
- _exitItem = new ToolStripMenuItem("Выход", null, (s, e) => ExitApp());
- _menu = new ContextMenuStrip();
- _menu.Items.AddRange(new ToolStripItem[] { _showItem, new ToolStripSeparator(), _exitItem });
- _notifyIcon = new NotifyIcon
- {
- Text = "FloatingTextNotifier",
- Icon = SystemIcons.Information,
- Visible = true,
- ContextMenuStrip = _menu
- };
- _notifyIcon.MouseUp += NotifyIcon_MouseUp;
- _hourTimer = new Timer();
- _hourTimer.Tick += (s, e) =>
- {
- _hourTimer.Stop();
- ShowNewText();
- ScheduleNextHour();
- };
- // Требование: сразу при запуске показать текст
- ShowNewText();
- // Требование: далее ровно в начале каждого часа
- ScheduleNextHour();
- }
- private void NotifyIcon_MouseUp(object sender, MouseEventArgs e)
- {
- if (e.Button == MouseButtons.Left)
- {
- ShowNewText();
- }
- else if (e.Button == MouseButtons.Right)
- {
- _menu.Show(Cursor.Position);
- }
- }
- private void ScheduleNextHour()
- {
- DateTime now = DateTime.Now;
- DateTime nextHour = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0).AddHours(1);
- TimeSpan due = nextHour - now;
- int ms = Math.Max(1, (int)due.TotalMilliseconds);
- _hourTimer.Interval = ms;
- _hourTimer.Start();
- }
- private void ShowNewText()
- {
- string text = LoadRandomLineOrError(TextFilePath);
- _form.SetText(text);
- _form.ShowInTopRight();
- }
- private string LoadRandomLineOrError(string path)
- {
- try
- {
- // Требование: читать файл полностью перед каждым показом, UTF-8
- string[] lines = File.ReadAllLines(path, Encoding.UTF8);
- List<string> candidates = new List<string>(lines.Length);
- for (int i = 0; i < lines.Length; i++)
- {
- string line = lines[i];
- if (!string.IsNullOrWhiteSpace(line))
- candidates.Add(line.Trim());
- }
- if (candidates.Count == 0)
- return "Ошибка: файл пуст или нет непустых строк.";
- int idx = _rng.Next(candidates.Count);
- return candidates[idx];
- }
- catch (Exception ex)
- {
- string msg = ex.Message ?? "Неизвестная ошибка.";
- if (msg.Length > 220) msg = msg.Substring(0, 220) + "...";
- return "Ошибка: " + msg;
- }
- }
- private void ExitApp()
- {
- _hourTimer.Stop();
- _hourTimer.Dispose();
- _notifyIcon.Visible = false;
- _notifyIcon.Dispose();
- if (!_form.IsDisposed)
- {
- _form.Hide();
- _form.Dispose();
- }
- ExitThread();
- }
- }
- internal sealed class FloatingTextForm : Form
- {
- public event EventHandler RequestHide;
- private readonly TextSurface _surface;
- public FloatingTextForm()
- {
- AutoScaleMode = AutoScaleMode.Dpi;
- Font = SystemFonts.MessageBoxFont;
- // Стиль окна: стандартное системное окно текущей темы, без кнопок
- FormBorderStyle = FormBorderStyle.FixedToolWindow;
- ControlBox = false;
- MinimizeBox = false;
- MaximizeBox = false;
- ShowIcon = false;
- ShowInTaskbar = false;
- TopMost = true;
- // Фиксированный размер
- ClientSize = new Size(360, 72);
- _surface = new TextSurface
- {
- Dock = DockStyle.Fill,
- Padding = new Padding(10),
- BackColor = SystemColors.Window,
- ForeColor = SystemColors.WindowText,
- Font = SystemFonts.MessageBoxFont
- };
- Controls.Add(_surface);
- // Требование: при клике по окну — скрыть
- this.Click += (s, e) => RaiseRequestHide();
- _surface.Click += (s, e) => RaiseRequestHide();
- }
- private void RaiseRequestHide()
- {
- EventHandler handler = RequestHide;
- if (handler != null) handler(this, EventArgs.Empty);
- }
- // (C# 5) вместо "=> true"
- protected override bool ShowWithoutActivation
- {
- get { return true; }
- }
- protected override CreateParams CreateParams
- {
- get
- {
- const int WS_EX_TOPMOST = 0x00000008;
- const int WS_EX_TOOLWINDOW = 0x00000080;
- const int WS_EX_NOACTIVATE = 0x08000000;
- CreateParams cp = base.CreateParams;
- cp.ExStyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
- return cp;
- }
- }
- public void SetText(string text)
- {
- _surface.TextToDraw = text ?? "";
- _surface.Invalidate();
- }
- public void ShowInTopRight()
- {
- PositionTopRight();
- if (!Visible) Show();
- else TopMost = true;
- }
- private void PositionTopRight()
- {
- Rectangle wa = Screen.PrimaryScreen.WorkingArea;
- int margin = ScaleByDpi(10);
- int x = wa.Right - Width - margin;
- int y = wa.Top + margin;
- Location = new Point(Math.Max(wa.Left, x), Math.Max(wa.Top, y));
- }
- private int ScaleByDpi(int px)
- {
- using (Graphics g = CreateGraphics())
- {
- return (int)Math.Round(px * (g.DpiX / 96.0));
- }
- }
- }
- internal sealed class TextSurface : Control
- {
- private string _textToDraw;
- // (C# 5) вместо "auto-property initializer"
- public string TextToDraw
- {
- get { return _textToDraw; }
- set { _textToDraw = value ?? ""; }
- }
- public TextSurface()
- {
- _textToDraw = "";
- SetStyle(ControlStyles.AllPaintingInWmPaint |
- ControlStyles.OptimizedDoubleBuffer |
- ControlStyles.ResizeRedraw |
- ControlStyles.UserPaint, true);
- TabStop = false;
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
- e.Graphics.Clear(BackColor);
- Rectangle rect = new Rectangle(
- Padding.Left,
- Padding.Top,
- Math.Max(0, ClientSize.Width - Padding.Horizontal),
- Math.Max(0, ClientSize.Height - Padding.Vertical)
- );
- TextRenderer.DrawText(
- e.Graphics,
- TextToDraw ?? "",
- Font,
- rect,
- ForeColor,
- TextFormatFlags.WordBreak |
- TextFormatFlags.EndEllipsis |
- TextFormatFlags.NoPrefix |
- TextFormatFlags.Left |
- TextFormatFlags.VerticalCenter
- );
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment