HeyCHのブログ

慢性疲労のへいちゃんです

【C#】デスクトップメモを作ってみよう その1

今回は、Windowsフォームアプリケーションで作ったストップウォッチの時計部分をWPF化して、
ウィンドウではなく、時計だけが表示されるアプリケーションを作りたいと思っています。
また、時計を右クリックする事でメニューが表示され、付箋のようなメモをデスクトップに貼れるようにしたいと思います。

今回はその1という事で、WPF化した時計を透明ウィンドウにし、右クリックメニューを表示するところまでやってみたいと思います。

XAML

<Window x:Class="DesktopMemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DesktopMemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="120" Width="375"
        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent">
    <Grid>
        <TextBlock x:Name="label1" Text="{Binding Time}" FontSize="36" FontWeight="Bold">
            <TextBlock.Resources>
                <Style TargetType="TextBlock">
                    <Setter Property="Cursor" Value="Hand"/>
                </Style>
            </TextBlock.Resources>
        </TextBlock>
    </Grid>
    <Window.ContextMenu>
        <ContextMenu Name="_menu" StaysOpen="true">
            <MenuItem Header="フォント" Click="MenuItem_Click_1" />
            <MenuItem Header="カラー" Click="MenuItem_Click_2" />
            <Separator />
            <MenuItem Header="終了" Click="MenuItem_Click" />
        </ContextMenu>
    </Window.ContextMenu>
</Window>
  • 「WindowStyle="None"」「AllowsTransparency="True"」「Background="Transparent"」で透明Windowを実現できる。
  • 当然終了ボタンを用意しないと終了することができなくなるため、右クリックメニュー(ContextMenu)に用意してやる
  • ついでに時計のフォントと色を変更できるようにしてやる

コード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Forms;

namespace DesktopMemo {
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window {
        ViewModel vm = new ViewModel();
        public MainWindow() {
            InitializeComponent();
            this.DataContext = vm;

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += Bw_DoWork;
            bw.RunWorkerAsync();
        }

        private void Bw_DoWork(object sender, DoWorkEventArgs e) {
            while (true) {
                vm.OnoPropertyChanged("Time");
                System.Threading.Thread.Sleep(100);
            }
        }
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
            base.OnMouseLeftButtonDown(e);

            try {
                DragMove();
            } catch { }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e) {
            this.Close();
        }

        private void MenuItem_Click_1(object sender, RoutedEventArgs e) {
            FontDialog fd = new FontDialog();
            if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
                label1.FontFamily = new FontFamily(fd.Font.Name);
                label1.FontSize = fd.Font.Size * 96.0 / 72.0;
                label1.FontWeight = fd.Font.Bold ? FontWeights.Bold : FontWeights.Regular;
                label1.FontStyle = fd.Font.Italic ? FontStyles.Italic : FontStyles.Normal;
                TextDecorationCollection tdc = new TextDecorationCollection();
                if (fd.Font.Underline) tdc.Add(TextDecorations.Underline);
                if (fd.Font.Strikeout) tdc.Add(TextDecorations.Strikethrough);
                label1.TextDecorations = tdc;
                //Windowのサイズも変更してやる
                this.Width = label1.Width + 10;
                this.Height = label1.Height + 10;
            }
        }

        private void MenuItem_Click_2(object sender, RoutedEventArgs e) {
            ColorDialog cd = new ColorDialog();
            if (cd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
                label1.Foreground = new SolidColorBrush(Color.FromRgb(cd.Color.R, cd.Color.G, cd.Color.B));
            }
        }
    }

    public class ViewModel : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnoPropertyChanged(string propertyName) {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public string Time {
            get {
                return DateTime.Now.ToString("HH:mm:ss");
            }
        }
    }
}
  • protected override void OnMouseLeftButtonDownで左クリックしたとき移動できるようにしている。
  • FontDialog 、ColorDialog は両方ともWindows.Formsのを使用しているため、WPF用に変換してやる必要がある。
  • フォントサイズが変わった時はWindowよりも大きくなっている可能性があるため、サイズを変更してやる必要がある。

f:id:HeyCH:20200505003943p:plain