野鳥紀トップページへ 野鳥の写真集・総合目次へ 観察野鳥一覧表へ 制作メモのページへ ご案内のページへ 一シギ二タカ三ツグミへ移動 動画集「ビデオカメラと野鳥」のサイトへ移動

VisualStudioメモ

VisualStudioCommunity2019

(200506)フリーのVSをインストールしました。
事の始まりは、いつも使っているHSPで、テキストファイルの操作に11分かかる
スクリプトを作った事でした。
これではどうしようもないと思い、C言語か何か、コンパイラを探しました。
結局、VSに挑戦してみる事にしました。
色々かじってみたのですが、Cでは画面が作れない、C++は難しい、
という事で、現在、C#で右往左往しています。
以下は、極めて個人的なドタバタの記録です。
なお、先の11分の件、今は解決しています。
CやC#を調べていくうちに、HSPでの私のスクリプトの欠陥に気付きました。
改良した結果、HSPでも500ミリ秒で終わります。

210414
C#、フォルダのソート

下のメモと全く同じトラブルです。
忘れていました。
月初めに作ったフォルダに動画ファイルが残っていました。
動画は動画専用のフォルダに保存しています。
これを忘れていて、今日移動させました。
直前に、今日の写真をカメラから取り込みました。

HSPで作っているビューアはちゃんと最新のフォルダが表示されます。
ほぼ同じものをC#で作っています。
こちらの方は、動画を移動(削除)したフォルダが最新だと表示します。
原因は下のメモと同じで、削除するとそのフォルダの更新日時が変わるせいです。
忘れていました。
対策は泥縄ですが下に書いています。

ただ、この件、現在、サーバ移転がらみのFTPツールで問題にしています。
参考になりそうです。


210111
C#、フォルダのソート
C#でビューアを作って、使っています。
撮影してきた写真は、まず、日付け付きのフォルダに入れて作業を開始します。
ビューア起動時に、一番新しいフォルダを探して、そこを作業フォルダとしています。
つまり、今日撮ってきた写真の取捨選択をする訳です。

今日も同じ様に作業を始めようとしました。
ところが、何故か、最新のフォルダを開きません。
中途半端な日付のフォルダが選択されます。1月3日のフォルダです。今日は1月11日です。何度やっても同じです。

私のプログラムは、作業経過をクリップボードに転送して終了します。
プログラム作成時に、デバッグが簡単にできるように作ったものです。
完成した後も、この機能は残しています。実行速度に影響がない時の話です。

その経過を見ると、しっかり1/3のフォルダが一番あたらしいとされています。

この、C#で動かす前は、HSPでも同じ様なものを作っていました。
そのHSPでのビューアを動かしてみると、ちゃんと最新の今日の日付のフォルダが選択されます。
同じ様なアルゴリズムのはずです。困りました。

Array.Sortを使っています。いえ、どこかのページからコピーさせてもらったコード、を見よう見まねで使わせていただいています。
理屈が分かっていません、こういう時は困ります。

ここで、ひらめいた事があります。
HSPでは、なんと、サブフォルダのリストを取ると、一番新しいフォルダが先頭にリストされます。何もしていません。
で、結果オーライです。

C#でのソートは更新日時でソートするものだった。わざわざ、更新日時を指示しています。
Win10のエクスプローラでソートを更新日時にすると、1/3のフォルダが先頭に来ます。
ファイル名でソートするとちゃんと日付順の並びになります。日付込みでフォルダ名を作っていますので。

ここに至り、原因が分かりました。直前に手書きで削除したファイルがあるのです。1/3のフォルダの中のファイルでした。

つまり、削除するとそのフォルダの更新日時が変わるという事です。
対策も分かります。
新しいフォルダの中のファイルを一つ削除するといいのです。




201210
C#、サーバー移転に関して

先月末に思い切ってレンタルサーバーを移転しました。
移転作業、移転作業に伴うプログラム類の変更も、応急的な措置ですが、一段落しました。
これまで、サイトのページの追加や更新の作業は、HSPで作ったプログラムで大半仕上げていました。
本来は、これらのプログラムを移転に合わせて作り直す必要があります。
この経緯は、半自動化メモやサーバー移転の経緯メモに書いています。
結果的に、現在、HSPでマップファイルとRSSファイルの旧のURLを新しいURLに置換するプログラムを作って、定型化しています。

ただ、折角VSの環境があるので、これをC#で書き直そうと思います。
面倒なものではないはずです。
気を付ける所は文字コードぐらいだと高をくくっています。

下にメモしていたプロジェクトの作り方に関して、プロジェクト名とフォルダ名の関係を間違えていましたので、書き直します。
新しいプロジェクトの作成方法です。
Visual Studio 2019を起動します。
新しいプロジェクトの作成(N)を選びます。
次のページで、C#、Windows、デスクトップ、Windowsフォームアプリケーション、.netFramework、
を指定、選択します。
次のページで、プロジェクト名は、あらかじめ作っておいたフォルダ名を指定します。
場所は、そのフォルダの一つ上を指定します。
ここで、作っておいたフォルダを場所として指定すると、そのフォルダの下にフォルダが作られてしまいます。
もしくは、
場所にはフォルダを配置するフォルダを指定します。
フォルダ名にはそのプロジェクト名を指定します。(この場合はフォルダはプロジェクト名で作られます。)
結果、配置するフォルダ名\プロジェクト名\というフォルダにソリューションファイルが作られます。

まあ、この時点では、フォームだけがあって、コードは何も無い状態ですので、失敗したらフォルダごと削除してやり直す、です。


201114
.NET Framework、有効、無効
下でメモした.NET Frameworkのバージョンの事で、あれこれ試しました。
目的がエラー処理でしたので、.NET Frameworkを無効にしたり、有効にしたりが大変でした。
ネットには、.NET Frameworkはアンインストールは出来ない、無効にはできる、とあります。
プログラムと機能から処理します。

Win10では有効も無効も簡単に出来ました。
問題は、Win8.1でした。

まず無効化、
機能(Windowsの機能の有効化または無効化)には.NET Frameworkを含む項目が二つあります。
これをひとつずつ無効化しようとすると、失敗しました、となります。
物は試しと、二つ一緒に無効にすると、成功しました。

有効化、
今度は、二つ同時に有効化しようとすると失敗します。
そこで、一つずつ有効にすると、一つは成功、もうひとつが何回試しても失敗です。

困り果てた挙句、
何気なくWinUpdateを見てみました。オプションの更新に.NET Frameworkがらみの更新が二つありました。
これをインストールしました。
その後で、有効化を試すと、見事成功でした。

その後は、恐る恐るでしたが、もう一回試しました。
無効も有効も問題なく成功しました。

ただ、.NET Frameworkのバージョンは無効化しても変わりません。
regeditで調べるレジストリの数字です。
ですので、先のC#のプログラムは無効化しても動きます。エラーになりません。
無効化の状態で、正常に起動し正常に終了します。
中で、そのレジストリの数字を確認して、古いバージョンの場合はダイアログを出すようにしていますが、当然反応しません。

ただ無効にしただけで、アンインストールした訳ではないので、そうなのかもしれません。
そうなると、無効化の意味がよく分かりません。.NET Frameworkが使えなくなる、という事ではなさそうです。
実態は分かりません。


201114
C#、.NET Framework

Visual StudioのC#でプログラムを作っています。
その際、.NET Frameworkを利用しています。フォームを使いたいならコレ、みたいな解説がありました。
最初のプロジェクトの指定の所で、.NET Framework付きの物を選んでいます。

未だに、用語の使い方がよく分からないままです。
現在での理解は、.NET Frameworkとは、関数群で、プログラム上から簡単に利用できる物、
画面作成も.NET Frameworkがらみで、これがあると簡単にフォームが作れます。
いずれにしろ、良くは分からないながら、.NET Frameworkを使っています。
正確には、.NET Framework4.7.2です。

当選、出来上がったプログラムを使う際にも、これ以上のバージョンが必要になります。
VisualStudioを置いているWin10では、問題はありません。

PCにはマルチブートで幾つかのOSを入れてあります。
PCは新旧二つあります。
各々で試してみました。

まず、インストールされている.NET Frameworkを調べる方法です。
バージョンを調べる方法がMSのページに紹介されていました。
レジストリを調べ、
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\Release
にある数字が、
.NET Framework 4.5.1は、378675
.NET Framework 4.7.2は、461808
.NET Framework 4.8は、 528040
だそうです。

実際にregeditで見てみると、
新旧二つのPCのWin10は、528372
Win8.1は、一つが、528049、もう一つは、378675でした。
Win7では、528049でした。
WinXPでは分かりませんでした。レジストリに先の項目がありません。

さて、先のMSのページでは、378675はありますが、他の数字はありません。
違いは細かいバージョンアップのせいで、この数字より大きければいいのでしょう。

実際、動かないのは、378675だったWin8.1と、WinXPでした。
後は、全部正しく起動し、正しく終了しました。
XPの方は、32ビット版で対応していない、というようなメッセージが出ます。

問題は、378675だったWin8.1での挙動です。
実行ファイルは2か所に置いてあります。
一か所は、全く動きません。
起動すると、エラーダイアログだけが出ます。内容は英語で、意味は.NET Framework 4.7.2が必要だと書いてあるようです。
もう一か所の実行ファイルは、置いてあるフォルダが違うだけなのですが、起動はします。
しかし、途中や、終了時にエラーが出ます。

という事で、エラー処理ルーチンをセットしておいても損はなさそうです。
.NET Frameworkのバージョンを調べて、バージョン次第で終了する、だけです。
ただ、終了処理をスキップする必要がありました。
トラップしてある終了処理でエラーが出ているのです。
折角、その旨のダイアログを出して終了しようとしても、通常の終了処理へ飛ぶとエラー、では意味がありません。
そのまま終了する様にしないといけません。
それが、Environment.Exit(0)でした。強制終了です。



201023
C#、フォーム間のデータの受け渡し、自作ダイアログ
二つ目のフォームを作り、データを受け渡しする事について、調べました。
標準のMessageBoxが使いづらく、何か方法は無いかと調べて、フォームを使う方法があることを知りました。

フォームの追加は簡単です。
メニューだったか右クリックメニューだったかで追加できます。
新しいフォームの大きさを適当に決め、縦に二つの領域を作ります。
下に、ボタンを3個配置し、上にはpictureboxを配置します。
pictureboxの中にメッセージを表示する方法があります。これでフォントの大きさなども指定できます。

問題は、データの受け渡しです。
使うダイアログに応じて、メッセージの内容他幾つかのデータを渡さないといけません。
受け渡しの方法がネットに色々紹介されていますが、悲しいことに、どれもこれも今一よく理解できません。

そこで、勝手知ったるグローバル変数です。
C#にグローバル変数は無い、と書いてあります。ただ、それらしきものはある、との事です。
変数に、public staticを付けると、どこからでも読み書きできる、フォーム間でも同じ事、の様です。

ネットで調べ、更に試行錯誤を繰り返し、分かったことが幾つかあります。
ボタンのプロパティに、返り値をセットできるDialogResultがあります。
例えば、DialogResultをYesとすると、そのボタンを押すとYesを返してくれます。
ボタン名を「はい」としておけば、MessageBoxと変わりません。
しかも、MessageBoxと同じ様にフォームが終了し、呼び出し元へ帰ります。
返り値の受け取りも、MessageBoxと同じ要領です。

DialogResultをセットした状態で、ボタン名botton.Textを変えても問題ありません。
ボタン名に関係なく、設定したコードが帰ります。
ボタン自体を見えなくするbutton1.Visible、こともできます。

という事で、当初、ボタンの種類や数に応じて、幾つかのフォームを作る必要があるか、と考えていましたが、
工夫すると一つで済みそうです。
はい、いいえ、キャンセル、というボタンを作ってあるフォームで、
はいとキャンセルを非表示にして、いいえのボタン名をOKに書き換えると、OKボタンだけのダイアログになります。
このボタンで帰ると、Noが帰ってくるのでしょうが、受け取りませんので問題ありません。
Yes、Noだけで、キャンセルがいらないなら、3番目のボタンを非表示にすると済みます。

文字はフォーム一杯にpictureBoxを配置してその中に書き込みます。
一番必要なフォントの大きさも指定できます。
表示する文字数とか行数に応じて、呼び出し側のフォームからダイアログとして使うフォームのサイズと
表示領域RectangleFを指定します。
これをやらないと、表示する文字列が左や上に片寄ってしまいます。

フォーム2の表示位置を決めるために、元のフォームの中心座標も送ります。
まあ、呼び出し元の画面の真ん中に出すのが普通でしょう。

それでも、無駄な余白や偏りを出さない様に、多少の試行錯誤が必要です。
本来なら、表示する行数、文字数を調べて、必要なサイズを計算する、という事でしょうか。
結局、計算するにしても、同様に試行錯誤が必要です。であれば、その都度試しながら数値を決める方を選びました。

文字表示の領域とボタンの領域はsplitcountainerで分割して、ボタン領域を固定します。
こうしておくと、フォームを小さくした時もボタンが消えることはめったにありません。

右肩の閉じるボタンを表示させないcontrolboxことも出来ます。
ただ、このボタンが無いと、万一、作っていたボタンが全部見えなくなってしまった時、終了できません。
ダイアログを終了できないと呼び出し側も何もできません。(タスクバーの右クリックで何とかなるとは思いますが)
よくよく見てみると、普通のMessageBoxにも閉じるボタンは残してあります。
ここでもこのボタンは残すことにしました。

もう一つ、閉じるボタンで終了すると、戻り値はCancelです。

この作業の途中、先に書いたように、受け渡しするデータが多少多いので調べました。
分からないなりに構造体、という感じがしました。
すると、意味不明ながら、構造体よりclassの方がいいとあります。
見よう見まねで、public static class unnun{}、としました。
中の要素にもpublic staticを付けて宣言します。
中の要素に、配列も宣言できます。
こうすると、どちらのフォームからも見たり書き込んだりできます。できるようです。
ただ、表現が面倒で、ドットで並べていかないと行けません。
Form1.unnun.str[0] = "a"、という様な形になります。

と、ここに来て、引数での受け渡しと勘違いしている事に気付きました。
私の理解できる範囲でやります、これに関しては引数は使いません。
引数で受け渡すなら、構造体とかも便利なのでしょうが、単なるグローバル変数で強行突破です。
とすると、まとめる必要はありません。面倒なだけです。
ま、おかげさまで、構造体とかclass変数?とか勉強はしました。

201022
C#、フォルダの変更、ソリューション、プロジェクト、実行ファイル名の変更

作っているプログラム、写真ビューアですが、一応当初の予定通りで一段落しています。
これはこれで良いのですが、細かく見ると不満もあります。
ダイアログが小さくて不自由です。
調べてみると、別にもう一つのフォームを作り、加工して使う方法があるようです。
フォームを使うなら、フォントとか表示場所とか色とかも使えると想像しています。
これに取り掛かるにあたり、ここまでのプログラムは退避しておきたい、
新しい手法に失敗して、元に戻すような時、現時点の状態から再開させたい、という訳です。
バックアップはしますが、もっと確実な方は、現在の分は、そのまま残し、これから加工する分を新しいフォルダで始める。
こうしたい訳です。こうすると、確実に元に戻れます。
そこで、フォルダごとコピーした方を、フォルダ名やファイル名を変えて行きます。
以前、同じことを経験済みで、そのメモを見ながら進めました。

つまり、このメモは201009のメモの再確認です。
今回また、フォルダごとコピーして新しいプロジェクトにしました。前回のメモの通り実行して無事終わりました。
エラーも出ませんでしたので、まとめの部分を再掲、多少の追加です。

2回目のまとめ。
slnファイルのあるフォルダをフォルダごとコピーし、フォルダ名を変更予定の実行ファイル名に合わせて変更。
ここで、slnファイルを実行、VSを立ち上げます。
見慣れない画面(コードが見えません)で立ち上がりますが、アイコンやメニューから、すべて保存。デバッグ実行、またすべて保存。そして終了。
ちゃんと実行されます。

一息置いて、名前類を新しい名前(=新しいフォルダ名)に変更していきます。
sln起動、
ソリューションウインドウの右クリックメニューで、ソリューション名変更、プロジェクト名変更、
プロジェクト名の右クリックメニューにあるプロパティから、アセンブリ名変更、既定の名前空間変更、
コード画面で、namespaceの名前の右クリックから、名前の変更、
です。
全部、目的の実行ファイル名に変えます。

ことによると、この間、ひとつづつ変更するたびに、すべて保存、実行、すべて保存、終了を繰り返す方がいいのかもしれません。
今回、ソリューションウインドウだけは最初の起動から見えていました。
ですので名前の変更は簡単でしたが、最後のコードのnamespaceの名前が見えません。
表示メニューのコードを押しても、コードが出てきませんでした。
保存、終了、起動で見えるようになりました。



201020
C#、文字列補完式
文字列補完式、というものがあることを知りました。
ネットで、それとなく見てはいましたが、これほど便利だとは気付きませんでした。
textBox1.Text = $"{str}を{en]円";
これまでは、ToString()の嵐でした。
7000行ほどのコードに、調べてみたら、ToString()を170個使っていました。
逐次、メモを作る必要があって、数値をテキスト化するのに使っていました。
全部、この文字列補完式で代行できるのだと思います。


201018
C#、アイコンの変更

プログラム?アプリ?フォーム?ウィンドウ?に、独自のアイコンを使う方法を調べました。
アイコンファイルは、このサイトのトップページに組み込む時に作ってあり、それが使えました。
そこで、使えるアイコンは準備済として、フォームへ組み込む方法です。
フォームのプロパティにIconという項目があり、自分で作ったicoファイルを指定できました。
すると、フォームの右肩のアイコンが指定したものに変わります。
同時に、実行時のタスクバーのアイコンにも反映されます。

実行ファイルのアイコンは、ソリューションエクスプローラーのプロジェクト名のプロパティにアプリケーションというタブがあります。
そこで外部ファイルを指定できます。
エクスプローラーのファイル名の先頭に表示されるアイコンです。
実行ファイルと実行ファイルのショートカットにも反映されます。


201011
VS、ソリューションウインドウの位置変更
下のバックアップからの復元というかフォルダの変更というかの騒ぎで、何やら設定がリセットされるみたいで、ソリューションウインドウが右側に来ていました。
今まで、左側に置いてありました。最初から左だったか、初期の内に変更したか覚えていません。とにかく左に戻したいのです。
慣れればどちらでもいいのかも知れません。でも今までが左でしたので、何となく抵抗があります。それに勉強のつもりで探しまくりました。

メニューの中を探すと、設定のリセットとかウインドウレイアウトのリセットとかあります。
下のメモで、バックアップからの復元は出来るようになりましたので、気楽に試しました。
全く変わりません。いえ、レイアウト全体は見慣れないものに変わるのですが、肝心のソリューションエクスプローラーは必ず右側です。
この際、ヘルプは何の役にも立ちません。今までヘルプが役に立ったことは数えるほどもありません。
頼みのネットを探しても、簡単にできるとは書いてありますが、肝心のどうしたらいいのか書いてありません。いえ、見つけられません。

考えてみると、バックアップから戻しても、戻したのが現在の状態でした。
分からなければ、このままです。
半日ほど試行錯誤しました。
ネットだったか、ヘルプだったか、MSのページだったと思います。移動するには、Ctrl+ドラッグで移動、好きな場所にドロップ、みたいなことが書いてありました。
試しますが、左側でドロップしても右側に戻ってしまいます。
何度やっても同じです。

そのうちに、ドラッグ中に変なマークが出ることに気付きました。
しかも、Ctrl+ではなく、Ctrl無しの単にドラッグです。(当初はCtrl+だったように思うのですが)
サイコロの展開図みたいな模様が出ます。

その展開図の特定の位置にドラッグしたソリューションウインドウを持っていくと、画面の一部の色が変わる事に気付きました。偶然です。
色が変わるのは、その展開図の特定の位置にソリューションウインドウのタイトルバーを持って行ったときではなく、ドラッグ中のマウスカーソルが、その展開図に乗った時なのです。ここまで気付くのに何時間かけた事でしょうか。やはり偶然です。

要するに、そのサイコロの展開図みたいなものが、ソリューションウインドウの配置を示しているのです。
しかも、決定は、ウインドウをそこに乗せた時ではなく、ドラッグ中のマウスカーソルを乗せた時です。
左側に持っていきたいなら、展開図の左端の模様にマウスカーソルが乗ると、左端の、ちょうどソリューションウインドウぐらいの領域が青色に変わります。
その状態でマウスを離すと、めでたく左側に鎮座して頂けます。

幾つかリセットしたおかげでしょうか、画面がとてもシンプルになっています。
以前は、画面がいくつものブロックに分割されており、肝心のコードの編集領域はとても狭い物でした。
恐ろしいのは、そんなものだろうと思って、今まで続けていたことです。

コードは、まあ極端な話、数行もあればいいのですが、フォームのデザインが面倒です。
大きなフォームを作ろうとしても、大半の部分が隠れています。スクロールバーを操作しないと全体は見られません。
これが、だいぶ改善されると思います。
あれこれいじったおかげで、必要のない窓は、X、バッテンで消してしまえばいいのに気付きました。
復活は、そう面倒ではないことも分かりました。表示メニューにあります。

これからは、ソリューションウインドウとコードウインドウだけ出しておこうと思います。
フォームの編集の際は、そのソリューションウインドウも消してしまえば、ほぼ画面全部を使えます。


201009
C#、フォルダの変更、ソリューション、プロジェクト、実行ファイル名の変更

ビルドで排出される実行ファイル名を変えたくて、色々試しました。
もっとも、実行ファイル名は、ファイル名を直接変えても動きます。
ただまあ、何となく、実行ファイル名と同じフォルダ名、ソリューション名、プロジェクト名の方がいいのかな、と思っての事です。
後々、探すときに、面倒がありません。
単に、出来上がる実行ファイル名を変えるだけだったら、アセンブリ名という所を変更するといいと紹介されています。

以下、細かく試してはいません。単純な構造のおかげで、偶然、うまく行っているだけかも知れません。
普通に立ち上がります、ビルドもデバッグも正常です、ちゃんと実行できます。
結論は、フォルダ名もソリューション名も実行ファイル名も変えられました。

過去のメモを見直してみたら、ソリューションというのかプロジェクトなのか未だに分かりませんが、その全体を入れているフォルダを移すことは問題なさそうです。
作業中のものをフォルダごとコピーして、そのフォルダ名を変えて試しました。
ですので、訳が分からなくなったり、迷ったりした時はフォルダごと削除してやり直しです。

途中、一回だけエラーが出る事があります。
このエラーメッセージは、長いものですが、
ドキュメントはソリューションとして開かれているのでエディタで開けません。
というような内容でした。残念な事に、私には意味不明です。
ただ、エラーが出ても、いったんVSを閉じて、再起動するとちゃんと立ち上がります。

試行錯誤の結果、
普通にフォルダごとバックアップしたフォルダで、そのままslnファイルを実行すると、VSがちゃんと立ち上がります。
多少ですけど、起動に時間がかかっているようです。内部で何やら復旧作業をしている様に感じます。
VSは起動はしても、一見、コードが見えなくなったり、デザイナーが表示メニューから無くなっていたりします。
この場合でも、デバッグ実行させると、普通に実行できます。
コードやフォームは行方知れずのままです。私が探し出せていない、操作方法を知らない、という事のようです。
これは、タブをクリックしたり、ビルドしたり、VS自体を再起動したりしていく内に見えるようになりました。
とにかく、やたらと試しましたので、どれが効果があるのかよく分かりません。
一番効果的だったのは、保存してVSの再起動だったような気がします。

名前を変更した箇所は、ソリューションエクスプローラのソリューションとあるところです。
右クリックメニューから、名前を変更、です。
その下、プロジェクト名でしょうか、これも右クリックメニューに変更メニューがあるので変更しました。
更にプロパティから、アセンブリ名を変更しました。

アセンブリ名を変えると、ビルドで出来る実行ファイル名が変わります。古い名前の実行ファイルは無くなります。
と思ったのですが、不思議な事に、古い実行ファイルが残ることもあります。どういう場合に残るのか分かりません。
ただ、削除しても大丈夫です。debug、releaseのフォルダに古い実行ファイル名の付いたファイルが3個残っています。
この3個は日付が古いままで残っています。新しくビルドしても上書きされていませんので、区別は容易です。

このアセンブリ名の所に、既定の名前空間というボックスがあり、古い名前のままです。
名前空間というのは、よく出てくる単語ですが、私には全く意味不明です。
ここも変えてみました。何の影響もないようです。
これに関して、コードの先頭に、namespaceという単語があります。これと関連がありそうですが。
コードが、namespace旧ファイル名、となっていて変えたいものです。
変えていいようでしたので、右クリックメニューから新しいファイル名に変えてみました。異常ありません。
VSには、変数などの名前を変更する場合、右クリックメニューに一括で変更できる手段があります。便利なものです。
この効果はありました。画面に旧ファイル名.form1というタブがありましたが、これが新ファイル名に変わりました。

この後も、何度か試しました。エラーを出さない方法を調べる為です。
VSに何やら補完機能があるのか、あるいはしばらくプロセスが残るのか、と思ったからです。
ですので、出来るだけゆっくりやりました。
面倒ですが、逐次、立ち上げ、保存、実行、終了、を繰り返しました。どこが肝心なのか分からないので、やむを得ません。
結果、うまく行く時が多かったです。しかし、何度か試すと、やはり、先のメッセージが出ることもありました。
これは多分、急ぎすぎたか、何かの手順を抜かしたかだろうと思います。
逆に、メッセージが出ても、気にしないでいいという事にもなります。

もう一回まとめると、
slnファイルのあるフォルダをフォルダごとコピーし、フォルダ名を変更予定の実行ファイル名に合わせて変更。
ここで、slnファイルを実行、VSを立ち上げます。
見慣れない画面で立ち上がりましたが、アイコンから、すべて保存。デバッグ実行、またすべて保存。そして終了。
一息置いて、sln起動、ソリューション名変更、プロジェクト名変更、アセンブリ名変更です。名前空間変更、namespace変更、です。
全部、目的の実行ファイル名に変えました。
ことによると、この間、ひとつづつ変更するたびに、すべて保存、実行、すべて保存、終了を繰り返す方がいいのかもしれません。
逆かもしれませんが。
最終的に、あるいは、途中から、表示メニューにコードとデザイナーが出ていました。

もう一か所、変更する箇所がありました。
若干、暴走させたことがあって、恥ずかしながら、タスクマネージャーを開く機会がありました。
タスクマネジャーのファイル名が、元の変更前のファイル名のままでした。
これに関しては、参考になるような記事も見つけ出せません。

仕方なしに、あちこち探したら、前にアセンブリ名など変更した所、プロジェクト名のプロパティから入ってアプリケーションというタブです、
そこに、アセンブリ情報というボタンがあります。
クリックすると、タイトル、と、製品、という項目があり、そこに旧ファイル名が残っていました。
見た感じ、変えても構わないかな、という風に見えました。
恐る恐る、新しいファイル名に変更して、実行してみました。
タスクマネージャーを見てみたら、めでたく、新ファイル名に変わっていました。
この変更に関する影響については、全く見当もつきません。

(このメモの当初から、slnファイルをsinとしていました。見間違いです、全部修正しました。)

201011
ツールのオプションにあるフォントのサイズと、Ctrl+マウスホィールでの大きさ変更の関係が分かりました。
マウスで大きさを変えると窓の右下にサイズの%表示が出てくる。




201002
C#、フォルダ指定ダイアログ、commonOpenFileDialog、dllが必要だった
フォルダを指定する際のダイアログがあります。 よく紹介されているもので、FolderBrowserDialog、です。
簡単にダイアログを出せるので、これまで使っていましたが、多少の不満がありました。
小さいのです。
普通にエクスプローラみたいな感じで開けると、慣れた感じで、使いやすいのですけど。

探してみたら、commonOpenFileDialogというものがありました。
これが、使えるようにするのが多少面倒です。

コードをコピーしただけでは動きません。
以前、ゴミ箱へ移動する機能を追加した時と同じような手続きで、なにやら追加しないといけません。
意味は分かりませんが、NuGetパッケージを追加する、段取りを踏みます。
指定された通り実施すると動くようになりました。

これが、エクスプローラの感覚で使えて、しっくりきます。
左側にクイックアクセスも表示されます。

多少の不満は、デフォルトのフォルダが開いた状態で起動する事です。
そのまま決定でいいのですけど、下の段のフォルダが見えた状態ですので、ちょっと気になります。
仕方が無いので、デフォルトは前回指定のフォルダの一段上を指定する事にしています。

FolderBrowserDialogだと、前回と同じなら、ダイアログを開いて、決定、でよかったのですが、
上の変更のせいで、今回のものは、ダイアログを開いて、マウスでクリックが必要です。

201003追記
旧機で試したところ、commonOpenFileDialogが使えません。例外が発生します。
FolderBrowserDialogを使ったものも残してあり、そちらで試すと動きます。
Win102004です。Win8.1でも同様です。

原因が分かりました。
旧機で試すとき、実行フィルだけをコピーしていました。

古いバックアップのフォルダを移動している時、binフォルダの中のファイル数が違う事に気付きました。
commonOpenFileDialogを使い始めたバージョンから、binフォルダにdllやxmlファイルが4個ほど置いてあります。
Microsoft.WindowsAPICodePack云々というファイルです。
原因はこれでした。
フォルダごとコピーして使うと、めでたく新しいダイアログ使えます。
Win10の2004でもWin8.1でも同じです。


201002
C#、テキストボックスに連続で表示

下のメモで、フォルダのサイズ計算の際、場合によっては時間のかかるケースがあります。
そこで、途中経過の表示は難しいので、せめて作業前と作業完了後の表示をしようと考えました。

textBox1.Text = "計算中です・・・";
・・・
サイズ計算処理
・・・
textBox1.Text = "計算が終わりました";

この処理が数ミリ秒で終わることも、10数秒以上かかることもあります。
どのケースでも、計算が終わりました、しか表示されません。
どうやら、表示が早すぎて見えないのではなく、省略されているようです。

少し待たせるといいのかと、方法を探してみました。
await Task.Delay();を置いてみました。
即、エラーです。非同期がどうの、解説があります。意味不明です。

仕方が無いので、他を探しました。
textBox1.Refresh();を置けばいい、とありました。
これで、表示されるようになりました。




201001
C#、フォルダサイズ計算
フォルダのサイズ(容量?)を計算する方法を調べています。
ネットの記事によると、直接計算する方法はないので、
各フォルダの中のファイルのサイズを総当たりで計算していく、という方法が紹介されています。

幾つかコードが紹介されており、どれも同じにしか見えません。
この世界では常識なのでしょうね。どれも私の理解出来ない再帰を使ったものです。
仕方が無いので、丸写しで使わせていただいています。

何故か、ドライブ全体を計測する事は出来ません。ルートを指定すると例外が発生します。
残念ながら、その理由も分かりません。まあ、フォルダのサイズ、と書かれているので、そのようなものなのでしょう。

不思議な事に、同じフォルダを計測した時、計算時間が大きく変わります。
76GB、フォルダ数970、ファイル数7694のフォルダの計測に、
1回目、6016ミリ秒、2回目、75ミリ秒、です。
3回目以降も2回目と同様です。1回目だけが特別時間を要します。
計算結果はどれも同じです。フォルダのプロパティと同じ数字になります。
キャッシュでしょうか。それにしても効きすぎに思います。


200928
C#、ソート、Array.Reverse()

ソートで苦労しました。
理由は単純で、Array.Reverse()を降順でソートするものだろうと勘違いしていました。
正しくは、現在の配列を、ただ、逆さまに並び替えるだけのものです。
ですので、目的の配列が正しく並んでいないと、結果も正しくなりません。

20923でメモした事で、ファイルを更新日時でソート出来て、更にはフォルダも同じようにソートできる事が分かって、喜んでいました。
しかし、これには、細かく見ると問題がありました。
実際にソートした結果を日時と一緒に転記します、
DSC_1083.JPG:2020/09/24 木 12:46:18
DSC_1080.JPG:2020/09/24 木 12:46:18
DSC_1081.JPG:2020/09/24 木 12:46:18
DSC_1089.JPG:2020/09/24 木 12:46:20
DSC_1087.JPG:2020/09/24 木 12:46:20
DSC_1088.JPG:2020/09/24 木 12:46:20
となっています。
何度試しても同じ結果になります。

最近のカメラは、私のカメラでも1秒間に5,6枚は連写出来ます。
更新日時の表記は秒単位までです。撮影時間が秒までだと、同じ日時のファイルがいくつも出来ます。
そこで、時刻でソートすると、このような結果になるのでしょう。

本来は、まず、日時でソート、日時の同じものがあれば、ファイル名でソート、としたい所です。
エクセルなどではソートの優先順位をいくつか指定できます。
その方法がどこかに紹介されているといいのですが、見つけられませんでした。

でもまあ、実用上はあまり問題になりません。
撮影時間が同じ場合、つまり連写した時の写真は、どれもほぼ同じです。
つまり、同じ写真の並びが多少変わっても、さほど困った事ではなく、プログラムの結果がきれいではない、というだけです。

この問題、撮影時間が同じ場合、ソート後の並びが安定しない件、HSPでやっていた対策を思い出しました。
ファイルのリストを作る際、ファイルのフルパスと同時に更新日時も調べておきます。
そして、更新日時とフルパスを連結した文字列の配列を作ります。
更新日時+フルパス、という文字列の配列を作るのです。
この際、フルパスでなく、単にファイル名だけでもいいのですが、フォルダ内の一覧を作る際、受け取るのがフルパスです。
変換すのも面倒ですので、そのまま使います。
ファイル名だけにするのは、作業の最終段階で必要ですので、その時一回やれば済むことです。

具体的には、このような文字列になります。
2020/09/19 土 13:29:16D:\・・・\・・・\DSC_9998.JPG
単純に連結しただけです。実際には70文字ほどの文字列になりました。空白も漢字も\も入っています。
これをソートします。
すると、日時順できれいに並びます。
日時が同じ場合でもファイル名が繰り上がっているからです。
文字列の途中のフォルダ部分は、全部同じフォルダです、同じです。

そうそう、なぜ、こんな面倒な事をするかというと、私のカメラのファイル名は、9999の次が0001になるからです。
撮影した順番は、こうです。
DSC_9998.JPG
DSC_9999.JPG
DSC_0001.JPG
DSC_0002.JPG
DSC_0003.JPG

単純に、ファイル名でソートすすと、こうなります。
DSC_0001.JPG
DSC_0002.JPG
DSC_0003.JPG
DSC_9998.JPG
DSC_9999.JPG

これでは、後で撮影したものを先に見る事になります。抵抗があります。
で、ネットで発見した更新日時だけを使う方法は、最初の例のような事情が出て、若干の面台を残します。
もちろん、うまく行く場合が多いのですが、連写した時、日付が全部同じだったら、偶然、下のような結果になるケースが出てきます。
DSC_9998.JPG
DSC_0001.JPG
DSC_9999.JPG
DSC_0002.JPG
DSC_0003.JPG

そこで、強引に更新日時を連結した文字列でソートする方法を使いました。
最後にソートされたファイル名だけを取り出すのには、
System.IO.Path.GetFileName()を使います。
元の文字列に、日時が入っていようが、漢字の曜日が入っていようが、空白が入っていようが、関係ありません。
ファイル名だけ取り出せます。ありがたいことです。一番右側の¥だけを見ているようです。

ソートに要する時間は、1200枚の配列で実質70ミリ秒でした。70文字の文字列の配列が1200個の要素で、です。
いえ、当初、数秒かかっていました。
そこで、ソート時間を計測しようと思ってコードを見直したら、また冗長な事をしていました。
ソートのルーチン内にループが3つあります。
更新日時とフルパスの文字列の連結、
その文字列のソート結果表示、
ファイル名だけを取り出す、
です。
経過を記録するために、それぞれを書き出していました。
これを全部省略すると70ミリ秒で終わります。

この間、理解できない事が起こっています。
先の3個のループで結果書き出しをしていると、だんだん作業時間が増えていきます。

ボタンを作っていて、昇順と降順を入れ換える様にしています。
最初の入れ換えでは、1秒程度で終わります。
しかしながら、これを繰り返す度に所要時間が1秒程度ずつ増えていきます。
10回10秒ぐらいまで試しました。安定するような気配はありません。
各作業結果を入れる配列を作っているわけですが、これの入れ換えに時間がかかるのでしょうか。
だんだん増えるということは、作業の構造は全く分かりませんが、経過を記録する変数のリサイズが必要で、これに時間を食っているのでしょうか。
いずれにしろ、ソート結果は大丈夫と分かりましたので、途中経過を残す必要はありません。
全部省略すると、先の結果、1200ファイルで70ミリ秒程度で終わります。

途中、もう一つの問題に気付きました。
降順にソートした際、期待した結果にならなかった事です。
これは、最初に書いた通りで、
昇順のソートは、Array.Sort()で、
降順は、Array.Reverse()だろうと思い込んでいた事です。

正しくは、降順は
Array.Sort()をして、
Array.Reverse()を実行しないといけません。

この間違いが問題なるのは、ファイルの数字が9999から0001になる時だけです。
通常はファイルのリストを作る時、何もしないでもファイル名でソートされています。いるようです。
そこで、Array.Reverse()を使えば、降順に並ぶのです。
ファイル名に、9999と0001がある場合には、Array.Reverse()だけではうまくゆかず、Array.Sort()を先に実行しておかないといけません。



200927
C#、NET Framework4.8
C#で作っているビューアが、一応、予定した感じで動いているので、実際に色々と試しています。
何を試すのかというと、どこまでの環境で動くのか、という事です。
作っているのは、Win10proの1909です。ディルプレイは1920x1080です。
もちろん、動きます。

ディスプレイはもう一つ、1280x1024があります。
試してみました。これでも動きますが、表示する写真のサイズの縦横比が、1.5対1という関係で、とても小さく表示されてしまいます。
どこかでこの計算はしているはずです。横幅が1280だと、写真表示領域には900程度しか取れません。
これに合わせると、縦幅は、600ほどです。つまり、900x600ほどの表示になります。これ以上大きくしても無駄なのです。
この点、1920x1080のディスプレイだと1500x1000程度の表示になり、面積で比べると2.7倍程度になります。
画面割をこのディスプレイでしか考えていなかった結果でした。

さて、それでも、条件さえ合えば、動くには動きます。
結論は、NETFrameworkが必須、という事です。
VSでプロジェクトを作る時NETFrameworkを含んだものを選択しました。入っていなければ動かないのは当然のことでしょう。

試せるものの一つが、Win10の2004です。PCは古いのですが、動きます。
NET云々は最新版が入っています。
これは、何年か前までメインで使っていたもの(旧機)で、アプリ類も色々入ったままです。その関係でNET云々も残っているのでしょう。

Win8.1で試してみました。
現在のPC(現機)の方では起動すらしません。
ダイアログが出ます。英語なので断言はできませんが、どうやら、NETFrameworkの4.7.2が必要と書いてあるようです。
入れていません。アプリを何も入れていません。WinUpdateする以外に使っていませんので、やむを得ません。

旧機でwin8.1を残しているものがありますので、そちらで試しました。
実際に使っていたもので、NET云々もインストールしてあります。
試すと、起動はしますが、終了時にエラーを起こします。
メッセージは、「アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました云々」、です。
調べて見入ると、やはりNETFrameworkがらみの模様です。
そこで、何がインストールされているか調べてみました。
NETFrameworkの3.5でした。バージョンが古いという訳です。

新しいNETFrameworkを探しました。4.8がありました。
これをインストールすると、ようやく正常に動きます。

ただ、問題があります。
古いPCです。Core2Duo E8400を積んでいます。遅いのです。
表示する写真は、6144x4080で、10〜15MB程度のものです。
これを表示するのに、850ミリ秒程度かかっています。
これでは、使うのにちょっと抵抗があります。

現機の方は、Corei5_4690で、同じサイズの写真だと400ミリ秒程度です。
この程度なら、何とか使える範囲でしょう。我慢できる範囲です。

時間の計測には、System.Diagnostics.Stopwatchを使っています


200923
C#、フォルダ一覧の更新日時によるソート

現在の階層のフォルダのリストを作り、その中の一番新しいフォルダを選びたい、という段取りです。

フォルダのリストは、Directory.GetDirectories(@path)というファイルのリストを取るものと同じような形で取れます。
試してみると、この結果は、明記されていませんが、フォルダ名でソートされているようです。
文字の大きい方が下になって、結果の配列に入っています。
ですので、全部のフォルダ名が日付の数字で成り立っているなら、この状態でなんとかなります。
例えば、ここのメモの日付と同じ様に200923とかをフォルダ名にしておけば、リストでは一番下が最新のフォルダになります。

しかしながら、この際、一般的にフォルダの配列を更新日時でソートできないかと探してみました。
結果、見つけられませんでした。
そこで、以前調べたファイルのソートの関数が使えないかと思い立ち、試してみました。
使えます。全く同じように使えます。



200923
C#、一つ上のフォルダ名
タイトル通りです。
写真を置いているフォルダがあります。
最近はこれが深いのです。私の場合は、今、フォルダの階層が5個あります。フルパスには、\が6個あります。
年度別、月別、カメラ別、日付別、形式別、などで、
G:\A\B\C\D\E\F.jpg、こんな感じです。
このフォルダの一つ上のフォルダまでのパスを作りたい、という事です。

便利な関数、コマンド?があるものです。
末尾のファイル名だけ取り出す、
System.IO.Path.GetFileName(@path)

ファイル名を除くフォルダ部分を取り出す
System.IO.Path.GetDirectoryName(@path)

このフォルダ部分を取り出す関数が使えます。
要するに、これは、最下層がファイル名であれフォルダ名であれ、一段上までのパスを返してくれるものだ、
という記事がどこかに書いてあった記憶があり、恐る恐る試してみました。
フォルダだけのパスの場合、最下層のフォルダを除いてくれます。ファイル名であれフォルダ名であれ、一緒です。

一回呼び出すごとに、こんな感じになります。
G:\A\B\C\D
G:\A\B\C
G:\A\B

ただ、今回メモしたかったことは、末尾に\があるとうまく行かない、という事です。
\が末尾にあれば、その\だけを除いたパスが帰ります。

そこで、末尾の¥を削除しながら実行します。
これも、ありがたいことに、末尾の指定文字を削る関数があります。
if (path.EndsWith("\\") == true) path = fpath.TrimEnd('\\')
これを組み合わせることで、上の結果になります。

同じことをするのに、HSPには、パスを一つずつに分離するコマンドがありました。
これを使って、一段上のパスを作っていました。
探せばC#にもあるのかもしれません。




200923
C#、ファイル名のソート
ファイル名が入っている配列のソートが必要になりました。

写真のファイル名は連番になっています。
フォルダに入れた写真のファイルを取り出すと、ファイル名でソートされて帰ってくるようです。大きい方が下です。
つまり、普通にリストを作ると、新しいものが下になって並びます。
普通にはこれでいいのですが、私のカメラでは連番が9999の次が1に戻ります。
このケースが困ります。ファイル名でのソートでは新しいものが上になる事もあります。

そこで探しました。ファイル名の入ってる配列を更新日時でソートする関数です。
これを見つけて、使わせていただいています。
しかしながら、この構造が私にはよく分からず、結果、ソートされているからまあいいか、という物です。
あくまで私が理解できないだけです。

丸写しで恐縮ながら、以下、総武ソフトウェア推進所様のページから引用、です。
static int CompareLastWriteTime(string fileX, string fileY)
{
 return DateTime.Compare(File.GetLastWriteTime(fileX), File.GetLastWriteTime(fileY));
}

例えば、フォルダ内のファイルを表示する関数()
{
 ・・・
 ・・・
 Array.Sort(files, CompareLastWriteTime);
 ・・・
}

これで、filseの配列にファイルのフルパスを入れて呼ぶと、新しいファイルが下になって帰ってきます。
丁度、撮影した順番で見ることになります。
更新日時を使うと、連番が1に戻っても大丈夫です。

この時、もう一つ気がかりがありました。
逆順でソートする場合はどうするのか、という事です。
新しいものを先に見たい事もあります。
撮ってきた写真は、大体において、後ろの方に良い写真があります。
まあいいか、という程度のものが取れたら、撮影を終わりますので。

さて、どうしようかという時に、先の関数のxとyを入れ換えてみようと考えました。
何となく、ソートの順番を指定している様に思います。
結果、その通りでした。
逆の順番に表示されます。

新しいファイルが下に来るか上になるのかは、結果を見れば分かります。
しかしながら、これが巷に言う昇順なのか降順なのかが説明を見ても簡単には分かりません。
あちこち調べた結果、1,2,3と並べば昇順、3,2、1なら降順の様です。


200921
C#、描画領域へテキストボックスを置く

今作っている写真ビューアで、困っていた事がありました。
画面が足りないのです。

カメラで撮ってきた写真をPCに写します。
それを、全部チェックする必要があります。
無駄なものは残しておきたくないし、まあ多少写りの良かったものは、バックアップなり、別に整理しておきたいし、なのです。

具体的には、一つひとつ写真を見て、削除する、別のフォルダにコピーする、この作業を続けます。
大体はこの作業は、フリーのツールで、XnViewというものを使わせていただいており、とても重宝しています。
XnViewでは写真の編集が出来ます。もちろん、コピーや削除の作業も簡単です。とてもありがたいものです。

このほかに何が欲しかったかと言いますと、コピーです。
ワンキーでコピーが出来るとありがたいのです。
XnVeiwでも簡単にコピー出来ます。
ただ、同じフォルダにコピーするんだったら、コピー先をいちいち指定しなくてもいいではないか、と思います。
具体的な作業は、まず写真を見ます。すると、取るに足らない写真ですが、偶然、ピントだけは合っています。
そこで、別のフォルダにバックアップしよう、となった時、まずコピー先のフォルダを指定するダイアログを開きます。
私は、後日探しやすいように鳥種別、日付別に分類して保存しています。
XnViewでも、ワンキーと言いますか、Alt+Cですが、ダイアログを開けます。
ダイアログでは、前回コピー先がデフォルトで指定されていますので決定、するだけです。

ただ、そのコピー先も前回と同じなら、コピー先指定を省いてもいいではないか、という事です。
違うフォルダにコピーする時だけ、ダイアログを開くようにすると良い訳です。
写真数が数十枚、というなら別に考えません。
時々、1000枚、2000枚と撮ってくる時があります。こうなると、少しの手間が問題です。

という事で、当初、HSPで作ってみました。数年前の事です。
まあ、動いています。
これが今一なのです。何とか我慢できる速度ではありますが、やはり遅いのです。
それに、よく息をつきます。止まる時があります。ガベージコレクションでしょうか。よく分かりません。

そこで、これをC#で作ろうとしています。
一応、動くものが出来上がってはいます。
ただ、思ったよりは早くなりませんでした。HSPより気持ち早いかな、という程度です。
この速度の問題は改めて考える事にしています。

今は、機能を揃える事に苦労しています。
そこでの問題です。

写真を表示する領域は出来るだけ大きく取りたい。
ただ、補助的なデータで、同時に表示しておきたいものが沢山あります。
ついにその領域が無くなりました。

写真のサイズはどれでもほぼ同じで、1:1.5になっています。
これを、1920x1080のディスプレイに表示します。
ディスプレイの表示領域は、横はそのまま1920、縦はタスクバーやメニューバーにとられて、有効寸法は、1000ピクセルほどです。
タスクバーは残しておきたいのです。
この1920x1000に最大に表示すると、領域は、1000X1.5=1500、差し引き1920-1500=420で、横に420ピクセルほどの余裕が出ます。
実際は横幅にも必要な縦線があったり、完全に全画面にしたくない事情などがあって、残りは390ほどになります。
この390ピクセルに必要なボタンやボックスを作っていきます。

ボタンとかテキストボックスとかが作業が進むにつれ増えていき、領域が足りないという訳です。
ここで、HSPの事を思い出しました。
HSPでは、画像表示領域にも、ほぼ全面を使って、普段は見えないテキストボックスを複数配置しておき、必要な時だけ見えるようにしていました。
C#でも、見えないテキストボックスを作れる事は先日知りました。当然の事だったのでしょうね。
これで何とかなりそうだ、というお話でした。


200917
C#、listboxの選択されていないアイテム取得
listboxで選択されている項目?、アイテム?、を取得する方法はすぐ分かりました。(多数紹介されています。)
しかし、選択されていない項目を受け取りたい場合があり、この方法がなかなか分かりませんでした。(探し出せんでした。)

苦労して、ようやく分かりました。
最初の項目を受け取るには、listBox1.Items[0].ToString()です。以下同じです。

よくよく考えたら、必要なインデックスにまずフォーカスを当てて、その後取り出せばいい、という事にも気づきました。
最初の項目を受け取りないなら、istBox1.SelectedIndex = 0;として、listBox1.Textです。


200915
C#、キーイベント

プログラミングの過程で、当初は、マウスでのボタンクリックから作業を始める、という段取りで行きます。
最近の言語は、全部、そのようにボタン類から作業を始めるようになっているようです。

ただ、プログラムや作業の段取りが固まってくると、操作性の問題になります。
作業が単純で大量の処理が必要なものになると、マウス操作よりキーボードからの操作の方が簡単かつ素早く処理できます。
コードが高速に処理されるという事ではなく、実際の作業が簡単になる、という意味です。
そこで、マウスでボタンクリックから始まる作業を、キーイベントでも代替できるようにしていきます。

例えば、「下へ」というボタンが作ってあって、このボタンをクリックすると、次の写真を表示する、という動作をさせていた場合です。
キーイベントを拾うようにして、キーボードの下カーソルが押された事が分かれば、その「下へ」のボタンのルーチンへ飛ぶようにします。
同様にボタンとマウスで操作していた作業を、どれかのキーの押下げにも対応させ、結局、キーボードでほとんどの操作できるようにします。
こうすると、実際の作業の効率が格段に上がります。プログラムの処理速度の問題ではありません。

このキーイベントの事を色々調べました。
当初は、特殊キーの補足に関して、面倒そうな記事が多かったのですが、まず試してみることにしました。

最初に、フォームのKeyPreviewプロパティをTrueにしました。
これで、Form1_KeyDown等で、大半のキーは取得できました。

しかしながら、色々試すうち、この方法ではうまく行かないと気付きました。
多くの記事にある様に、ボタンにフォーカスがあると、まったく役に立ちません。ボタンにフォーカスがある状態で、上カーソルを押すと、上のボタンにフォーカスが移動するだけです。
下カーソルだと下のボタンに移動してしまいます。
つまり、プログラムでキーイベントを補足できない状態です。

試していく内に、解決策を見つけした。
何故か、フォーカスがボタンではなく、テキストボックスにある状態だと、キーコードを取得出来ます。
(想像ですが、テキストボックスでのイベントを作っていないからだろうと思います。)

そこで、当たり障りのないテキストボックスに常時フォーカスが行くようにします。
private void button1_Click()などのボタンのクリックを拾う関数の末尾に、例えば、
this.ActiveControl = this.textBox3、などと書いておけば、マウスでボタンを押しても、フォーカスはテキストボックスに飛びます。
面倒ですが、これをボタン全部に書きました。大変でした。
これで、キーコードが拾えない事はなくなりました。動作としては、こちらの意図通り動きます。

しかしながら、この状態で使っていく内に、再度の不備に気付きました。
そのフォーカスを集中させているテキストボックスの文字が反転してしまう場合があります。
反転したり、しなかったり、条件は分かりませんが、とても見苦しく、気になります。

解決策にたどり着きました。
フォーカスを集中させるためだけのテキストボックスを作りました。ダミーです。何も書込みません。
これを最小限の大きさにして、目につき難い所に置いておけばいいではないか、という事です。
これでもいいのですが、半信半疑で調べたら、テキストボックスは見えないように出来ます。
プロパティにvisibleというのがあって、falseにすると、実行時には見えません。
何のためにあるのでしょうかね。

そこで、全部のボタンの操作後に、ここにフォーカスを持っていくようにしました。
これで、めでたく、キーコードの取得がいつでも出来るようになりました。

まだ使い込んではいませんので、何か不備が出るかも知れません。

ただ、あと一つ、分からない事があります。
本当は、プログラム側でNumLockのON、OFFを操作する事が出来ると楽なのですが、その方法がよく分かりません。
ONの状態でもOFFの状態でも、それぞれコードは帰ってきます。
どちらのコードでも同じ動きをさせれば、実用上はなんとかなりそうに思います。



200913
C#、削除、ゴミ箱へ移動
ファイルの削除で悩みました。
単なる削除の方法はすぐ見つかります。
欲しいのは、即削除ではなく、ゴミ箱へ移動です。

苦労の末、これも何とか見つけ出しました。
using Microsoft.VisualBasic.FileIO
FileSystem.DeleteFile(@フルパス, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
だそうです。

ただ、これを移しても赤線が消えません。
マウスカーソルを赤線に乗せると、参照がどうのこうのというダイアログが出ます。

この意味が、ようやく分かりました。
いえ、意味は相変わらず不明ながら、対策は分かりました。

メニューから、プロジェクト、参照の追加、でリストが出ます。
その中の、Microsoft.VisualBasicにチェックを入れて、OK、で赤線が消えました。
実際に試すと、確かにゴミ箱へ入ります。



200911
C#、ディスプレイのサイズなど

相変わらず、写真ビューアを作ろうとしています。
その中で、フォームの縦横のサイズとかディスプレイのサイズとか調べる必要がありました。
このサイズ関係は、比較的簡単なコードで取得できます。

で、フォームを全画面で起動して、その結果は、

タスクバーをロックしていたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域のサイズ横:1920
フォームがある画面の作業領域のサイズ縦:1040
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1056

タスクバーを隠していたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域サイズ横:1920
フォームがある画面の作業領域サイズ縦:1080
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1096
という結果でした。


コントロールパネルなどで見たディスプレイの解像度は、1920x1080です。
見よう見まねで作ったコードに間違いが無いとして、実際には公称のサイズより若干の余裕がある様です。
具体的には、上下左右に8ピクセルずつ余分に作ってあることになります。



200901
C#、写真表示、拡大縮小、劣化
写真を表示する方法で苦労しています。
ここに来て、ようやく目途が立ちました。

方法は探せば探すほど出て来ます。星の数ほどあるように感じます。
その中で、自分の目的にあったものを探すのは大変な苦労です。
元々、系統的な知識のないままに始めたC#ですので。

やりたいことは、写真の表示と、その拡大縮小表示です。
まず、 pictureBox1.ImageLocation、という、これでいのかというほど簡単な方法がありました。
事前に、ドッキングとかZoomとかpictureBoxの設定がいくつか必要ですが、この一行で写真の表示ができます。
ただ、拡大縮小が思い通りに出来ません。もちろん、私が知らないだけだろうと思います。

そこで、次に、
Image.FromStream()、というものを試しました。
これもうまく行きません。
いえ、表示は簡単に出来ますが、拡大とか縮小とかする段階で、問題が出ます。
拡大縮小していく内に、画像が劣化していくのです。
縮小は良いのですが、次にそれを拡大すると劣化していきます。
縮小したものをそのまま拡大しているのだろうと思います。

更にいくつか試した挙句、
Graphics.DrawImageに行き当たりました。
これだと、引数で写真の表示位置とサイズを指定できます。
未だ完全に理解は出来ていませんが、目的に合いそうです。
いえ、この方法でも、同じ写真の縮小と拡大を続けると、当初は画像が劣化していって、実用上は使い物になりませんでした。
縮小までは良いのですが、それを拡大していくと、g画像が荒くなっていきます。
つまり、縮小表示した画像を単純に拡大しているだけだろうと思います。
本来は、まず読み込んだ画像をどこかのバッファに置いておき、実際に画面に表示する場合は、そのバッファから必要な分をコピーして持ってくる、という形が普通だと思います。

具体的には、ネットの記事の見よう見まねですが、
Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(canvas);
Image img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
img.Dispose();
g.Dispose();
pictureBox1.Image = canvas;
これで、一回限りなら、どんな大きさにも対応できます。

2回目以降、つまり、先に表示した画像を拡大とか縮小する場合はどうしたらいいのか考えました。
極端な話、毎回ファイルから読み込んで表示する覚悟なら、上のサイズ類の数字を書き直して使えば済みます。
しかしながら、それでは抵抗があります。
そこで、上のどれかが、いわゆるバッファ操作だろうと見当をつけ、試行錯誤で確かめました。
Dispose()の説明にリソースの開放、とかあります。バッファを消しているのだろうという個人的な解釈です。

まず、どの関数でも共通して使える様に、勝手知ったるグローバル的領域に、
Bitmap canvas;
Graphics g;
Image img;
を持っていきました。
このうちのどれか、あるいは全部がバッファの設定になっているのだろうという期待です。
グローバル的領域とは、
public partial class Form1 : Formの下です。
ここで定義した変数類は、何故かどの関数でも使えます。理由は分かりません。

エラーを大量に発生させながら試行錯誤していくと、
最初の読み込みルーチンは、
if (img != null) img.Dispose();
if (g != null) g.Dispose();
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でうまく行きました。
ここで、1、2行目のif文は、多分、こうしておかないと、写真が変わった時に、バッファ、リソース、メモリ?の類を消しておかないといけないのだろうという想像です。効果や影響は分かりません。
実行しながら、タスクマネージャーなどで、メモリの使用率などを見ていくと、想像していたようには動いていませんが、少なくとも、メモリを使いっぱなしにはなっていないようなので、これで良しとします。

次に、拡大縮小ルーチンは、
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でした。
こちらの1、2行目の、canvas=云々と、g=云々はこれが無いと、前の画像が消えません。何故かはわかりません。試行錯誤の結果です。


200830
C#、SplitContainer、PictureBox

画面を二つに分割する事で苦労しました。
最初に試したのは、TableLayoutPanelです。

本題から外れますが、
大文字小文字の使い方が面倒です。
ツールボックスでは、TableLayoutPanel、SplitContainer、です。
コードの中では、この頭文字が小文字になって、tableLayoutPanel、splitContainerと表記されます。
こういうものなのでしょうが、面倒です。
それに、どこかの時点で変更されたのでしょうか、例文などで、PictureBoxなどと書いてるものがあります。

さて、
写真のビューアを作ろうとして、画面を縦に二つに分割する方法を調べました。
右に諸元、左に写真を表示するという計画です。
一応、HSPでも作って使用していて、使用中の1920x1080のディスプレイに最適なコマ割りが、左側の幅を389ピクセル取ると、右側の写真領域の比率が丁度よくなるという事は計算済みです。

今使っている写真の大きさが、6144x4080と5568x3712の2種類です。
単純な比例計算で左側の幅を389ピクセルにすると、右側の縦横の比率が写真の比率と一致します。
つまり、普通に写真を表示した時に、縦横に隙間ができないのです。

とにかく、起動時に、全画面で起動した時、左側の領域を389ピくセルにする方法です。
まず、TableLayoutPanelというのがあることを知りました。
これの横線を0にすると、縦に二つに分割した画面が作れます。
これには、欠点が(私が知らないという意味です)、二つあり、
全画面をやめて窓表示にしても、縦の分割線に位置を変更できない事と、
左側に置いたボタンなどのコントロールの位置を指定できない事です。

そこで、次にSplitContainerというものを調べてきました。
これで、意図通りの画面が作れました。
Form1のWindowStateをMaximizedに、
splitContainer1のSplitterDistanseを389に、(ややこしいですが、これは、splitContainer1.Panel1ではありません。)
とすることで、所期の目的が達成されます。
全画面で起動しますが、窓にしても、左側は一応固定されています。しして、位置をずらしたければ、マウスでドラッグすると移動出来ます。



200828
C#、ボタン名、関数名

前回のフォームアプリで、ボタン名とそのイベントハンドラというのでしょうか、ボタンをクリックした時のコードを記述する関数の関数名が一致せず、困りました。
確か、コードの中で、button1.Enabled云々とある所で、右クリックメニューから名前を変更すると全部変わると思って、実行しました。
コードの部分は一括で変更できました。しかし、関数名が変わりませんでした。
ややこしい話で、以降はどこにそのボタンの関数があるのか分かりにくい状態になりました。関数名とそのボタン名とが違うのですから。
動きに関しては、意図した通りに動くので、問題はなかったのですが。

ようやく、正解が分かりました。変更する順番が大事です。
ボタン名とその関数名(イベントハンドラー?)の名前を合わせるには、まず、最初に、ボタンのプロパティでnameプロパティを変更しないといけません。
その後で、ボタンをダブルクリックして、そのボタンの関数を生成します。
こうすると、その関数にも書き換えていた名前が使われます。
順番を逆に、関数を先に作っておいて、nameを変更しても、関数名は変わりません。


200827
C#、型変換?
何気なしに、下のようなコードを書いていました。
int a =0;
string b="";
b+=a;
これがエラーになりません。
何やらの型変換が起きています。調べても用語が分かりません。当たり前の事なのでしょうか。



200826
C#、SelectedIndex、SelectedItem

comboBoxのSelectedIndexとSelectedItem、見様見まねで使っています。ようやく、違いが分かりました。

私の理解では、
comboBox1に、always、hourly、daily・・・、とデータ(選択肢)がセットしてある状態で、
comboBox1.SelectedIndexには、数字(int)が入ります。選択肢の先頭から0,1,2です。
選択肢の2番目のhourlyが選択されたら、comboBox1.SelectedIndexは、intの1です。
こちらの方はそのまま代入も出来ます。comboBox1.SelectedIndex=0;とすると、一番目のalwaysが選択された状態になります。
ただ、数字ですので、選択状況をボックス以外に表示する時や、テキストファイルに保存する時にはcomboBox1.SelectedIndex.ToString();、とします。

comboBox1.SelectedItem、には、選択肢の文字列、alwaysとか、hourly、とかが入っています。
こちらの方は、選択肢の文字列が取り出せます。方法が少しややこしいですけど。
直接、string str = comboBox1.SelectedItem;とするとエラーになります。
object型とかキャストとかのエラーメッセージが出ます。
(string)comboBox1.SelectedIndex;か、comboBox1.SelectedIndex.ToString();とすると、選択された文字列が取り出せます。

ここまで、整理してきて、comboBox1.Text、というプロパティ?があることに気付きました。
先のcomboBox1で3番目のdailyが選択された状態だと、dailyが帰ってきます。
目的は、この文字列を取得する事でしたので、comboBox1.TextでOKです。
comboBox1.Textに関しては説明してあるページが少ないように思います。新しく追加されたものかも知れません。


200825
C#、this.Close()
プログラムを終了する時(フォームを閉じる時)は、this.Close()、とあり、各所に置いています。
とにかく、意図通り終了できていました。

今日、変な動作をするケースに気付きました。
終了すると同時に、例外が発生しているようです。
例外が発生せず、期待通りに終了する場合もあります。
終了、というボタンを作って、そのクリックイベントでthis.Close()すると正常に終了します。
フォームにあるXボタンでも正常に終了できます。

this.Close()をあちこちに置いて調べてみました。
原因が大体わかりました。いえ、原因というか、発生する構造というか。
this.Close()の次のコードが実行されています。
次の行に、フォームのボックスに表示するコマンドが置いてあった場合は、
破棄されたオブジェクトにアクセスできません、という例外が発生しています。

並行処理、みたいなもので、動作を止め切れていない様子です。

ただ、この現象は、デバッグモードの時だけで、デバッグ無しで実行、だと発生しません。
多分、Releaseモードでも大丈夫なのではないでしょうか。




200820
VS、ショートカットキー

C#をというか、VisualStudioを始めて二か月半ほどでしょうか。編集中、メニューを開くのが段々面倒になります。
そこで、使い勝手のいいショートカットキーを覚えていきます。

最近、ようやく覚えたものに、
F5キーがあります。デバッグの開始です。
これまでは、いちいちメニューを開いて、ビルドし、メニューのデバッグをクリックしていました。
これを、F5一発で済ませられます。ビルドエラーの時は止まりますので、問題は無いという事に気付きました。

関数間の移動に、F12や、Ctrl+マイナスキーなど、便利ですね。

ショートカットキーの怖い所もあります。
万国共通の、コピーペーストの関連で、Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X、などは便利な反面、よく間違います。
よくやるのが、Ctrl+V、とすべきところをCtrl+C、としてしまって、クリップボードを空にしてしまう事です。



200819
C#、ボタン名の変更
ボタン類を増やして行くと、コードが読み辛くなります。
button1は何のボタンだったかな、という感じです。

そこで、ボタンの用途に合わせて、ボタン名を変えることを考えました。
button1.Enabled = false、とするより、
Btn_end.Enabled = false、等とした方が、
終了ボタンを無効化したな、と分かります。

これはこれでいのですが、悪影響が出ます。
一つは、ボタンをクリックした時の関数名はそのままです。
そして、変更後に更にボタンを追加すると、button1がまた作られてしまいます。

で、関数はどうなるかというと、
最初のボタン名を変更したボタンの関数は、
private void button1_Click(object sender, EventArgs e)、で
後で作られた、button1の関数は、
private void button1_Click_1(object sender, EventArgs e)
となっています。

動きに矛盾はありませんが、ちょっと分かりにくいです。
私の知らない方法が有るのかもしれません。



200818
VS、二重起動

未だ、分からない事も多いながら、VisualStudio2019のエディタにも多少は慣れたと思います。
ただ、困った事に、油断すると重複して起動してしまいます。困った物です。

新しくプロジェクトを作る時以外は、slnファイルのアイコンを作っておいて、そのアイコンをダブルクリックして起動しています。
このアイコンをダブルクリックしさえすれば、同じものが何個でも起動します。
今、試してみたら、本体を起動して出てくる最近のリストを選択しても同じでした。やはり、重複して起動できます。

TeraPadで試すと、二つ起動は出来ますが、同じファイルを読み込もうとしても読み込みません。
右クリックメニューから、ファイルメニューから、どちらもダメです。

メモ帳は普通に読み込めました。

VisualStudioCodeも試してみました。
こちらは、よくわかりません。肝心な所で英語が出てきたりして、要領を得ません。
読み込めたり、読み込めなかったりします。



200815
C#、str.Contains(s)
strにsという文字列が含まれるか、という所で、str.Contains(s)を使いました。

いえ、特に問題はなかったのですが、ここでfalseを試してみようと考え、
string s="";
if (str.Contains(s) == false){}
としました。
バグ取り、と言いますか、動作試験などで、よくやることです。

しかしながら、これが期待通りに動きません。{}内は通らず、スキップしてしまいます。
冷静に考えると、当然でした。""は、どこにでも含まれています。trueです。


200814
C#、エラー処理

C#、VSの範疇かも知れません、C#でデバッグ中にエラーが発生すると、ブレークポイントみたいな感じで止まります。
発生した行と、原因の説明が表示されます。
心配なのは、これが実行ファイルで発生した時、どういう処理になるのか、という点です。

今回、簡単なエラーが出ましたので、思い切って試してみました。

VSのメニューにあるデバックなしで開始、bin/Debugフォルダに保存されている実行ファイル、bin/Releaceフォルダにある実行ファイル、のいずれの場合も、例外が発生した、という意味のダイアログが出ます。
続行と終了の選択が出来ますが、実質終了するだけです。
終了と言っても、実質は強制終了ですが、平和的な感じで終了できます。

この時のエラーは、ファイルが見つからない、というものでした。
念のためにもう一つ、0で除算しました、となるものを作ってみました。

対応は同じです。
デバッグモードでは、その行で止まり、原因が表示されます。
デバックなしで開始、では、先と同じダイアログが出て、終了させられます。

ありがたいのは、そのダイアログをよく見ると、詳細、というボタンがあり、そこにエラー発生の説明や発生した行番号まで表示される事です。
これはReleaseモードの実行ファイルでも同じです。行番号が表示されます。



200813
C#、forループ
forループをよく使います。
いえ、他にもループがある事だけは知っていますが、使ったことがありません。使い方が分かりません。

いつも気になっていた事です、最初からforの条件式に合わない場合はどうなるのか、という事でした。
c=-1;の状態で
for (int i=0; i<c; i++)、のループに入った場合です。

今まで、適当にやっていて問題は出ませんでした。
今日、しっかり調べてみました。

解説のあるページはネットにも多いのですが、このかゆい所に手の届く説明はなかなか見つけられません。
そこで、最後の手段、F1でMSのヘルプを見てみました。
いつも、このF1で出てくる説明は、訳の分からない事が書いてある場合がほとんどです。
しかしながら、今回は大当たりでした。しっかり書いてありました。
肝心の部分を書き出すと、

conditionセクションの式は、ループの反復の前に毎回評価されます。
式が true に評価される場合、次のループの反復が実行されます。
そうでない場合は、ループが終了します。
だそうです。
conditionセクションとは、上の例では、i<c、の部分です。

実際には、もっとねちねちと書いてあります。要約すると上の様になります。
つまり、最初から条件式に合わない場合はループは一回も実行されない、と解釈できます。

問題は、私の解釈で正しいかどうかなのですが。
振り返ると、HSPでも同じだったような記憶があるかないか、おぼろげですか、思い出しました。
どこでも共通なのでしょう。

実際に、動作がその通りなのか、調べるのは難しいです。
プログラム流れで、実際には、先のループの前の段階で、
if (c<0) return;
みたいなコードを入れるからです。

ここで気が付いて、試してみました。簡単なコードで試せばいいのです。
int c = -1;
for (int i = 0; i < c; i++)
{
MessageBox.Show("内");
}
MessageBox.Show("外");

実行すると、外、だけが表示されます。

200810
C#、エディタ、<>

VSのエディタは機能が多くて便利です。
まだ、記号の意味や操作方法の分からない事も多いです。

その中で、困ることがひとつ、<や>の扱いです。不等号ですね。

今、サイトマップファイルを扱うプログラムを作っています。
そこで、頻繁に出てくるのが、<url>とか</loc>とかいう文字列です。
この文字列をタイプする分には問題ありません。
が、なぜかコピー、ペーストで持ってくると、エディタ側で勝手にスペースを入れてくれます。
< url >というようになります。
//の後に貼り付けるとか、""の間に持ってくるとかだと大丈夫です。
計算式と勘違いするのでしょうね。

もし、文字列の先頭が<url>となっているなら、という様な構文はよく作ります。
タイプミスを減らす為、文字列を引用する時は、出来るだけコピーで持って来るようにしています。
そこで、油断すると、先ほどの変化が起きます。困ったものです。



200809
C#、File.Copy()、更新日時
ファイルのバックアップを作る必要に迫られ、調べました。
System.IO.File.Copy(@path1, @path2, true);という関数を見つけました。
コピー先に同名のファイルがあっても上書きする、というものです。
文字コードの指定とか、宣言とか、前置きも何もいらない(多分)様です。すぐ試してみました。

何かが違います。
ふと気が付きました。
ファイルの更新日時が変わりません。いえ、多分変わらないのだと思います。
普通の事ですが、不便な点があります。
上書きされたかどうか分かりにくいという事です。

実は、HSPでは通常、コマンドでコピーすると更新日時が変わります。これも多分です。
更新日時が変わらないと、実際に上書きされたかどうか分かりにくいのです。
上書きされた際、更新日時がその上書きされた時間になるなら、前回のコピーの後、1分待って試してみると結果が分かります。
コピー元のファイルの日時のままだと、こうはいきません。1分待ってコピーしても、あれ、上書きされなかったかな、と心配になります。
ファイルの中身を変えるなりして、その中身を見てみないと分かりません。

元々、エクスプローラなどでコピーする場合は、更新日時は変わりません。
当たり前で、まあ、慣れの問題かもしれません。



200808
C#、Win8.1、.NET

このPCと無関係の環境で、C#の実行ファイルを起動したいことがあり、マルチブートのWin8.1に切り替えてみました。
これが、立ち上がりません。
エラーメッセージのダイアログが英語ですので断定ではありませんが、意味は、.NETFramework、Ver4.7.2が必要だ、インストールするか、と書いてあるようです。
確かに、C#のプロジェクト云々の時、NET云々が沢山出ていました。必要な物なのでしょうし、私の8.1は飾りみたいなもので、必要最低限と言いますか、何も追加してありません。

Win10の方に、それがちゃんと入っているのか、入っていないはずはないのでしょうが、調べてみました。
これが結構面倒でした。

まず、コントロールパネルなどにあるプログラムと機能を見てみました。
ありません。
Windowsの機能の有効化の所に、.NETFramework、3.5の記述はあります。
これでは足りません。
もう一つ、.NETFramework4.8AdvancedServices、というものもあります。
4.8だからよさそうなものの、その後ろの英語の意味がよく分かりません。

そこで調べてみました。
MSのページにバージョンの確認方法が書いてありました。
regeditから調べられます。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Fullのキーがあれば4.5以上が入っている、あと、その先の細かい数字を調べるとバージョンも分かる、という事です。

で、その通り調べていくと、どうやら4.8が入っています。
これも、4.8と書いてある訳ではなく、適当な5、6桁の数字を見比べて判別する、というものでした。
これで大丈夫だという事になりますが、面倒な話でした。
なぜ、もっとはっきりと出さないのでしょうかね。

それに、普通には.NETは入っているものなのでしょうか。
そこで、旧機を調べてみました。Win10です。
こちらには入っていました。と言いますか、先の実行ファイルがすんなり立ち上がりました。
必要な.NETはインストールされているという事になります。





200808
VS、バージョンアップ
VSのバージョンアップのダイアログが出ました。
バージョンアップは頻繁に出ます。5月に始めて、月に一回以上のぺーズだと思います。記録はしていませんが。
今回は16.7.0です。いつもの様に、すぐ実行しました。

今回は変化がありました。嬉しい事ではありませんが、起動時にダイアログが出るようになりました。
ソリューションを準備しています、とかいうメッセージです。
このダイアログが出ている時間は一秒そこそこです。
出ない時もあります。何度か試している内に、状況が分かりました。
PCを立ち上げ、最初にVSを使う時だけです。2度目からは出ません。
状況はVSを立ち上げ、リストにある目的のslnをクリックして起動する場合でも、直接slnのショートカットから立ち上げても同じです。最初にslnを起動する時、一回だけ出ます。
これが、PCの再起動でリセットされるみたいで、また最初の一回だけ出ます。

起動時のダイアログでは、バックグラウンドタスクがまだ実行中です。というものもあります。
これは、必ず出ますが、ひっそりと出ます。気にすることもないようなメッセージです。
今回のダイアログは、画面の真ん中に出ますので、とても気になります。
何も出さずに待たせる方が良いと思います。その方が、ほんの僅かでしょうが、早いはずです。

私の環境での、ショートカットからの起動に要する時間は、
一回目の起動、その面倒なダイアログが出る場合です、カーソル点滅まで15秒、バックグラウンド云々が消えるまでに更に10秒ぐらいでした。
2回目以降は、エディタのカーソルの点滅が始まるのに約10秒、バックグラウンド云々のダイアログが消えるまでに更に5秒ぐらいです。
あ、この差はダイアログのせいではなく、一回起動すると、何かメモリに残すのでしょうね。
また、この差があるせいで、一回目だけ、間つなぎのダイアログを出す様にしたのでしょう。
面倒な事です。

200812追記
再度、バージョンアップの通知がありました。16.7.1です。
すぐ、アップデートしました。
前回は、確かPC自体の再起動が要求されたと思いますが、今回はありませんでした。
今回の変化は、参りました、起動時の、ソリューションを準備しています、のダイアログが毎回出るようになりました。

起動に要する時間を再確認してみました。
PC起動後の一回目のVSの起動が、15秒+10秒、
2回目以降が、10秒、5秒、程度です。変わりません。
気持ち遅いようにも感じます。気のせいでしょう。


200807
C#、プリプロセッサ命令、#if DEBUG、注釈

デバッグモードの時だけ実行させたい命令があります。
動作確認用にダイアログするとか、テキストボックスに途中経過を表示するとかです。
HSPでは#defineで同じ様な事が出来ていました。
C#でも探していましたが、今日ようやく、このコマンドにたどり着きました。
#if DEBUG
#edif、です。

文字通り、VSのエディタでDebugにしている時だけ有効になるコマンドです。
Releaseにしていると、VSから起動した場合でも、Releaseフォルダにあるビルドした実行ファイルでも、このコマンドに挟まれた部分は実行されません。
逆に、Debugにしている場合は、メニューで、Debugなしで開始、でも実行されます。

この件、と言いますか、条件付きで実行したい場合、色々試しています。
//の注釈行は手軽なのですが、コードが長くなると手間です。
/*・・*/は復数行指定する時に便利なのですが、ネストが効かないというか、よくわからない状態になります。
コメントアウトしたい部分の一部に、既に/**/を使っている場合、よくわからない状態になります。

以前、調べた事で、#if trueがありました。
デバッグに関しては今日の分が便利です。書き直す必要がありません。


200804
C#、int、return
C#では、毎日の様に驚く事があります。

恥ずかしながら、
int aa(string bb)
{
  int cc;
  for (int ctr = 4; ctr < dd; ctr += 7)
  {
    bool tof = ee[ctr].Contains(bb);
    if (tof == true)
    {
      cc = ctr;
      break;
    }
  }
  return cc;
}
という感じのコードを書きました。

最後のreturn cc;に赤い波線、インテリセンスでしたか、が出て消えません。
マウスカーソルを当てると出てくる解説には、未割当云々と出ています。
解決後に考えると、その解説の通りなのですが、発生時には慌ててもいますし、理解不能でした。

原因は、最初の宣言で
int cc=-1、等、初期化?;が必要という事です。
納得は出来ますが、厳しすぎるようで、少し考えていただきたいような気もします。

先日、returnはループの中からでも問題ない、という事を知りました。
それに、trueは省略できますので、
少しスマートに(極めて個人的な感想です。)書き換えてみました。
int aa(string bb)
{
  for (int i = 4; i < dd; i += 7){if (ee[i].Contains(bb)) return i;} return -1;
}
と書けそうな気がします。
いま、試すと、エラーは出ていません。動作は未確認です。
動作も試しました。意図通り動いています。動いているように見えます。

こうなると、関数にする必要もありません。
ただ、分かりにくいし、本当に意図通りなのか、確信が持てませんので、私には使えません。
元に戻して、使っています。

200802
C#、str.TrimEnd()

末尾の空白行を削除するという事で、str.TrimEnd()を使ってみました。
全て手書きで作ってる場合は問題にもならない改行コード(0D0A、CRLF、\n、\n\a、以下改行)ですが、プログラムで行数をチェックしていると、これが問題になります。

そこで、簡単に末尾の改行を消せるみたいで、表題のメソッド?、関数?、を使ってみる事にしました。
どのような動作になるのか、コードの前後を調べました。
・・
・・
</urlset>改行
改行
改行

となっているファイルをstr.TrimEnd()を通すと

・・
・・
</urlset>

となります。
つまり、末尾にある改行は全部削除されます。
末尾の行は</urlset>だけになります。直後の改行も消えます。
これで問題はありません。
行数はちゃんとカウントされます。

なお、最後の行に改行のあるなしは、行数のカウントでは同じです。
つまり、末尾が
</urlset>改行、と
</urlset>、だけの行は、同じ一行です。



200802
C#、throw
try、cacth、throw、構文というのでしょうか、ネットから頂いたコードの中にありました。
指定のページが実際にサーバにあるか調べる為に使わせていただいています。
ページがある場合は、何も問題なく処理されます。
しかし、でたらめなURLを指定すると、throwの所でエラーで止まってしまいます。

on error gotoみたいなものだと思っていましたので、びっくりです。
デバッグモードでしたので、もしかと思ってリリースモードで試してみました。
こちらでは、ダイアログが出ます。続行するか終了するか選択するものです。
続行を選ぶと、すんなり回復します。
自前のダイアログを出す方法があればと探しましたが、見つけられません。


200720
C#、フォームに四角形の描画

フォームで画面を作っていく時、四角形を描画したい場合があります。
ボタンとかボックスとか幾つか配置してあり、このボックス類は一つのグループです、みたいな表示をしたい時です。

調べても、調べても、この方法が分かりません。
その中に、ラベルが利用できる、みたいな記事がありました。
正式に作る方法が分からないので、そのラベルを転用する方法に挑戦しました。

普通にラベルを配置します。
右クリックメニューに最背面へ移動、があります。こうしないと他のコントロールが隠れてしまいます。

そのままでは、文字数に合わせた小さなボックスで、どうしようもありません。
後、プロパティを変更していきます。
文字があるとまずいので、Textを削除します。
AutoSizeをFalseにすると、サイズを自由にできます。これで大きな四角形が描けます。
BorderStyleをFixedSigleにすると枠線が出てきます。
BackColorで色の指定が出来ます。

これで、必要なコントロールを囲うことが出来ました。


200729
C#、カレントフォルダ
レジストリが使えるなら、問題にはならない事でしょうが、そのような知識はありません。
あちこちに、素人は、レジストリをいじるなと書いてありますし。

プログラムでカレントフォルダを調べることは、簡単にできます。
System.Environment.CurrentDirectory、です。
ここにファイルを置きたいことはよくあります。
作業内容を次回の起動時に復元したい時に使う設定ファイルなどです。

さて、C#の場合、多分VS共通だと思いますが、このカレントフォルダが複雑です。
まず、コードが書かれているForm1.csがあるフォルダがあります。
ただ、これはカレントではありません。
ソリューションのフォルダ、あるいはプロジェクトのフォルダというべきものでしょう。
私は、今だに、ソリューションとプロジェクトの違いが分かりません。

さて、カレントは実行ファイルがあるところです。
この実行ファイルが二つあります。デバッグ用とリリース用です。別々です。
\bin\Debug
\bin\Release
となっています。

ですので、先の設定ファイルなどDebugフォルダに置いておかないといけません。
面倒な事です。こうしないと、動作試験ができません。



200726
C#、forループ、return、break、goto

これまで、forなどのループの中で、途中で抜け出すには、breakと覚えてきました。
ですので、ネストされたループから抜け出すのにフラグを使ったりして苦労したものです。

ここまで、C#でも同様に思っていましたが、詳しく調べてみたら、違うようです。
gotoでもreturnでも自由に抜け出せるようです。


200726
C#、false、!
if (!kkk.Contains(rrr) == false){}
このコードが意図通り動いてくれないので困りました。

原因は先頭についている小さな!でした。
ネットで、文字列が含まれているのか調べる構文をコピーしてきて使いました。

元々は、f (!kkk.Contains(rrr)){}、となっていたものです。
これで使わせていただいていたのですが、コードを見直す最中に、やはり、==が欲しくなります。
==が無いと直感で分かりにくい事と、
最近、trueとfalseのスペルを覚えましたので、==false、を付けて、見やすくしようとしました。

すると、突然、動きがおかしくなりました。
先頭の小さな一文字を消し忘れていたのです。



200725
C#、配列のコピー

文字列の配列のコピーに Array.Copy()を使いました。
この動作が、参照なのか値のコピーなのか分からず、困っています。
ネットでは、参照渡しになっていて、コピー先を変えると、コピー元も変わってしまう、と書いてあるようです。
逆にそんなことはない、と書いてあるように見えるものもあります。
一番の問題点は、私が専門用語を理解できない事なのですが。

そこで、実際に試してみました。
Array.Copy()で、配列kkから配列mmへコピーした直後です。

1行目を表示させると、
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm[0]は、<?xml version="1.0" encoding="UTF-8"?>

次に
mm[0] = "test"、としてみた結果です。
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm0]は、test
となっていました。

念のため、
kk[0] = "testtest"、としてみた結果は、
kk[0]は、testtest
mm[0]は、test
でした。

これで、はっきりしました。
参照ではない、という事です。

string型の配列の場合、参照ではない、と書いてある記事も見ました。
これだろうと思います。



200725
C#、バックアップ
プログラムを作りながら、ここでバックアップを作っておきたいと思う時があります。
やみくもに発展させてしまって、どうにもならなくなって、元のちゃんと動く状態まで戻そうとするときの為です。

HSPなら、単純にファイル名を変えるなり、フォルダを変えるなりして、毎日でもバックアップしておけました。
どうやら、VSでは単純ではないようです。
設定ファイルみたいなものがあって、バックアップから単純に戻しても動かない、みたいです。
でも、一応、節目節目で、フォルダごとバックアップしてあります。
しかしながら、これを戻してみた事はありません。
戻す場合は、フォルダごと戻さないといけないでしょうし、そうすると、現在のファイルをどこかに退避する必要がありそうです。
その退避した方が使えるか不明です。
バックアップも現在のファイルも同時に使えないと、怖くて使えません。

200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまうとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。

201009追記
ついでがあり、少し前にバックアップしたもので、slnファイルをクリックしたらどうなるか試してみました。
つまり、別のフォルダにコピーしたものがそのまま使えるか、という事です。
使えます。
フォルダごとコピーしたものです。
当初、コードを出すのに苦労しました。起動はしますが、コードが出てきません。
いえ、出ることは出るのですが、コードを開いた状態が保存されません。
slnファイルを起動すると、画面が空白状態になっていて、コードを見るには左側の何たらから、関数名などをクリックする必要がありました。
再起動しても同じ操作が必要でした。

そこで、実際に使っているものと見比べて、コードのタブのピンを縦にする必要がある事に気付きました。
こうしておくと、再起動しても、同じコードが見られる状態で開きます。
何やら、初期化されているようです。
この件、8/28にも試していますね。


200724
void、boid

boid サブフォルダ変更()
今日作った関数名です。これがエラーになって、原因が分からず、気が付くのに1時間以上かかりました。

赤い波線が出て、消えません。
関数内のreturn;の所にも波線が出ています。ヒントには型が違うみたいな表示だったと思います。

このヒントがよく出来ていると思います。赤い波線、インテリセンスの事です。
マウスカーソルを波線の上に持ってくると、エラーの原因やヒントが出てきます。
残念な事に、それを読んでも理解できる程の知識がありません。
ヒントの中に、解決策出ています。クリックしていくと、その案に沿ってコードを書き換えてくれます。
この方法で解決する場合もあります。

今回は、四苦八苦した挙句、スペルミスに自分で気付きはしました。
後で確認したことです。先のヒント、いくつかの解決案が箇条書きに出ているのですが、その最下段に、
boidをvoidに変更、という項目も出ていました。

あらためて感心すると同時に、最下段での案内です、そんな間違いはまずないだろうと思われているようです。

200723
VS、フォントサイズ
エディタのフォントサイズは、Ctrl+マウスのスクロールボタンで簡単に変更できる事に気付きました。ただ、多少の不便さがあります。
VSのメニューとCtrl+のショートカットが連動していません。
設定が維持されない時があります。

VSの使い始めの頃、フォントサイズの変更に苦労した覚えがあります。設定は、ツール、オプション、環境、フォント及び色、にあります。
どうやら、Ctrl+は規定外かもしれません。

メモ帳でも試しました。
メモ帳でも、Ctrl+マウスのスクロールボタンで変更できます。
つまり、Win共通のショートカットなのでしょう。

ただ、やはり、安定しません、と言いますか、設定が維持されません。。
メモ帳では、メニューの、書式、フォントで簡単に設定できますので、行き来して調べました。
ショートカットと連動していません。
ショートカットでの変更は、その場限りの変更の様です。
メモ帳を再起動すると、メニューで設定したサイズに戻ります。

VSでは、どうやら、すべて保存を実施した後では、設定が残るようです。
それでも、設定メニューの数字は、つまり、メニューに表示されるフォントサイズは実際と合いません。
ショートカットで変更して、そのサイズが維持される場合でも、ツールオプションの中のフォントサイズは変わりません。
多分、です。何しろ再確認が面倒なので、好みの大きさからもう変更したくありません。



200723
サイトマップファイル

このサイトは、一応、サイトマップファイルが作ってあります。HSPでの半自動化の一環です。
この作業がここまでの懸案で、半自動化のメモに書いていますが、何しろ30000行、600KB程のテキストファイルです。
ファイルを更新するのに50秒程かかっていました。
ページの更新はほぼ一日おきにしていますので、この作業も一日おきです。少し辛い物がありました。
この問題は、こちらのC#などを勉強する過程で原因に気付き、現在では3秒程度で終わる様に改良しました。

更に、このC#をかじっていく内に、C#がコンパイラと同じ程度に高速だという事を実感する様になりました。
そこで、このサイトマップファイルの更新作業をC#で組もうとしています。
現在、このページのメモは、大半、この作業に絡むものです。

そして、今、大まかなところで出来上がりました。後は、エラー処理と操作性の改良だけです。
そこで、実行時間を測定してみました。
やはりC#だと、ミリ秒の世界です。
実行時間は、ソートが入れてある関係で、ファイルの先頭近くに追加するか、末尾近くになるかで大きく違います。
一番手間を食うような状況、つまり、ファイルの末尾に追加するような作業で、500ミリ秒程度で終わります。


200722
C#、フォルダ選択ダイアログ、プロパティ
フォルダ選択をマウスで指定出来るように、と調べると、これが出てきます。
FolderBrowserDialog fds = new FolderBrowserDialog();

ただ、これは必要最低限と言いますか、まあ、意図通りには動きますが、操作性はよくありません。
本来は、普通のエクスプローラと同じ操作性で、左側にクイックアクセスやドライブなどが表示され、右側で目的のフォルダを選択するものです。

先のダイアログだと、その左側部分がありません。
それに、どうやらデスクトップが既定になっているみたいで、これが選択リストの最上段に出てきます。
必要なフォルダは、データドライブの中の、かなり深い位置にあり、スクロールしないと出てきません。

せめて、初期のフォルダだけでも見える状態で出てこないかと調べました。
fds.RootFolder = Environment.SpecialFolder.MyComputer;
とすると、何とか目的のフォルダが見える状態でダイアログが開きます。
これが確実ではなく、たまには別のフォルダが出てくるときもあります。
どうやら、前回の動作を覚えているようです。

200722
C#、テキストボックスの自動スクロール

複数行のテキストボックスの表示が、自動でスクロールする事に気付きました。
HSPではこれが無くて、苦労しました。システムコールか何かで実現させていました。
ボックスのプロパティに可否があるのかもしれません。
ま、うまくいっている所は探しません。

200720
#if、#endif、プリプロセッサ命令
#if true
#else
#endif
が使えます。

今まで、変数類を大幅に入れ替えて試したい時、
/*
*/、で囲んで、切り替えていました。
#ifの方が楽です。
trueをfalseに書き換えるだけで済んでしまいます。


200719
str.Remove(0, 1)

文字列の先頭ある「/」を削除したい時の処理、正しくは、
if (str.StartsWith("/") == true)
{
   str = str.Remove(0, 1);
}
なのですが、この=の前のstrを忘れて、
str.Remove(0, 1);だけにしてしいがちです。
困ったものです。
確かに、解説には、作業後の文字列を返す、と言うような事が書いてあります。

左側のstrに入る様だったら、右側にも入りそうなものですが、そうはなりません。

ただ、これとか、文字列の末尾の一文字を削る関数もあり、C#の便利な所です。


200717
C#、フォーム表示後にダイアログ表示、Form1_Shown()
フォームを表示させた直後の作業で、例えば、ファイルのあるなしを調べて、目的のファイルがない場合に、ダイアログでメッセージを出します。
この際、最初に配置されているpublic Form1()という関数がそれらしく、最初に実行されるのだろうと思い、ここにこの段取りを書き込んでいました。
ファイルの読み込みや、ボックスへの表示など、普通にはこれで予定通りです。
しかし、先の様にエラーのダイアログを出す様にしたら、肝心のフォームが出てきません。ダイアログだけが表示されます。

これでは、多少見苦しいので、調べました。
Form1_Shown()、という関数がそれで、ここに書き込むと、フォームの表示後にダイアログが出るようになりました。

正確には、private void Form1_Shown(object sender, EventArgs e)、です。
フォームのプロパティで、Shownという項目をダブルクリックすると出現します。



200717
C#、関数、引数、参照渡し、値

関数について、少し勉強してみました。
ここまで、使わない訳にもいきませんので、使ってはいますが、全部、引数無しの、Void関数名()、です。

必要な変数は、試行錯誤で全体にスコープされる場所を見つけました。
classの下です。
ここに置いておくと、これ以下のどこからでも参照?(言葉については不明)できています。

ネットの記事では、C#にはグローバル変数はない、と書いてあります。
多分、classとかnamespaceとかを超えられないという意味だと思います。
そのような大掛かりなものは、私には作ろうにも作れません。

そこで、折角なので勉強してみました。
引数について、参照渡し、値渡し、配列は参照渡しになる、という事は、昔読んだ記憶があるC言語と同じです。

ただ、そこまで厳密な区別は出来ず、肝心な変数はどこからでも参照できた方がしっくりきます。
これは、グローバルな変数しかない言語から入ったものの欠点だと、やはりどこかの記事にありました。


200712
C++、デスクトップアプリ
C++をまた少し触ってみました。
簡単にフォームが作れないかと思っての事です。過去何度も挑戦して、失敗しています。
なんのことはない、プロジェクトの所でデスクトップアプリを選択すると、簡単にできます。
出来ると言っても、初期画面のままです。どこにコードを書き込むのかさえ分かりません。
分かったとしても、これまでに知識はほとんど役に立たないと思います。そんなコードが並んでいます。

とにかく、フォームでしょうかデスクトップ画面というのでしょうか、窓は、初期状態でビルドしさえすれば表示されます。



200712
VS、プロジェクトのバックアップ、再利用

C#でプロジェクトかソリューションか、とにかく今作っているコードを利用して別のプロジェクトを作りたい場合があります。
普通には、ファイルをコピーして、それを使えばいいはずです。
バックアップでも同じです。ちょっと作業が一段落して、一応ちゃんと動いている。これから先の作業でどうなるか分からないので、バックアップしておく。最悪、これからの作業が行き詰ったら、そのバックアップに戻ってやり直せばいい、はずです。

調べたら、VSの場合、これが通用しない様です。
何やら設定ファイルみたいなものがあって、絶対パスになっているのでしょうか、フォルダを変えてしまうと、うまくないみたいなのです。
試してみて、元も子もなくなるのが心配なので、この件は試していませんが。

フォルダごとのコピーもバックアップも通用しない様なのです。困ったものです。
200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまううとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。



今回も、そのようなケースで、新しくプロジェクトから始めます。
作るのは、C#、Windows、デスクトップ、Windowsフォームアプリケーション、.netFramework、です。
(次回の為に、プロジェクトの選択項目をメモしておきます。)
予めフォルダを作っておいて、そこを指定します。プロジェクト名はフォルダ名にします。根拠は、その方が面倒がなさそうなので。
フォルダは、新規の際のプロジェクトの場所を決めるボックスでも指定できます。
これが間違いやすいのです。
例えば、G:\data\cs\map、というフォルダで作業したいのに、出来上がって調べてみると、G:\data\cs\map\mapとなっていた、という事が起きがちです。
なので、あらかじめフォルダを作っておいて、プロジェクト名にそこを指定する、と失敗はありません。



200710
関数、メソッド、一覧、移動、日本語
関数への移動方法で悩んでいました。
関数を呼び出している所からなら、F12で移動できることは最近分かりました。
元の呼び出し場所へ戻るのは、Ctrl+-です。

いつもHSPを引き合いに出しますが、HSPでは編集メニューに関数一覧があります。ここから実際の関数の場所に移動できます。

今日ようやく、同じような方法を見つけました。
ソリューションエクスプローラーのform1という項目の横の小さな右三角をクリックです。
ここに関数一覧+αがズラーッと出てきます。
似たような名前がいくつも出てきて迷いますが、よく見ると自分が作ったものもあります。
で、目的の関数名をクリックで、コードの場所へ移動します。
200818追記
これに気付くのに一か月と8日かかりました。
関数等への移動の方法です。エディタの右上に小さなボックスがあり、そこの小さな三角をクリックすると、上と同じような関数類のリストが出てきます。
関数と変数定義と他にも何やらあるようですが、とにかくジャンプテーブルになっています。
上の方法だと、リストを表示させるまでに幾つかクリックが必要ですが、こちらならワンクリックです。
それに、懸案だった、今どこにいるか、カーソルの位置も分かります。
ただ、先の方法だと、常時リストが見えているので、連続して移動する時には、まだ使えそうです。
もう一つ、右上のリストは、ソートされています。これでは多少使い辛いです。
この点、どこかに設定があるといいのですが、あったとしても探すのが大変です。
200818追記ここまで。

更に調べたら、C#でも関数名や変数に日本語が使えます。今日初めて気づきました。
変数は何度も使うので日本語は面倒ですけど、関数には使った方が便利です。
HSPでは、よく使う、というか、重要な関数や区切りの場所に日本語のラベルを使う様にしています。
すると、関数の一覧を出した時、探しやすくなります。
C#でもラベルが自由に使えるといいのですが。
いえ、使えるみたいです。
ただ、使いたいのは、例えば、ボタンのクリックの所です。

ファイル読込ボタン:
private void button1_Click(object sender, EventArgs e){}
このように、関数の宣言の前後に日本語のラベルが使えると、関数を探すのがとても楽になるはずです。
残念な事に、関数の内側ならラベルは使えますが、ラベルは一覧には出てきません。

それに、今いちなのが、これで現在の位置が分からない事です。
HSPのラベル一覧では、現在のカーソルの位置のラベルが反転して、自分が今どこにいるのかが分かります。
これは重宝します。


200709
VSのヘルプ

常々、Visual Studioのヘルプは貧弱だなと思っていました。
まあ、フリーの物にはよくあることだからと観念して、ネット検索に励んでいました。
今日、気付いた事が1件、プラス2件あります。

まず、ファイルなどのフルパスからファイル名だけを取り出す(メソッドというのか関数というのか)方法について、
System.IO.Path.GetFileName()は、ファイル名だけではなく、最下層のフォルダ名も取り出せる、という事です。
つまり、文字列の一番右にある\から先の部分を切り取ってくれます。とても便利です。

これを利用する状況は、フォルダの一覧を作る時です。この時の試行錯誤で、便利なヘルプの機能について気付きました。
まず、単語の上にカーソルを置いてF1でヘルプが出てきます。
これは、HSPにも同じF1でヘルプが出てきますので同じでした。
ただ、VSのヘルプは、読んでみても私にはよくわかりません。専門家向きなのでしょうかね。

フォルダの一覧を作るので、下の様に書いてみました。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", SearchOption.TopDirectoryOnly);
ところが、例の赤い波線がSearchOptionの所に出て消えません。
しかし、その赤い波線の所にマウスカーソルを持っていくと、ヘルプみたいなプルダウンが出ます。
考えられる修正内容を表示してくれるのです。
その内容の中にSystem.IO.とか、using System.IO、とかいう項目が出てきます。
ああ、これだと気づきます。で、クリックすると補完されます。
using System.IOの方がスマートなのでしょうか。何故か私はこれを使っていません。

で、こうなります。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", System.IO.SearchOption.TopDirectoryOnly);
波線が消えます。実行すると意図通りに動いてくれます。

もう一回、System.IO.Path.GetFileName()について、
フルパスから一番右側のファイル名だけ取り出すものですが、とても便利です。
ファイルやフォルダのリストを取ると、全部フルパスで帰ってきます。
必要なのはファイル名だけです。この時に使います。
HSPでは、これが無いので、関数など作ったりしていました。
strrepとかsplitとかこれに近いものはあります。それでも面倒です。
一番ありがたいのは、文字数などのカウントが必要ないことです。
0から始まるのか、1からカウントするのか悩む必要がありません。



200708
true、false、if (!a)
未だにif文の書き方がおぼろげです。

まあ、間違っても、その場で赤い波線になるので、何とか処理出来ていますが。
よくやるのがこれ、if (a = fales)、です。
2か所も間違っています。
==とfalseのスペルです。

これに気が付かないので、どうしても赤い波線が消えません。
やむを得ず、例文などからそのまま、if (a)とかif (!a)とか書き直して凌いでいます。
もちろん、!を付けるのが正しいのか、付けないのか分かりませんので、試行錯誤します。
それぞれ実行して、どちらか予定通りの行動になる方を採用する、という段取りです。

これを回避する為に、a=bの形式にしたいのですが、一方がtrueかfalseの場合、先のスペルミスがあります。
何しろ、いくつもの選択肢があります。
まず、引用符""が必要なのか、大文字なのか小文字なのか頭文字だけ大文字なのか、等、無限に試行錯誤が続きます。

長年=一つで済ませてきましたので、==に気付かないのはやむを得なかったと思います。
false、trueは、最近、こう書けばいいと気づきました。
if (a == false)、です。
ネットでは、ほぼ全部、if (!a)、と書いてあります。
if (a == false)、と書いてもらうと分かり易いのに、なぜ省略するのでしょうかね。

今日、気付いた事が2点、
falseは、フェイルスではなく、フォールスと発音する事、
VSのエディタでは、正しくfalseとタイプすると、文字が青色に変わる、という事です。
これで、今後は大丈夫でしょう。多分。


200707
C#、テキストボックスへの表示にかかる時間

200705付けでメモした事で、全く同じ作業なのですが、2度目の方が作業時間がかかってしまう、という現象がありました。
かなり大きなテキストファイルの更新作業です。670KB程度、行数は30000行ほどのファイルです。
このファイルの適当な位置に、新しく10数行の文字列を挿入します。挿入位置は末尾や先頭ではありません。途中です。

フォームで画面を作ります。テキストボックスを数個、ボタンを数個です。
テキストボックスのmaxlengthは0にしています。
こうすると、表示サイズの制限がなくなるとの事です。

起動時に、目的のファイルを読み込んで、表示までしておきます。
ボタンにコードを埋め込んで、実際の作業、文字列の挿入です。
具体的には、以下の作業になります。
まず、念の為、ファイルはもう一回読み込み、表示します。
読み込んだテキストに、文字列を挿入して、再度表示、保存です。
念のため、上書きしないように、保存する時のファイル名は変えています。
ですので、何度でもボタンを押して、同じ作業が出来ます。

いつも作業時間を計っています。
HSPでは3秒かかる作業で、C#で代替えして、もう少し早く出来ないかという事が動機でした。
結果、320ミリ秒程度で終わります。

ただ、ここで問題があって、ボタンをもう一回押して、同じ事を再実行させると600ミリ秒かかってしまいます。
これは何だ、となって、時間の計測を細かく分割しました。
ファイル読込に何ミリ秒、表示に何ミリ秒、という感じです。

これで、簡単に原因が分かりました。
一回目の実行では、読み込みに要する時間は10ミリ秒程度でした。これが2回目以降は270ミリ秒程かかっています。

この結果は、こう考えるよりありません。
C#では、テキストボックスに再表示する際は、表示してある内容と同じテキストだったら、表示を省略する。
どうしているのでしょうかね。チェックサムみたいな物があるのでしょうか。
コードを読み切っているのでしょうか。このコードなら再表示の必要なし、という判断をしているとは思えませんが。
だとすると、向こうが偉いという事になります。
まさか、文字数とかファイル名だけで判定しているはずもないでしょうし。

更に、もう一つ、大事なことに気付きました。
C#で、ファイルが大きい時など、テキストボックスへの表示をさせなければ、圧倒的に速くなる。
今回のケースでは、表示を省略すると、50ミリ秒で終わることになります。
比較の為に挙げた、HSPでの3秒という時間には、表示時間が含まれていませんでした。
つまり、C#が圧倒的に速い、ということです。

さらに、ずーっと下のメモで、色々な比較をしています。
この時、表示に時間がかかるという事は考慮していたのか気になります。
やはり、正確な比較をするなら、C#は、C言語といい勝負をするのかもしれません。



200705
C#、文字列の分割と結合
テキストファイルの途中に文字列を挿入する作業に苦労しています。
文字列の末尾ではなく、途中に小さな文字列を追加しようとしているのですが、なかなかうまく行きません。
HSPだと、noteadd 追加するブロック,追加する行番号,0、という一行で済む作業ですけど。

C#で、文字列の途中に文字列を挿入する手段を探しましたが、簡単な方法が分かりません。
簡単ではないというような記事もあります。

分かったのは、
元の文字列を、行単位に分割する。
追加する位置を境にして、前後のブロックに分けた文字列を作る。
前のブロックの末尾に今回挿入するブロックを追加する。
その後ろに、先に分けておいた後半部分のブロックを追加する。
という手段です。これ以外にはなさそうです。

上の方法で試しますが、すんなりとは行きません。
分割する時、前半のブロックの末尾が改行だけの行になっていて、これを連結すると、その改行だけの行が消えてしまいます。
一行短く仕上がってしまいます。
やむを得ないので、連結する時、改行を一行追加して辻褄を合わせました。

この作業、現在、HSPでは3秒強かかります。
サイトマップファイルに新しいページを登録する作業です。
ファイルは30000行660KBあります。
一応、同じ種類のページはまとめておきたいものですから、末尾に追加とはいきません。
今のところ、出来上がったテキストを保存する作業を入れていませんが、C#だと、300ミリ秒ほどで終わります。
C#に変える効果がありそうです。

どうやら正解が分かりました。
途中で配列にしたものを文字列に戻して、その文字列同士を連結したのがまずい様です。

完成後の行数、文字列を挿入した作業後の行数は分かります。
最初に、その長さの配列を宣言しておきます。
元の文字列も挿入する文字列も配列に変換します。
完成後の長さ分確保していた配列に、前半部分の配列、挿入する部分の配列、後半部分の配列を、位置を指定してコピーします。
最後に配列を文字列に変換します。
これで、改行だけの行も残ります。

完成したとして、ファイルの読み込み、連結、ファイルの書き込み、までの時間は330ミリ秒ほどです。
HSPでは3秒かかっていました。

ただ、連続して実行すると、2度目には600ミリ秒かかります。原因不明です。
原因が分かりました。テキストボックスへの表示時間です。これについては、改めて、項を変えてメモします。




200702
tt.Replace("\\", "/");

とあるフォルダのファイルリストを取ると、次のような文字列が出てきます。
G:/main-data/code/VS2019/CSDATA/temp20\200625mg.htm
\を/に変えたいのですが、うまく行きません。
tt.Replace("\\", "/");
が言う事を聞きません。

200701
C#、降順のソート
listBoxを使ってみる事にしました。
フォルダにあるファイルの一覧を作って、リストボックスに表示させます。

まず、ListBoxではなく、listBoxですね。まずここでエラーと言いますか、例の赤い波線です。
どうやら規定では、昇順にソートされる様です。
私の希望では降順でソートして表示させたいのです。
基本的に、ファイル名に日付を付けていますので、一番新しいファイルを一番上に置きたいのです。

全くの付け焼刃です。例によって、ネットを探しました。
これが面倒でした。様々なソートの方法が有るようですが、どれも分かりません。
構文が長くて、意味不明です。2行に渡る物もあります。
C#のバージョンによっても違うのかも知れません。
やはり系統立てて勉強していない事へのしわ寄せでしょうね。
目的は、単純に文字列の配列を昇順に並び換えたいだけです。
HSPだと、簡単に、sortnote files,1、とするだけなのですが。

ようやく、見つけました。
Array.Reverse(files);、で目的達成でした。



200623
VSエディタの起動時間

VSのエディタの起動にかかる時間が気になってきました。
C#で、デスクトップにslnファイルのアイコンを作って、そのアイコンをダブルクリックしてVSのエディタを起動しています。
これが、開き終わるまでの時間です。

編集しているテキストは、Form1.csだけです。これが30KBで、あと、Program.csというファイルがあります。1KBです。
csファイルはこれだけです。
そこで、時計を横目で見ての計測ですので、正確さはありませんが、ダイアログで、準備が完了しました、と出るまでに8秒ほど、
そのダイアログで、バックグラウンドで云々とあって、ダイアログが消えるまでに更に8秒ほどかかります。

エディタに慣れてくると、この辺りも気になってきます。


200620
C#、byte[]

昨日発見したbyte型ですが、ある程度の文字列を扱うので、大きめに確保しておきました。
byte[] aa = new byte[1000000];
そして、文字のアスキーコードを順番に入れていき、終わった所で終端の0を入れます。
その後で、Shift_JISの文字列に変換します。
string tt = System.Text.Encoding.GetEncoding(932).GetString(aa);

当方の目論見通りです。ちゃんと表示され、保存も出来ます。
ですが、よくよく調べてみると、ファイルの大きさが、最初に確保した1000000バイトのままです。
それこそVSCodeで強引にhexダンプしてみると、文章が終わった所から以降には全部、0が並んでいます。
Shift_JISでは考えられない世界です。これがUnicodeなのでしょうか。私の無知なのでしょうか。

やむを得ず、完成後のバイト数をしっかり計算して、必要十分な領域を確保して、回避しました。
それにしても、byte型に関しては、もう少し勉強が必要かもしれません。
一番の原因は付け焼刃でやっている事なのですけど。


200619
C#、char、byte、Shift_JIS
C#のcharは16ビットです。8ビットはbyteという型があります。
これは許せません。これに気付くまでに3日かかりました。

普通は一文字ずつメモリというか配列に収めるならcharでしょう。
そのつもりでやっていったら、どうしても型変換のところで止まります。
char m[0] = 65;
char m[1] = 66;
char m[2] = 0;

これをstrngに変換しようとしても出来ません。
強引に変換しても、結果は文字化けしています。
VSのエディタの警告やブレークポイントでのデータを見ると、UTF-8になるよ、みたいな表示です。
理解はできません。

正解は、
byte m[0] = 65;
byte m[1] = 66;
byte m[2] = 0;
です。
これで期待通りのShift_JISの文字列”AB”を作れます。
(何故か、末尾の0?='\0'は必要なし。)

このところ、文字列の連結で試行錯誤です。
言語も、C、C#、HSPを右往左往しています。
C#の速度がどうにも遅いので、調べたら、StringBuilderクラス、というものがありました。
これを使うと、Cに近い速度が出ます。
よく見たら、Cではcharの配列を使っていました。
文字列を連結するのではなく、インデックスを指定して直接書き込んでいます。
そこで、HSPに戻って、pokeを使って書き込みするようにしたら、こちらもC#並みとはいきませんが、かなりな速度になりました。
そこで、戻ってC#です。
C#でも配列に書き込んだら、訳の分からないStringBuilderクラスなど使わなくてもいいのではないかと考えました。
そこで、当然、私の知識ではchar[]を使えばいい、はずです。
この間、3日悩みました。
正しくは、byte[]でした。

文例などに、byte型とかあるので、何だろうかとは思っていました。




200619
C#、型

C#の変数の型について、大して違わないだろうと、これまで何も調べずに使っていました。
と言いますか、どこに書いてあるか分かりませんでした。
最近、型変換がうまく行かないので、探していて、ようやく、分かり易いページを見つけました。

思っていたものと違いますね。
charは16ビットです。Unicodeのせいでしょうかね。
byteという型があって、これが8ビットです。1バイトですね。
intは32ビット、とあります。

Cでは、
charが8ビット
intが通常32ビット、
shortが16ビットとあります。ただ、Cはコンパイラ次第のようです。

念のため、VSのCではどうなのか、調べたのですが、見つけられません。
いえ、検索すると、intが4バイトというページがあります。32ビットですね。
ただ、残念なことに、これがどの言語の規定なのかが分かりません。
考えると、OSの32ビットと64ビット違いによる関連はないのでしょうかね。少し心配です。

HSPでは、
変数の宣言がありませんので調べるのに苦労します。
intは型変換です。小数点を切り捨てるのに使います。多分。
基本が整数なので、普通に割り算すると整数が帰ります。多分。
10進数の範囲は32ビットと書いてあります。これが制限なのでしょう。


200617
VS、上書き保存
Cの編集中、VSのエディタで上書き保存のアイコンをクリックするとダイアログが開いて、出力-デバッグ.txtというファイルを保存しようとする。
どうやら、コンソール出力の内容を保存するみたい、リダイレクトだったか、既定かな。便利と言えば便利。
コンソールを閉じていても出てくる時がある。
何か知らない構造があるのだろう。
200617
C、open
ファイル読込の際、rでもrbでも同じ結果になる。読込方次第か。
fp = fopen(fpath, "r");
200617
C#、byte[] bytes
byte[] bytes = SiftJISenc.GetBytes()について調べてみました。

76C2CC・・というテキストを読み込ませ、
変数に代入し、直下にブレークポイントを置くと、実際の数値をみられます。

データは以下の通りです。
bytes[0]=55= "7"
bytes[1]=54= "6"
bytes[2]=67= "C"
bytes[3]=50= "2"

つまり、アスキーコードが入るという事です。

ついでに、文字に戻すには、
char mo = (char)bytes[0];
char mo2 = (char)bytes[2];
UTF-16で戻ってしまう。困った。(これは間違い、勉強不足の頃の話)

200617
C#、ブレークポイント

Cではどこにでもブレークポイントが置けます。
C#ではコードのある行でないと置けません。
これが分からずに、再起動を繰り返しました。

200616
スクリプト、コード

エディタで作るプログラムのソースファイルの中身をなんというか、迷っていました。
今後は、HSPはスクリプト、その他の言語はコードと表現する事で統一します。
HSPのエディタは、HSPスクリプトエディタとなっています。
VSの方はMicrosoftVisualStudioCommunity2019となっていて、ここでは判断できませんが、ヘルプの中にはコードと書いてあります。

200615
C、strcat
strcat(aa,bb);
この前に、aa[0]='0';が無いとエラーになる。

200615
VSCode、HEX表示

VCCodeに16進表示の拡張機能をインストールしました。
下のプログラムの確認の為に使います。
この操作方法に毎回迷います。どうしたら16進表示になるのかです。

あちこちメニューをめぐって何とかなるのですが、今回間違いのない方法を見つけました。多分。
ファイルを読み込んで、ファイル名が表示されている所を右クリック、
そのプルダウンメニューの最下部にShow Hexdumpと出ています。

Shift_JISファイルが、いつも、文字化けしています。UTF-8で読み込まれています。
下のエンコーディングの所から、読み直すことが出来ますが面倒です。
ウーザー設定に初期設定がありました。

200611
C#、StringBuilderクラス、言語別実行速度比較、poke
C#で満足できるだけの速度を出せました。
ネットは、早い、という記事を見ます。ここまで信じられない話でした。
恥ずかしながら、ここまでのバタバタをまとめておきます。

作業は、テキストファイルの16進表示です。100KBのテキストファイルを変換してみました。
(実際には、その他、多少の副次的な作業もするのですが、中心の作業は16進変換です。)

という事で、forにしろrepeatにしろ、100000回のループが必要です。
最初にHSPで作ったものは、100KBのファイルを処理するのに11分かかりました。
いつものやり方で、冗長なスクリプトで作るとこうなります。
これは、スクリプトを見直して、39秒までには縮めました、(下の一覧表の*列の記号で、A、以下同じ)
しかし、この速度では役には立ちません。

そこで、コンパイラで、となります。
VisualStudioCommunity2019をインストールしました。
ついでに、VSCodeも落としました。
(後で気づいたのですが、このVSや、VSCodeには、16進表示の機能が付いていました。)

色々の言語を試しましたが、総合的な問題でC#に行き着きます。
当初、C#では期待通りの速度は出ませんでした。HSPより多少いいか、という程度でした。
そこで、調べていたら、文字列の連結には、StringBuilderクラスというものがあって、これが早いそうです。
以下、このStringBuilderクラスに到着するまでの経過です。

最初に、VBで試しました。
しかしながら、付け焼き刃の知識では何ともなりません。
VSの文字コードは、基本Unicodeだそうです。
ここまで扱ってきた文字コードはShift_JISだけでした。
Shift_JISのファイルを読み込んで、Unicodeで処理されるので、多分、変換してShift_JISのコードを出力する、となると思いますが、この変換がうまく行きません。
(この時点では、こんな風に考えていましたが、C#で何とか出来た現在、C#もVBもほとんど変わらないみたいですので、今なら何とかなるのかも知れません。Shift_JISで読み込んで、そのまま処理して、出力もShift_JISを指定して出力する。でしょう。)

対象のテキストファイルを、最初からメモ帳などでUnicodeに変換して処理するといいじゃないか、となります。
長年の事で、これが許せません。BOMとか4バイト一文字とかに抵抗があるのです。
やはり、文字は1バイトで処理できないといけません。(根拠なし。面倒だというだけです。)

そこで、先のVSでCに挑戦しました。
C言語については、昔、ほんの少しですが経験がありましたので。
便利な世の中です。ネットを探すと、例文が沢山出てきます。
それを継ぎはぎすると何とかなるものです。以下同じ。
それに、VBで悩んだUnicodeが出てきません。Shift_JISをShift_JISのまま読込め、そのまま処理出来ました。
VCでは、コードのファイルもShift_JISで保存されています。

Cで試すと、100KBの作業でも78ミリ秒で終わります(B)。
ただ、残念な事に、コンソールモードです。
Cではデスクトップの画面が作れません。どんなに探しても、フォームエディタを見つけられませんでした。

これには、便法ですが略式の解決方法があります。
画面処理はHSPで済ませて、実際の作業は、execでCの実行ファイルを起動します。H
この方法でやると、100KBの処理を700ミリ秒で終わります。(C)
待たされたと感じない時間です。
これで、実用上は問題ないのですが、ちょっと見苦しい気がします。

そこで、C++です。
確かに、ネットの情報を駆使してVSのメニューを掘り下げると、フォームエディタは出てきます。
ただ、ビルドしてもコンソール画面しか出てきません。
コードの書き方も全く分かりません。文法がCとはかけ離れています。
ネットにはCと大して変わらないとありますが、とてもそのようには思えません。

やむを得ず、C#を試しました。
C#だとフォームエディタは簡単に出現し、編集もできました。ボタンやテキストボックスなど簡単に取り付けられます。
マウスのドラッグでボタンなどの配置場所を指定できます。
HSPだと配置場所はスクリプトに座標の数字を書き込んで行きますので、C#の方が簡単です。
コードの配置場所もすぐ見つかりました。
private void button1_Click(object sender, EventArgs e)
の下に書けばいいのです。
ここに、ネットからの例文をコピーして多少変数をいじるだけで動きます。

で、試した結果、100KBの処理に16秒かかりました。ミリ秒ではありません。(D)(E)
こんなものかと思いました。コンパイラではありません。C#は中間言語なのです。
HSPよりはいいけど、秒の単位が必要なら、使うのに躊躇します。
そこで、順番としてはC++に向かったのですが、上のメモの通りです。
この間、他の言語も調べました。
GoとかFreeBASICとかです。
いずれも、デスクトップ画面を作れるかがよく分かりませんでした。

やむを得ず、C#に戻りました。
ここでようやく、StringBuilderクラスを知りました。
これを使うと、驚きです、同じ処理が151ミリ秒で終わります。(F)(G)
C並みとは言えないにしろ、これに近い、抵抗のない数字です。
それに、C#だけで画面から処理まで完結できます。

これで、ネットでの評価に近い数字になりました。
C++の迷路をさまよう必要はなく、HSPからCの実行ファイルを呼び出す必要もありません。
手探り状態ですけど、C#で何とかなりそうです。

一段落した所で、各言語のコードやスクリプトを比較していたら、幾つか気付いたことがあります。

HSPでは、文字列の足し算(連結)をしていました。
ここまでの経過で、文字列の連結には時間がかかる事を知りました。
HSPにも文字列を直接操作する手段があります。pokeです。
元々、変換元からの取り出しにはpeekを使っていました。
それでも、pokeを使わなかったのは、peekはメモリからの読み出しで、pokeはメモリへの書き込みです。
これに、多少の躊躇がありました。
それに、多少は早くなったとしても、そんなには違わないだろうと思っていました。
しかし、C#での事で、試してみる価値がありそうな気がしてきました。

HSPのスクリプトをpokeで作り直してみました。
爆速です。
39秒かけていた100KBのテキストの変換が0.516秒で終わりました。ミリ秒の単位で終わります。(H)
こうなると、HSPでの作業に抵抗はありません。
C、C#での騒ぎが何だったのかという事にもなります。

Cでは最初からポインタと配列で作業しています。つまり、メモリへ直接書き込んでいました。(B)
偶然、参考にした文例がよかったのでしょう。
あ、恥ずかしながら、配列とポインタが同じものだ、ぐらいは知っていました。

Cにも文字列の連結があります。一応。これも試しました。
連結だと、Cでも遅くなります。100KBの変換で2.8秒かかりました。(I)(J)


処理にかかる時間に関して一覧表を作りました。
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) Cを1とした倍率   処理時間(秒) Cを1とした倍率
A HSP 1.703 106.4   39.860 511.0
B C(コンソール) 0.016 1.0   0.078 1.0
C HSP+C 0.653 40.8   0.703 9.0
D C#(debug) 0.393 24.6   15.683 201.1
E C#(releace) 0.319 19.9   8.092 103.7
F C#(sb:debug) 0.133 8.3   0.155 2.0
G C#(sb:releace) 0.135 8.4   0.151 1.9
H HSP(poke) 0.329 20.6   0.516 6.6
I C(strcat) 0.265 16.6   5.563 71.3
J C(sprintf) 0.140 8.8   2.813 36.1


以下は作業中のメモです。
System.Diagnostics.Stopwatch()を使って、時間を表示させました。
(HSPでは、GetTickCount、C#では、GetTickCount())

C#の作業時間、(F)
20KBで、(0, 2, 0, 123, 8, 合計133ミリ秒)
100KBで、(1, 12, 0, 132, 10, 合計155ミリ秒)
という結果です。いずれもデバッグモードです、驚きました。

releaceモードだと、(G)
20KBで、(0, 2, 0, 133、合計135ミリ秒)
100KBで、(1, 10, 0, 140、合計151ミリ秒)

合計以外のコンマ付きの数字は、各セクション毎の所要時間です。
テキストファイル読込、16進数変換、16進数整形、mesboxへの表示、16進数ファイルの保存、の順番で表示しています。
コンマ付き数字が4個の結果は、mesboxへの表示と16進数ファイルの保存の合計です。

こうしてみると、時間のかかっているのは、変換結果のボックス表示の時間です。
他の作業には時間がかかっていません。
コードの間違いか、何やら、タイムラグみたいなものがあるのかも知れません。
あるいは、並行処理みたいなもので、実際の処理は他所でやっているとか。
あるいは、グラボの性能が悪いだけ、かも知れません。


簡単にそれぞれのスクリプトとコードを書き出しました。
肝心の所だけです。本来は、多少の修飾があります。

HSP、単に文字列の結合、(A)
repeat len
  one=peek(sjistext,cnt)
  hextext=hextext+strf("%02x",one)
loop
実行結果は、20KBで、1.703秒、100KBで、39.860秒


C、コンソールモード、配列に直接書き込み、(B)
for (i = 0; i < size; i++) {
  one = buf0[i]
  mae = one / 16;
  sprintf(mozi, "%X", mae);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
  usiro = one % 16;
  sprintf(mozi, "%X", usiro);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
}
buf[ctr] = '\0';
結果、20KBで、16ミリ秒、100KBで、78ミリ秒、(デバッグモードのデバッグなし開始)


C#、単に文字列の追加、(D)、(E)
for (int ctr=0;ctr<len;ctr++)
{
  hextext += bytes[ctr].ToString("X2");
}


C# StringBuilderクラスを使って文字列を追加、(F)(G)
System.Text.StringBuilder hextext = new System.Text.StringBuilder();
for (int ctr = 0; ctr < len; ctr++)
{
  hextext.Append(bytes[ctr].ToString("X2"));
}
string hextext0 = hextext.ToString();
結果は、20KBで、135ミリ秒、100KBで、151ミリ秒



HSP、pokeで書き込み、(H)
repeat len
  one=peek(jistext,cnt)
  mae=one/16
  asc=strf("%X",mae)
  poke hextext,ctr,asc
  ctr=ctr+1
  usiro=one\16
  asc=strf("%X",usiro)
  poke hextext,ctr,asc
  ctr=ctr+1
loop
poke hextext,ctr,0
実行結果は、20KBで、329ミリ秒、100KBで、516ミリ秒


C、コンソールモード、連結方式でも試してみました。(I)
strcatで連結していきます。
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  sprintf(mozi, "%X", mae);
  strcat(buf, mozi);
  ctr++;
  usiro = hitomozi % 16;
  sprintf(mozi, "%X", usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果(H)、20KBが、265ミリ秒、100KBで 5563ミリ秒。(デバッグモードのデバッグなし開始)


C、更に、sprintfを連結して二文字ずつ作業すると、(J)
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  ctr++;
  usiro = buf0[i] % 16;
  sprintf(mozi, "%X%X", mae, usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果、20KBで、140ミリ秒、100KBで 2813ミリ秒(デバッグモードのデバッグなし開始)





200609
C++のプロジェクト、フォーム

上に新しいメモあり、

C#の速度が、HSPに比べたら早いけど、驚くほどの速さではない、Cに比べたらかなり遅い、という状況でした。
そこで、C++でフォームアプリに挑戦です。
何しろ、プロジェクトの作り方から分かりません。フォームのデザイナが出てこないのです。
ネット参照でようやくたどり着きましたのでメモしておきます。

新しいプロジェクトの作成
上の窓で、C++、Windows、コンソール、を選んでおく。
CLR空のプロジェクト(.NET Framework)を選ぶとビルドが通らない。。
CLRコンソールアプリ(.NET Framework)を選ぶとビルドできる。
次へ
プロジェクト名とフォルダを適当に指定する。
作成
エディタのプロジェクトメニューで、新しい項目の追加、
UI、Windowsフォーム、を選んで、(UIがないのは今までの選択が間違っている)
追加
データが失われる可能性云々のエラーが出る。この場合は、
ファイルメニューで、ソリューションを一旦閉じる
ソリューションの一覧が出るので、今作ったソリューションを開く

何とか、フォームを使う所まで到着して、ボタンをダブルクリックでコードを書き込む場所までは分かりました。
しかし、分かりません。構文が他の言語とはあまりに違いすぎます。
ここで中断(というより放棄)して、DLLを勉強してみます。

そのボタンのコードですが、
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
というものがダブルクリックで生成されます。
ダブルクリック以外に冷静な方法がありそうなものですが、分かりません。

どこか間違っている様です。ビルドしてもフォームが出てきません。main()が?

C#では、同じ部分がこうなっています。
private void button1_Click(object sender, EventArgs e)
この程度だと、我慢して見られます。

どうにもこうにもC++が分かりません。
そこで、C#に戻って、調べました。
文字列の連結に使うStringBuilderクラスというものに気付きました。
これを使うと、C並みとはいきませんが、Cと同じ桁で実行できます。
C#に戻ります。

200609
C#、実行速度
この項、上に、新しいメモあり。

ネットではC#の実行速度は、コンパイラ並ではないにしろ、コンパイラと遜色ないような記事が多いです。
それならと、目下勉強中です。
ある程度、作り上げて、実際に試してみました。結果、HSPよりも少し早い程度です。
いえ、まだ途中経過で、改良の余地がある状況ですし、完全に同じ作業にはなっていないはずです。
とりあえずの結果です。

何しろ、ほとんど文法が分かっていないのに、ネットの文例をつなぎ合わせていくと、動いてしまいます。
そういう作りですので、まだまだ不十分だと思います。

その上で、
20KBのテキストファイルの処理がHSPでは1.7秒でした。

これをC#では、約400ミリ秒、です。
C#の計測結果、debugモードで、(10, 248, 248, 393ミリ秒)、12, 261, 0, 142(合計415ミリ秒)
releaceモードでビルドした実行ファイルで、(11, 183, 183, 319ミリ秒)

やはり、C#でもテキストボックス等へ大量のテキストを表示させると、時間がかかっています。
これはHSPでも同様で、どちらも表示は部分的に省略するようにしています。
どちらも、条件は変わらないと思います。

100KBのテキストで、HSPで40秒でした。
C#の計測結果は、debugモードで:(32, 15541, 15542, 15683ミリ秒)、36, 16006, 0, 155(合計16197ミリ秒)
同、releaceモードでビルドした実行ファイルで:(12, 7953, 7954, 8092ミリ秒)
C#では、8秒という事になります。

ここで、初めてreleace版で生成した実行ファイルで試してみました。
かなり早くなっています。こちらが本当の速さという事でしょう。
Cでも双方試しましたが、差は分かりませんでした。Cでは差が出るほどの作業ではなかったという事かも知れません。

やはり、テキスト表示は部分的に省略しています。
なお、C#で、テキストを省略せずに表示させると、29秒かかります。つまり、ボックスへの表示に13秒かかっています。
上二つ、Cも計測してあります。

まとめると、(前半の作業時間)
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP 1.703 1.0   39.860 1.0
C#(debug) 0.393 1/4.3   15.683 1/2.5
C#(releace) 0.319 1/5.3   8.092 1/4.9
Cのみ 0.016 1/106   0.078 1/511

HSPと比べればかなり成績が上がりましたが、8秒では心理的にも抵抗があります。
もう少し対策を考えます。

ネットで調べていたら、StringBuilderクラスというものがあって、文字列の連結に強い、そうです。
試しました。
20KBで140ミリ秒、(0, 3, 0, 137、合計140ミリ秒)
100KBで175ミリ秒、(12, 14, 0, 149、合計175ミリ秒)
という結果です。いずれもデバッグモードです、驚きです。
これで、ネットでの評価に近い数字になりました。C++のジャングルをさまよう必要はなく、C#に戻れそうです。


ループについて
この間の作業で、C#でも単純で数の多いループの最中に、帰ってこない状態になることがありました。
フォームの右肩のXのボタンが赤く表示されます。マウスカーソルが行っている状態です。
数秒ですので、何も試していませんが、ちょっとした暴走状態だと思います。
終了だけは出来ます、という意味かも知れません。
HSPではwaitを入れない単純なループでよく経験します。



漢字モード
VSのエディタで漢字がONにならない場合があります。
ビルドしてエラーも結構出ていますので、何やら暴走させているのかもしれません。
エラーが出ている間、デバッグ実行中にはONに出来ないようです。
コードを書き換えられない様にしてあるのかもしれません。



200607
VS、灰色の点々

自己書き換え、とでもいうのかな
VSのエディタに灰色の点々があります。よくできていると思います。
マウスを近づけるとメッセージが出てきます。
int宣言の所で、不必要な代入、とありました。
エラーにはならないけど無駄だという程度なのでしょう。

str.Replace("A", "B")

文字列の一部を入れ換えるのに
str.Replace("A", "B")
というものがあります。
これをそのまま信用して、
str.Replace("A", "B");
と書きます。
いくら待っても書き換わりません。

HSPに同様のコマンド、strrepがあります。
strrep strr,"A","B"、とすると、strrが書き換わります。

C#では、
strr=str.Replace("A", "B");
が正解の様です。

文字コード指定、文字コードの確認
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

私が扱うテキストファイルの形式は全部Shift_JISなので、苦労しています。
VSではUnicodeが標準みたいですので。
上の構文でファイルのエンコードを指定できるみたいです。
最初に指定しておくと、いい様です。
と言いますのも、ファイル読込の時に指定して、再度書き込みの時に指定するとエラーになります。
例の赤線、インテリセンスが出て、既に定義されているとなります。
コンパイルは通るのかもしれませんが。

さて、問題は実際にShift_JISで保存されているのかが心配です。
構文の意味がよくわからずに使っていますので。
最近は、いい時代になりました。
ネットで探せば、大抵の例文が出ています。
例え初めてのC#でも、面倒な作業でなければ、なんとかなっています。
ですが、上のような心配もします。

そこで、解決策に気付きました。
半角だけのテキストの場合に、文字のエンコードを確認する方法です。
メモ帳ではUTF-8と表示されます。TeraPadでは、Shift_JISと表示されています。
プロパティなどで、バイト数を見ます。
同じもので、エンコードがはっきりしているファイルが必要です。
私の場合は、同じものを、HSPで作っていますので、Shift_JISとはっきりしているものがあります。
それと同じバイト数ならShift_JIS、少し大きいならUTF-8となります。

上のメモは、BOM無しUTF-8だとダメみたいです。
しかし、VSで出力されているものはBOM有りでした。

検索と置換、インテリセンス
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

上のコードのencをShiftJISencに置換したいと考えました。
ネットを見ていたら、同じような文例を見つけ、こちらの方が分かり易いなと思った次第です。
それに、多分、この単語は適当に変えていい部分だと気が付きました。

で、エディタの編集メニューにある検索と置換から実行しようとしました。
すると、encの部分は良いのですが、どうやら.Encoding.GetEncodingにあるEncの部分も置換対象に含まれている様子です。

そこで、いちいちスキップする方法はありますが、手間は変わりません、手書きで変更していくことにしました。
手書きと言っても最初にShiftJISencをコピーしておいて、対象のencを探してペーストしていきます。

ここで、ありがたい機能に気付きました。
よく出てくるインテリセンスの赤い点線です。これがとても役に立ちます。
最初に、定義の?最初の行の、encを書き換えると、残りのencが全部赤い点線になっています。
先ほど度違って、今度は変更が必要な部分だけです。
これを順番にペーストしていくだけでした。



200605
C#、ツールボックス
フォームを作るのに、C#が簡単という記事を見て、ちょっと始めてみました。
VSにC#も全部入っています。多分。
見よう見まねで作っていきます。
ネットからの切り貼りで何とかなるというのが、便利というか恐ろしいというか。

確かにフォームデザインが簡単にできます。できました。
それでもやはり試行錯誤です。
失敗した時、意図通り出来上がらない時、フォルダーごと削処して、プロジェクトの作成からやり直しです。
いえ、どこが間違っているのか分かりませんし、修正なんかできるはずもありませんので。

何回かやり直しているうち、ツールボックスからボタンbuttonという項目がなくなりました。
新しいプロジェクトを作る際、.NETCoreと.NETFrameworkを行き来している時でした。
フォームにボタンが貼り付けられません。
困って、色々メニューを探したら、それらしきものがありました。ツールボックスのリセット、という項目です。
ツールボックスの上での右クリックメニューです。
これで復活しました。

長い文章を表示するボックスをつくるのに、TextBoxだと一行しか表示できそうにありません。
試してみると、よさそうな物に、RichTextBoxがありました。
これだと、簡単に、縦長のボックスが作れます。
しかし、よくよく調べると、TextBoxでもよかった様です。オプションでMultilineをセットすると縦に拡張できました。
今のところ、どちらが正解なのかは分かりません。

TextBoxにも最大文字数があるようです。32KBみたいです。
ただ、こちらはMaxLength=0とする事で簡単に変更できるとの事です。

さて、迷いごとを一つ、
System.IO.File.Exists();、
という構文と、

using System.IO;
.IO.File.Exists();
という、どうやら二つが分離されている構文があります。

どうやらusingがdefineみたいなものの様で、以下省略できるという意味の様です。
迷いますね、統一してもらいたい所です。


200529
文字列の比較

Cで文字列の比較で躓きました。
if (argv[1] == "ag")です。全く意図通り動いてくれません。

試しに、
printf("1番目の引数は:%s %d\n",argv[1],strlen(argv[1]));とすると、
ちゃんと
1番目の引数は:ag 2、とでます

正解は、Cでは文字列の比較は、==、では意味がなく、
if (strcmp(argv[1], "ag") == 0)
だそうです。

思い起こせば、HSPでも同じような事情があります。ただHSPでは=までは通じます。
大小の比較はできません。



200528
CTRL+A

各種編集作業の時便利なキーがあります。
Ctrl+C、Ctrl+V、Ctrl+X、Ctrl+A、です。
コピー関係のショートカットです。
特にCtrl+Aは重宝しています。全て選択、ですね。

私は、HSPの作業中に途中の経過をクリップボードに転送しておきます。
メモ帳などに貼り付けるのです。
作業後にそれを見て、意図通り動いているか調べます。

この時、前回の経過が貼り付けてあるメモ帳の表示を入れ換えるのに、Ctrl+A、Ctrl+Vで済みます。
ただ、最近、これらのショートカットを多用していると、効かなくなることがあります。
コピーもペーストも出来なくなります。

原因不明です。特に、HSPのエディタ上で顕著です。HSPを再起動すると回復します。
最近、Cを始めたので、何か悪影響が出ているのかもしれません。
そのものずばりで、clipsetを多用している事が原因かもしれません。


200524
VSのエディタ、赤い波線、インテリセンス
VSのエディタでCの作業中、全く関係ないファイルから数行のテキストををコピーして持って来ました。
すると、赤い波線が出て来ました。理由はよくわかりませんが、エラーの様です。
赤い波線は、例えば、行末にセミコロン;、を付け忘れた時に出てきます。心穏やかではありません。
どうやら、この波線をインテリセンス、というみたいです。やはりエラーです。

しかしながら、コピーしたものは日本語のテキストで、貼り付け(ぺースト)した場所は、/**/で囲んだ注釈行の中なのです。
構文の間違いではありません。
200526追記
この件、プログラムをVer16.6.0へアップデートする事で解決しました。した様に見えます。
以下、無意味なドタバタの記録です。200609再発しました。
まず、VSで悩まされている、日本語コードを疑いました。
調べてみると、ファイルの日本語コードは、コピー元もコピー先もShift_JISです。
コピー先の、VSのC言語のソースも、何故かShift_JISなのです。
VSのエディタで、どのように扱っているかは調べようがありませんが、保存してあるソースファイルはShift_JISです。

試しに、保存してあるソースファイルをメモ帳で開いて、同じ内容を貼り付けて、VSを立ち上げてみました。
結果、同様に赤い波線が出てきます。

特殊な漢字を使っていて、それに反応しているのかもと調べてみました。
昔、機種依存文字とか、コントロールコードとかの絡みで、こういう事がありました。
一行ずつ、一文字ずつ削除して調べました。それでもはっきりしません。
消える場合もあります。消えない場合もあるのです。どの漢字か特定できません。
しかも、全部削除しても波線が残る時もあります。

ただ、コンパイル、ビルドは通ります。
この用語がよく分かりません。
昔は、実行ファイルを作る作業をコンパイルとかリンク、メイクmakeとか読んでいたと思いますが、VSには、今の所、どちらも出てきません。
後日、調べて、実行ファイルを作るのはビルドだそうです。いつもビルドした後デバッグしていたので、デバッグで実行ファイルが作られるのかと勘違いしていました。
更に、releaseモードでビルドしたものが正式の実行ファイルの様です。
debugモードでもビルとすると実行ファイルができます。
同じものかと思っていましたが、ファイルを比較しててみたら。サイズが違います。
releaseモードの方が小さくなっています。
どこにも書いてありませんが(どこにも見つけられませんが)、多分、デバッグモードの方は、デバッグの為のコードが含まれているのでしょうね。暴走しない様に。
実行速度にも違いがあります。releaceの方が早いです。

そのビルドやデバッグですが、波線があってもできます。実行できています。
これはやはり、波線の方が間違いだろうと考えるようにもなりました。

ある時、偶然気付きました。
窓で作業している時に発生します。
全画面で作業している時はこの現象は出てきません。
ただ、窓で発生している状態で、全画面にしても消えません。
逆に、全画面でコピーして、窓に変えた場合は、発生する場合も発生しない場合もあります。
困ったものです。
貼り付けたものを、元に戻すコマンドで戻しても消えない事が多いです。しかし、そのまま全画面にして、赤線の出た状態で終了して、再度起動すると消えていたりします。
色々試すと、もう滅茶苦茶です。

プロジェクトをもう一つ作ってあって、そちらではこの現象は発生しません。
そこで、考えました。
最初からやり直す事にしました。
下のメモにある方法で、既存のCファイルからプロジェクトを作り直してみました。
何しろ、ソースファイル一つのプロジェクトです。
そのファイルを一つだけコピーして作り直すだけです。
これで見事解消しました。

思うに、原因は、
この作業中にソースファイルを入れ換えたことです。
なんの為だったかおぼろげですが、どこかのコメント行を追加したか、コードの一部を他所から持って来たかで、ソースファイルを同じ名前で入れ換えたことがあります。
多分、このせいだと思います。
試してみると簡単に分かることですが、面倒なのでやりません。
VSのプロジェクトは、多数のファイルが出来ています。
その中に、何かエディタ上の変更に付随して書き換わるファイルがあるのではないだろうか、という事です。
VS以外のエディタで、途中で編集をすると、何か辻褄の合わない事が起きるのではないのか、というのが、現在の推定です。

200526追記
再発しました。また赤い波線です。
思い当たる直前の作業は、
まず、ちょっと暴走気味で、メニューの変な所をクリックして、帰ってきませんでした。
どうするかのダイアログが出て、終了を選びました。
メモ帳からの文章をコピーで持って来ました。
#define文で、一行に//を2か所使いました。
この辺りで波線に気付きました。
やはり、窓での作業中でした。全画面にすると、消える時も消えない時もあります。
今回は、二つのプロジェクトで同時に発生しました。

行き詰って、最後に、プログラムのバージョンアップが無いか調べたら、新しいものがありました。
更新しました。
今の所、発生していません。波線は出ていません。まだアップして一日目ですが、平穏です。

200609
再発しました。
コメントの、/*、*/、の部分が赤い波線になっています。
今回は、変な作業はしていません。いえ、他のテキストからコピペぐらいはしたかもしれません。
200610
また、更新がありましたので、実行しました。Ver16.6.2になっています。
再起動したら、消えています。
200616
しばらく出ていませんでしたが、今日出ました。赤い波線です。
何故か、ほぼ全体的に発生しました。
終了、起動を何度か繰り返すと消えました。
発生は、エラーと言いますか、例外が発生した直後に出るようです。
一旦VSを終了し、再開すると大体は消えます。
更新は関係ないかも。更新したら、再起動しますからね。
こんなものなのかも知れません。



200522
既存のCのファイルからVSのプロジェクトを作る

既存のC言語のコードからVisualStudioのプロジェクトを作る段取り。
これまで、何度か試していて、ここまで、うまく行ったり行かなかったりでした。
今日、改めて試して、すんなり成功しましたので、メモしておきます。

別のプロジェクトで使ったフォルダ全体をコピーして、フォルダとソースファイル名だけ変えて、新しいプロジェクトを立ち上げても、うまく行きませんでした。対策を知らないだけかもしれませんが。
ソースファイルだけを、名前を変えて新しいフォルダにコピーして、この方法でプロジェクトを作るとうまく行きます。
(単独のソースの場合です。)

まず、
VSの起動画面の、プロジェクトの選択画面で、コード無しで実行、を選択します。

何も無い状態でVSが開くので、
メニューの、ファイル、新規作成、既存のコードからプロジェクトを作成、を選択していきます。

作成ウイザードが開くので、
作成するプロジェクトの種類はVisualC++、を選択し、次へのボタン、

プロジェクトのファイルの場所は、あらかじめ準備していたフォルダを、
プロジェクト名は、準備してある既存のCのコードのファイル名を入れます。
ここ、あらかじめ、既存のファイル名、フォルダ名、プロジェクト名の3つを同じ名前に合わせています。ただ、これが必須かどうかは不明です。
この窓には、都合3個のチェックボックスがあります。
一つは、次のフィルダー云々「フィルダー」となっています。
既定で全部チェックされていますので、そのままです。意味は分かりません。
次へのボタン、です。

つぎの画面で、プロジェクトの種類に、コンソールアプリケーションプロジェクト、を選択します。
ここの選択肢で、Windowsアプリケーションが既定の様ですが、多分、これを選ぶとまずいのだと思います。
後、次へのボタンで数画面ありますが、意味不明で、いずれも既定のままです。
ですので、完了ボタンで終わっています。

この設定で始めると、先のSDL関連はチェックされていません。
ですので、最初から、ビルドエラーは出ません。


200522
VSでコードのファイルがリソースファイルのフォルダに属している

何やら、試行錯誤でプロジェクトを作った際、よく見ると、Cのソースファイルが、ソリューションエクスプローラーでリソースファイルのフォルダに属している問題。

ファイル一つのプロジェクトで、ソースファイルのフォルダには何もありません。
これで、期待通りに実行は出来ているので、実用上の問題はないのですが、少し不安です。

そこで、思い切って入れ換えてみました。
方法は、
ソリューションエクスプローラーのファイル名の右クリックメニューに削除という項目があります。
これを選ぶと、除外か削除か選択するように促されます。
そこで、除外を選びます。削除を選ぶと、実際にファイルが削除されそうでした。
次に、ソースファイルの右クリックメニューで、追加、既存の項目、と進んで、該当ファイルを選択すると、無事入れ換えが出来ました。
ビルドもデバッグも同じようにできます。変わりません。


200521
VS2019、ビルドエラー、C4996

これまで、ほどほどうまくいって、期待通りの結果を出しているCのプロジェクトがあったので、このコードを使って別のファイルを作ろうと、新しいプロジェクトを立ち上げました。

新しいプロジェクトを作り時、試行錯誤で色々試したので、どの方法だったか思い出せません。
何やら、ソースファイルに、元のファイルからコードを全コピーして持ってきたと思います。
ところが、全く同じコードなのですが、ビルドエラーです。
fopenなどがエラーになっています。
元のコードでは警告で済んでいる所です。

何か対策があるはずと調べてみたら、
ソースファイルを反転させて、(右クリックメニューにあるプロジェクトから進んでも同じです。)、
メニューの、プロジェクト、プロパティ、C/C++、全般、と進んで、SDLチェック、という項目を、いいえ、にすると解決しました。
プロジェクトの作り方、初期設定が間違っていたのだと思います。
多分、コンソールではなくWindowアプリを選んでいたのだと思います。

なお、この問題、上の200522の記事で、根本的な(多分)解決方法を見つけてあります。

200519
malloc

Cでテキストファイルを読み込もうとしました。
250KBほどある巨大なファイルです。
大きいファイルだと、読み込んだり、作業するのが面倒なので、最初は小さなファイルから始めました。

まあ一応、予定通りの動きをします。
そこで、目的のファイルを読み込ませてみます。
エラーです。

試行錯誤と合わせて、ネットで調べた結果、分かったことです。
文字型配列の要素数に限度があり、大きな配列を宣言する時は、mallocを使って領域を確保する必要があるとの事です。
スタック領域、ヒープ領域という言葉で説明されています。
普通の宣言では、スタック領域に確保され、こちらだと、通常、あまり大きな領域は確保できない。
思い起こすと、アセンブラで言う、push、popの領域でしょうかね。
ヒープ領域は、この制限がなく、こちらを使う時には、mallocを使って確保する、のだそうです。

200512
文字コード、改行
Cでのテキストファイルの保存に関して
改行が余分に入って保存された事があります。
メモ帳で見たら、Macintosh(CR)となっていました。
TeraPadでは、SJIS CRと表示され、やはり改行が余分に入っていました。
ワードパッドでも試しました。改行されていませんでした。こちらでは何と判断されているか分かりませんでした。

余分な改行の原因はすぐ分かりました。と言っても試行錯誤の結果です。
fopenを "w"で開くと別にCRが付加されます。CRLFの他にCRが付きます。
"wb"で開くと、そのままです。
そうです。テキストをバイト単位で扱っているプログラムです。
ですので、16進のダンプも打ち出せます。
先の改行を挟む所は、通常は0d,0a、(CR,LF)となるべきところで、
余分な改行が入っている分は、0d,0d,0a、(CR,CR,LF)となっていました。
読込の時は、普通に"r"でfopenしても問題は出ていません。

なんとなく、世間では常識的な話なのかもしれません。

200512
プログラム言語、VisualStudio2019、文字コード

ほかの言語についても、多少の知識はあります。あるつもりでした。
現に、PCには古いコードを残しています。
1998年にCを、2003年にC++をやっていた形跡があります。LccとかBccとかのフォルダがあります。
コードもexeファイルも残っているので、試しに実行してみましたが、現在の環境では動きませんでした。
タイムスタンプから見て、Win98とかXPの頃でしょうかね。XPの環境はありますので、実行してみましたが、動きませんでした。

PCを作り変える際、データディスクだけは、そのまま付け換えるなり、コピーするなりして移動させていましたので、当時のOSが何だったかは、はっきりとは思い出せません。

他に、COBOLを勉強していた時期があります。
かすかな記憶では、COBOLは計算が苦手で、平方根の計算が出来ませんでした。
そこで、ニュートン法を使って試行錯誤で平方根を探すルーチンを作った覚えがあります。

具体的には、平方根は、元の数字以下になる事は分かっていますので、まず、元の数の半分の値を2乗します。
さすがに2乗は掛け算です。どの言語でもできます。
この結果が、元の数より大きければ、更に下半分に答えがあることが分かります。
小さければ、上半分です。
ですので、どちらかをさらに半分にした数字で試していきます。
これを必要な桁数まで探していくだけです。
これをある程度進めていくと、小数点以下で変化しない桁が増えていきます。
その変化しない桁は有効な数字と考えていいはずです。多分。

このルーチンは、当時は貴重だったのかもしれません。
オフィスコンピュータのメーカーのSEの方から、コピーさせてくれと頼まれて、コードの入っているFDを渡した記憶があります。
何しろ、当時、COBOLはオフコンでのみ動いていましたので、コンパイルさせてもらう為に、時々、メーカーの事務所に遊びに行っていました。会社にオフコンを導入した際の取引先でした。

BASICに関しては、使っていたPCの数だけありますね。
当時は、各メーカーが独自のパソコンを作っていて、OSもメーカーの数だけありました。それぞれ、ほとんど互換性はありませんでした。
その後、MS-DOSというOSが主流になって、全てMSのWindowsに流れていく訳です。

思い出すのは、沖BasicとN88Basicとの共通のFDを作った事です。
当時は5インチFDでした。2DDとか1MとかのFDの頃です。
双方のBasicで、FATでしたか、データを管理する領域の配置が違っていました。
幸い、当時は、セクター単位で読み書きするコマンドがBASICにもあって、自由に中身を調べ、変更できました。
そこで、互いの管理領域に仮のデータがあるように処理して、アクセスしないようにしていました。

アセンブラも少し勉強しました。MASMとかありました。
当時、Z80でした。haltだけ覚えています。
こちらは、8086に変わった時点で諦めました。
逆だったかもしれません。
ニーモニックでしたか、命令語が一段と増えていました。まあ、様子見、冷やかしでしたので。

さて、本題は、
とにかく、処理の早い言語の導入を考えました。
どうやら、コンパイラならどれでもいいようです。
各言語での速度比較のページによると、BASIC関係以外は大差ありません。いえ、BASICやHSPに比べたら格段に速いです。

真っ先にC言語です。
以前、Cで簡単な計算をする物を作っています。
最初、LotusかExselのシートで作った物を、Basicに移し、C言語に移しました。
更に主流は当時でもC++に移行中で、C++でも作りました。
ところが、C++に至って、クラスだったか構造体だったかが理解できず、挫折しました。
おぼろげな記憶ですが、とにかく、選択肢が多くて、複雑で面倒だなと思ったものです。
その後、現在のHSPを見つけて、ほとんどこれ一本で遊んでいます。
数KBのファイルを扱うものなら、インタプリタでも速度が遅くても問題ないのです。

ここに至って、なにがしかのコンパイラで作ればなんとかかるだろうと、準備を始めました。
VisualStudio2019をインストールしました。
これだと、CでもC++でもVisualBasicでも使えるという事です。しかも無料です。
先の速度比較では、VisualBasicでもHSPより格段に速いとありました。

まず、VB、C++,、Cと試しました。
先に、昔、自分で作った物をVS2019に移そうとしましたが、まずこれが出来ません。
ようやく移行できて、コンパイルすると、ビルドでしょうか、エラーです。
残念なことに、Cでさえ、その原因が分かりません。
どうやら、当時のコンパイラ独特のヘッダファイルとかがあるようです。

それなら、VBなら何とかなるかと、試してみました。
さすがに、VBだと、ある程度工夫すると動きます。
ところが、結果が文字化けします。
理由は、どうやら昔のShift_JISが通用しない事にあるようです。
いまのVisualStudioはUnicode(UTF-8、16)が標準みたいです。
コンバートする方法もあるみたいですが、理解できません。うまくいきません。

最終的にCで組めました。コンソールタイプですが。
ありがたいのは、どうやらC言語だとVSでもShift_JISで扱える事です。
標準なのかどうかは不明ですが、そのままで通用しています。
ソースファイルもShift_JISで保存されています。
ことによると、最初の既存のコードファイルがShift_JISだったので、そのまま引き継がれているのかもしれません。
作業対象のShift_JISのテキストファイルを普通にfopen、fread、fwriteすると、Shift_JISのままで操作できています。



200512
実行速度
現在、このサイトのページを作る事以外にも、色々な作業をHSPで試しています。
その中で、テキストファイルの変換をするものを作りました。
テキストを読み込んで、変換作業をして、再度ファイルに保存するものです。
単純な作業なのですが、バイト単位の作業で、意外と時間がかかります。
100KB程度のファイルで、11分ほどかかっていました。(この点、下に訂正あり。)
これでは、少し、時間がかかり過ぎです。

そこで、他の言語の実行速度を調べてみました。
まず最初に、自分のスクリプトを見直してみる、という事には思い当たりませんでした。
ネットで、他の言語を調べてみると、さすがにコンパイラでは速度は桁違いです。しかも何桁も違います。
そこで、コンパイラを試す事にしました。

200526追記
C言語での作業が一段落したので、結果です。
対象は100KB程度のテキストの変換作業です。作業内容は先のHSPと同じです。
HSPのみでは、11分かかる作業が、Cで作ると、125ミリ秒弱で終わります。0.125秒です。
HSPに比べてCでは、1/5500の時間で済んでしまうという事になります。(この点、以下に訂正あり。)

200530追記
Cでコードを作る際、HSPで組んでいたスクリプトを参考にしました。
ここで、HSPのアルゴリズムを見直しましたので、実行速度に関して、ものすごく冗長に作っていた事に気付きました。
プログラムは、速度より見やすさ優先が昔からの癖で、一回のループで済むところを何回かに分けたりして処理しています。

極端な話、数回のループなら、スクリプトをその数分コピーして済ますようなこともあります。
この方が、安全確実ですので。

やむを得ず、ループ内で複数の作業をする場合、作業の経過が分かるように、中間の処理状況を入れる変数をたくさん作ります。
途中、debugやassertを使って状況を調べられ、作業状況が分かり易くなるのは間違いありません。
ただ、大量のデータを扱う場合、そうも言っておられません。上の通り、たいした事をしていないのに11分かかる様になってしまいます。

Cの方は、アルゴリズムが分かっていたので、一回のループで処理できています。
それに、経過記録など悠長なコードの書き方を知りません、コンソールなので元々表示が単純でした、等が原因でしょう。
時間計測の際は、更に、#defineでprintf類をスキップします。

これを見習って、翻って、今度はHSPのスクリプトも修正しました。
作業時間の比較をするのなら、無駄な作業を省かないといけません。
無駄な変数を使わない。
無駄な表示もしない。
今回、mesboxも大量のテキストだと、表示時間が結構かかる事に気付きました。
しかも、末尾の記述が見やすいように、逐一スクロールさせていましたので大変です。
また、mesboxを使って、バイト単位の作業状況を表示させていました。
つまり、バイトごとに表示、ここでは数字ですが、を書き換えていました。
ループも出来るだけ少なく、中でawait類を使わない。(これで大量のデータ処理をすると、帰ってこない状態になりますが。)
等、作り直しました。

結果、先の100KBのテキストの処理が、49秒で終わるようになりました。HSPだけでの作業です。
上で、冗長なスクリプトで、11分かかったとメモしたものです。正確には689秒でした。
HSPでの改良だけで、前に比べて、1/14の時間に短縮されています。
いえ、それだけ冗長なスクリプトを書いていた、という事で、11分に関しては、これ以上比較する意味がありません。

次に、肝心のテキストの変換作業だけをCで代行する事を考えました。
本来は、作業速度を考えるなら、デスクトップを含んで全部をCか他のコンパイラで作ってしまう所でしょう。
あるいは、Cでdllを作って、HSPで読み込んで実行させる、という事の様です。
これについても少し調べましたが、私にはどちらも理解が出来ませんでした。

そこで、Cとの連携をファイルを使ってする事にしました。幼稚なやり方です。ですが、今の知識で出来ました。
目的のファイル名など、HSPでデータ引き継ぎ用のテキストファイルを作って保存して、Cを呼び出します。
Cでは、そのファイルを読み込んで変換作業をし、作業結果を、やはりファイルに保存します。

まあ、Cでも、ファイルの読み書きと、足し算引き算ぐらいなら、私にも出来るという事です。
それに、今回分かった事で、ファイルの読み書きには、さして時間がかからないという事です。
Cと引継ぎをする為のファイルにしろ、作業対象のファイルにしろ、ミリ秒の単位で処理されています。

このCで作るファイルをHSPで見張っていて、ファイルが出現したら、作業完了となります。
今、HSP側で、ファイルの出現を見張る間隔を1秒にして試すと、変換作業が3秒で終わるようになりました。
HSPだけで作業すると、50秒でしたので、1/17に短縮したことになります。
何より、3秒程度の待ち時間なら、精神的に許される時間だと思います。
その意味で、Cとの原始的な連携は許されていいと思います。

更に、HSP側の見張る間隔を0.5秒にすると、作業は1.2秒で終わりました。
これなら、もう十分に許される範囲です。
改良しても、HSPだと目的の100KBを処理するのに50秒かかります・
これでは、やはりストレスです。Cと組み合わせた価値が出てきます。

この状態で、C単独での実行時間(0.094秒)と比べると、527倍の時間です。Cだと、1/527の時間で済む、という事です。

ここまでの数字を一覧表にまとめてみます。
言語 100KBのテキストでの作業   20KBのテキストでの作業   2KB のテキスト
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP改良前 689.000 13.9   134.000 60.2  
HSP改良後 49.548 1.0   2.226 1.0   0.156 1
HSP+C 1.234 1/40   1.023 1/2.2   1.094 7.0
Cのみ 0.094 1/527   0.031 1/72  

20KBのテキストでも試してみました。
HSP+Cでの作業時間は、どちらでも、ほとんど変わりません。
これは、HSPでCの作業終了を見張る間隔を0.5秒にしている事で、この時間内に収まる作業では差は出ないという事でしょう。
何しろ、C単独だと、0.1秒程度で終わっています。

HSP単独での作業で、作業時間がファイル容量の比率にならないのが不思議です。
指数関数的な作業になっている様ですが、よく分かりません。

HSPで、2KBも試して、HSPだけで時間の比較をしてみました。
100KBだと、1KB当たり、0.495秒、
20KBだと、1KB当たり、0.113秒、
2KBだと、1KB当たり、0.078秒、
やはり、何か指数関数的なものがあるようです。



200507
Visual Studio Code 日本語化

エディタが欲しくて、Visual Studio Codeをインストールしてみました。
HSP以外のプログラム言語に挑戦してみようという魂胆です。
どうやら、今持っているTeraPadやメモ帳では物足りないみたいですので。

まず最初に、
MSのページからインストーラをダウンロードするのですが、紹介されているページが沢山あり、どれが一番安全なのか、主流なのか迷います。
結局、Microsoft Storeにも置いてありましたので、これを使いました。
他にも、MSのページが検索の最初に出ました。そこからもダウンロードしてみましたが、全く同じ物でした。

インストールは簡単に終わり、簡単に起動できました。
途中、デスクトップにアイコンを作る、ファイルの右クリックメニューに追加する、という意味のチェックが出ましたので、追加しておきました。

問題は、最初の起動が英語で、これを日本語化する事でした。
ネットの記事通り実行したつもりですが、再起動しても相変わらず英語のままです。

何度か試した結果、原因は、
メニューのviewのプルダウンから幾つか進んで、
configure display languageをクリックした後、
select display languageというダイアログが出ますので、
そこで、jaを選択する、
という事でした。
この間、日本語のインストールが済んでいなければ、その作業も入ります。

肝心の場面は下のキャプチャー画像の通りです。
そのまま適当にクリックしたり、Enterなどで指定するとenの方が反転していて、enを指定したことになります。
ここでしっかり、jaの部分を指定し、反転させねばなりません。
install云々の所をクリックしても、jaを選択したことにはなりません。
enを選択した状態でも、再起動のメッセージが出ますので、ここがとても迷うところでした。


200506
HSP、C言語

普段、HSPでプログラムを作っています。趣味程度です。
このサイトの大半のページを、そのHSPで半自動化しています。
今回、サイト作成とは関係なく、テキストファイルを読み込んで、バイト単位で変換して、保存する、というプログラムを作りました。
ところが、これが手間取るのです。
100KB程度のテキストファイルだと11分かかってしまいました。

このサイトのページは、5KBから10KB程度です。この程度のものだと待ち時間は感じられません。
ただ、11分もかかるようだと問題です。
対策は、プログラムを改良するか、他の言語を試すかです。
他の言語を試すことにしました。



トップページへ