タミヤの『楽しい工作シリーズ No.227 カムロボット工作セット』と『IchigoJam』の組み合わせで動くサンプルプログラムを作ってみました。
プログラムを実行するとIchigoJamにつながっているキーボードがリモコンになり、キー入力をするとカムロボット(カムロボ)が動きます。
「KB4497934を適用するとレイアウトが崩れる?」の続きです。
検索キーワードが絞り込めたので、改めてインターネットを検索してみるとQiitaで@tfukumoriさんの記事が見つかりました。
『2019/4/26のWindows 新元号(令和)対応パッチでのフォント変更?での不具合調査(Windows 7, 10 1803, .NET, Excel)』 (https://qiita.com/tfukumori/items/a1fb3984a3488875515e)
@tfukumoriさんの記事を読んでいくと自分が遭遇している現象と同じようです。
自分の場合、KB4497934で現象が起きましたが、俗に「令和対応」と呼ばれるパッチがリリースされたあたりから発生しているようです。
さらに読み進めていくと、この現象を解決するための修正パッチが配布されているようです。
Windows Updateでの修正(5/15追記)
Windows Update 定例パッチ(Bリリース、アメリカ第2火曜日の翌日、日本では5/15)で修正されたようです。
えっ、自分の環境では解決できていない…
ページに書いてあった情報をヒントに試してみたところ、解決ができたので修正方法を以下に記載します。
「KB4497934を適用するとフォントの大きさが変わる?」でアップデートを適用するとフォントの大きさが変わるようだと記事を書きましたが、それ以外にも違いがあるようです。
差異を確認したのはVB .NETのSystem.Windows.Forms.Formクラスを継承したクラスでインスタンス生成時に発生するフォームのResizeイベントです。
具体的には、フォームのコンストラクタから呼び出されるInitializeComponentメソッドの実行中に発生するResizeイベントの発生回数が変わります。
Windows 10 Pro Version 1809 Build 17753.475
Visual Studio Professional 2017 Version 15.9.11
VB .NETを用いたWindows Formsアプリ
比べてみると、アップデート適用後の4回目のResizeイベントが発生したタイミングでフォームのレイアウトが崩れてしまっています。
調査のために使用したフォームでは145ピクセル相当の横ずれが生じているようです。
全体の幅が1000ピクセル強の中で145ピクセルのずれなので見た目的にはかなりの違和感があります。
4回目のResizeイベント発生自体はInitializeComponentメソッドのMe.ResumeLayoutメソッドを呼び出している部分をコメントアウトすることで抑制できます。
(かなり乱暴な方法ですが、ResumeLayoutの引数を変えるなどでは抑制できませんでした。)
しかし、Resizeイベントの発生を抑制した状態でも生成されたフォームを確認するとフォントの大きさが異なるためか、やはりレイアウトが崩れています。
全体的にフォントの横幅が狭まっているのか前詰め状態になっています。
Windows Updateで改善されるのを待つのが無難かもしれません。
InitializeComponentメソッドの変更ですが、ソースを確認すると以下のように変更をするなとコメントされている部分なので危険性を理解したうえで変更するようにしてください。
‘メモ: 以下のプロシージャは Windows フォーム デザイナで必要です。
‘Windows フォーム デザイナを使って変更できます。
‘コード エディタを使用して、変更しないでください。
※2019/05/30 14:00 「KB4497934を適用するとレイアウトが崩れる? [とりあえず解決]」にこの記事の続きを書きました。
Windows 10のWindows UpdateでKB4497934
(2019年5月21日リリース)を適用するとフォントの大きさが変わってしまうケースがあるようです。
この現象を確認しているのは、MS UIゴシックとMS Pゴシックの2種類です。
(Visual Studio Professional 2017 Version 15.9.11上でVB .NETを用いてWindows Formsアプリを開発しているときに発生)
掲載したサンプルはSystem.Windows.Forms.LabelとSystem.Windows.Forms.TextBoxを用いてフォントにMS UI ゴシックを指定して表示してみました。
このサンプルではわずか数ピクセル程度のずれですが、String.Drawing.GraphicsクラスのMeasureStringメソッドなどを用いて描画サイズを測りながら描画位置を調整するような処理を行うと、かなり大きくずれて表示されます。
守秘義務の都合上公開はできないのですが作業中のプロジェクトではドン引きするくらいに画面が崩れています。
KB4497934のリリース文でフォントや描画に関する言及はありませんが、KB4494441 (2019年5月14日リリース)のリリース文に以下のような説明があります。
Microsoft Excel で、MS UI Gothic または MS PGothic フォントを使用しているときに、テキスト、レイアウト、またはセルのサイズの幅が予想よりも狭く、または広くなることがある問題を修正します。
また、インターネットの情報を検索すると令和対応のあたりから表示崩れの報告が散見されるようです。KB4497934でもなんらかの影響を受けているのかもしれないですね。
とりあえずKB4497934をアンインストールすると、見た目上は以前の描画に戻るようです。
※2019/05/30 0:40 「KB4497934を適用するとレイアウトが崩れる?」にこの記事の続きを書きました。
VB6のUpDownコントロールのように、Valueプロパティの値がMinimumプロパティの値より小さい値になったらMaximumプロパティの値に、Valueプロパティの値がMaximumプロパティの値より大きい値になったらMinimumプロパティの値に折り返すNumericUpDownコントロールです。
UpDownコントロールのWarpプロパティをONにした際の挙動のみを拡張しているので、それ以外の部分は必要に応じて実装してください。
' This software is distributed under the license of NYSL. ' ( http://www.kmonos.net/nysl/ ) ''' <summary> ''' VB6のUpDownのように値の折り返しに対応したNumericUpDown ''' </summary> Public Class WrapNumericUpDown Inherits NumericUpDown Private _wrap As Boolean = False Private _minimum As Decimal Private _maximum As Decimal ''' <summary> ''' 最小値 ''' </summary> ''' <returns></returns> Public Shadows Property Minimum As Decimal Get Return _minimum End Get Set(value As Decimal) _minimum = value MyBase.Minimum = value - 1 End Set End Property ''' <summary> ''' 最大値 ''' </summary> ''' <returns></returns> Public Shadows Property Maximum As Decimal Get Return _maximum End Get Set(value As Decimal) _maximum = value MyBase.Maximum = value + 1 End Set End Property ''' <summary> ''' 折り返しフラグ ''' Trueの場合、Valueプロパティの値がMinimumプロパティの値より小さい値になったらMaximumプロパティの値に、Valueプロパティの値がMaximumプロパティの値より大きい値になったらMinimumプロパティの値に調整 ''' </summary> ''' <returns></returns> Public Property Wrap As Boolean Get Return _wrap End Get Set(value As Boolean) _wrap = value End Set End Property ''' <summary> ''' ''' </summary> ''' <param name="e"></param> Protected Overrides Sub OnValueChanged(e As EventArgs) If _wrap Then If Me.Value <= MyBase.Minimum Then Me.Value = Me.Maximum ElseIf Me.Value >= MyBase.Maximum Then Me.Value = Me.Minimum End If Else If Me.Value < Me.Minimum Then Me.Value = Me.Minimum ElseIf Me.Value > Me.Maximum Then Me.Value = Me.Maximum End If End If MyBase.OnValueChanged(e) End Sub End Class
VB6を起動したところ、『Visual Studio 2005 Premier Partner Edition』のセットアップディスクを求められました。
自分で明示的にインストールした記憶がないので、何かに付帯してインストールされてしまったのではないかと考え、手元に該当するメディアも無いことだし、とりあえずセットアップ要求をスキップしようとしたのですが、キャンセルボタンを押しても「取消中」と表示されたまま先に進まなくなってしまいました。
そのような現象が発生したときに取った解決手順です。
※Visual Studio 2005 Premier Partner Editionは、SQL Serverの関連製品をインストールすると入ってしまうという情報が検索で引っかかりました。たしかに動作確認用にSQL Server 2005と関連ツールがインストールされています。
でも、最近までセットアップディスクの要求はなかったはずなんですよね、謎です。
VB .NETからWSL(Windows Subsystem for Linux)を起動しLinuxコマンドを実行、標準出力に出力された内容を.NET側で受け取りコンソールに出力するサンプルプログラムです。
サンプルプログラムはLinuxのPSコマンドを実行し、標準出力の内容を逐次読み込むパターンとイベントハンドラを用いて非同期に読み込むパターンの2つを用意しました。
BackgroundWorkerなどと組み合わせると長時間実行するLinuxコマンドから出力される内容を.NET側で受け取りGUIに進行状況を表示しながら実行することもできます。
' This software is distributed under the license of NYSL. ' ( http://www.kmonos.net/nysl/ ) ''' ''' <summary> ''' WSL上でLinuxコマンドを実行し、標準出力に出力された内容をコンソールへ出力 ''' </summary> Public Shared Sub InvokeWslCommand() Dim psi As New ProcessStartInfo() ' WSLのディストリビューション(ubuntu、ubuntu1804など) psi.FileName = "ubuntu1804" ' WSL上で実行するコマンド(実行したい部分をダブルクオーテーションで囲む) psi.Arguments = "run ""ps -aux""" ' リダイレクト設定(標準出力のみをリダイレクト) psi.RedirectStandardInput = False psi.RedirectStandardOutput = True psi.RedirectStandardError = False ' シェル使用せず、ウィンドウ表示なし psi.UseShellExecute = False psi.CreateNoWindow = True ' WSLプロセスを起動 Using p = Process.Start(psi) ' 標準出力に出力される内容を読み取り Dim reader = p.StandardOutput Do Until reader.EndOfStream Dim line = reader.ReadLine Console.WriteLine(line) Loop ' プロセスの終了待ち p.WaitForExit() ' 終了コードを出力 Console.WriteLine("exit-code=" & p.ExitCode) End Using End Sub
' This software is distributed under the license of NYSL. ' ( http://www.kmonos.net/nysl/ ) ''' ''' <summary> ''' WSL上でLinuxコマンドを実行し、標準出力に出力された内容をコンソールへ出力(非同期版) ''' </summary> Public Shared InvokeWslCommandAsync() Dim psi As New ProcessStartInfo() ' WSLのディストリビューション(ubuntu、ubuntu1804など) psi.FileName = "ubuntu1804" ' WSL上で実行するコマンド(実行したい部分をダブルクオーテーションで囲む) psi.Arguments = "run ""ps -aux""" ' リダイレクト設定(標準出力のみをリダイレクト) psi.RedirectStandardInput = False psi.RedirectStandardOutput = True psi.RedirectStandardError = False ' シェル使用せず、ウィンドウ表示なし psi.UseShellExecute = False psi.CreateNoWindow = True ' WSLプロセスを起動 Using p = Process.Start(psi) ' 出力を受け取った時のハンドラを設定 AddHandler p.OutputDataReceived, Sub(sender As Object, e As DataReceivedEventArgs) Console.WriteLine(e.Data) End Sub ' 非同期読み込み開始 p.BeginOutputReadLine() ' プロセスの終了待ち p.WaitForExit() ' 非同期読み込みをキャンセル p.CancelOutputRead() ' 終了コードを出力 Console.WriteLine("exit-code=" & p.ExitCode) End Using End Sub
Windowsのパス表現(例: C:\data\ )とWSLのパス表現(例: /mnt/c/data )を変換するための方法として、WSL側にはwslpathコマンドがサポートされていますがWindows側 .NETのライブラリでは簡単に変換できる方法がないようです。
WSL環境のwslpathコマンドを呼び出しパス表現の変換を行うための関数を作成しました。
' This software is distributed under the license of NYSL. ' ( http://www.kmonos.net/nysl/ ) ''' <summary> ''' Windowsのパス表現からWSLのパス表現に変換する ''' </summary> ''' <param name="distro">ディストリビューションの起動コマンド(ubuntu、ubuntu1804など)</param> ''' <param name="windowsPath">Windowsのパス</param> ''' <returns>WSLのパス</returns> Public Shared Function ToWslPath(distro As String, windowsPath As String) As String Dim psi As New ProcessStartInfo() psi.FileName = distro psi.Arguments = "run ""wslpath '" & windowsPath.Replace("\", "/") & "'""" psi.RedirectStandardOutput = True psi.UseShellExecute = False psi.CreateNoWindow = True Dim p = Process.Start(psi) Dim wslPath = p.StandardOutput.ReadLine p.WaitForExit() Return wslPath End Function ''' <summary> ''' WSLのパス表現からWindowsのパス表現に変換する ''' </summary> ''' <param name="distro">ディストリビューションの起動コマンド(ubuntu、ubuntu1804など)</param> ''' <param name="wslPath">WSLのパス</param> ''' <param name="slash">Trueの場合セパレータが"/"、Falseの場合セパレータが"\"</param> ''' <returns>Windowsのパス</returns> Public Shared Function ToWindowsPath(distro As String, wslPath As String, Optional slash As Boolean = False) As String Dim psi As New ProcessStartInfo() psi.FileName = distro psi.Arguments = "run ""wslpath " & If(slash, "-m", "-w") & " '" & wslPath & "'""" psi.RedirectStandardOutput = True psi.UseShellExecute = False psi.CreateNoWindow = False Dim p = Process.Start(psi) Dim windowsPath = p.StandardOutput.ReadLine p.WaitForExit() Return windowsPath End Function
PowerBuilderのソースファイル(.SRWファイルなど)からコントロールの定義とイベントハンドラを抽出するための正規表現です。
type\s{1,}(\S{1,})?([\s\S]*?)end\s{1,}type
event\s{1,}(\S{1,})?;([\s\S]*?)end\s{1,}event
$1にコントロール名またはハンドラ名、$2に本体部分が設定されます。
PowerBuilderライブラリファイル(.PBLファイル)から.SRW形式のソースファイルの作り方については、『PowerBuilderのソースファイルをテキスト形式で一括エクスポートするツール』をご覧ください。
PowerBuilderのソースファイル(.SRDファイル)からSQLを抽出するための正規表現です。
試した範囲ではデータソースとして設定されているSQL、PBSELECT(PowerBuilder独自のSQL)ともに抽出できています。
SQLの場合は、複数行にわたるSQLやダブルクォートで囲まれていても抽出ができることを確認しています。
retrieve=(\”[\s\S]*?^(\~\”)?\”|\”\s{0,}PBSELECT.*\”)retrieve=(\”[\s\S]*?(^(\~\”)?|[\s\w;])\”|\”\s{0,}(?!PBSELECT\s{0,})[\s\S]*?\”|\”\s{0,}PBSELECT.*\”)
※2019/01/22 12:30 抽出できないケースがあることが判明したので、正規表現を修正しました。
PowerBuilderライブラリファイル(.PBLファイル)から.SRD形式のソースファイルの作り方については、『PowerBuilderのソースファイルをテキスト形式で一括エクスポートするツール』をご覧ください。