// OpenTween - Client of Twitter // Copyright (c) 2013 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. #nullable enable using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace OpenTween { /// /// OpenTween で使用する全てのフォームの基底となるクラス /// public class OTBaseForm : Form { /// /// 全てのフォームで共通して使用する UI フォント /// /// /// SettingLocal.xml に FontUIGlobalStr 要素を追加する事で変更できます /// public static Font? GlobalFont { get; set; } /// /// デザイン時のスケールと現在のスケールの比 /// /// /// 例えば、デザイン時が 96 dpi (96.0, 96.0) で実行時が 120dpi (120.0, 120.0) の場合は 1.25, 1.25 が返ります /// public SizeF CurrentScaleFactor { get; private set; } private readonly SynchronizationContext synchronizationContext; protected OTBaseForm() { this.CurrentScaleFactor = new SizeF(1.0f, 1.0f); this.synchronizationContext = SynchronizationContext.Current; this.Load += (o, e) => { // デフォルトの UI フォントを変更 if (OTBaseForm.GlobalFont != null) this.Font = OTBaseForm.GlobalFont; }; } public Task InvokeAsync(Action x) => this.InvokeAsync(new Func(() => { x(); return 0; })); public Task InvokeAsync(Func x) => this.InvokeAsync(x).Unwrap(); public Task InvokeAsync(Func> x) => this.InvokeAsync>(x).Unwrap(); /// /// メソッドのTask版みたいなやつ /// public Task InvokeAsync(Func x) { var tcs = new TaskCompletionSource(); this.synchronizationContext.Post(_ => { try { var ret = x(); tcs.SetResult(ret); } catch (Exception ex) { tcs.SetException(ex); } }, null); return tcs.Task; } /// /// source で指定されたフォントのスタイルを維持しつつ GlobalFont に置き換えた Font を返します /// protected Font ReplaceToGlobalFont(Font source) { if (OTBaseForm.GlobalFont == null) return source; return new Font(OTBaseForm.GlobalFont.Name, source.Size, source.Style); } protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { base.ScaleControl(factor, specified); const float baseDpi = 96.0f; this.CurrentScaleFactor = new SizeF( this.CurrentAutoScaleDimensions.Width / baseDpi, this.CurrentAutoScaleDimensions.Height / baseDpi); } /// /// 標準の ListView のスケーリングでは不十分な処理を補います /// public static void ScaleChildControl(ListView listview, SizeF factor) { // カラム幅 foreach (ColumnHeader col in listview.Columns) { col.Width = ScaleBy(factor.Width, col.Width); } } /// /// 標準の VScrollBar のスケーリングでは不十分な処理を補います /// public static void ScaleChildControl(VScrollBar scrollBar, SizeF factor) => scrollBar.Width = ScaleBy(factor.Width, scrollBar.Width); /// /// 標準の ImageList のスケーリングでは不十分な処理を補います /// public static void ScaleChildControl(ImageList imageList, SizeF factor) => imageList.ImageSize = ScaleBy(factor, imageList.ImageSize); public static Size ScaleBy(SizeF factor, Size size) => Size.Round(new SizeF(size.Width * factor.Width, size.Height * factor.Height)); public static int ScaleBy(float factor, int size) => (int)Math.Round(size * factor); } }