質問: Windows VScode MinGW C言語 エンコード:ShiftJIS ### 前提・実現したいこと 例えば、画像1:1200x900,画像2:2400x1800があるとして、これをd&dすると、 縦:x2 x0.5 横:x2 x0.5 という風に表示するプログラムを作りたいです。 現在、以下の流れで実行する様にしようと思っております。 ``` プログラムに画像2つをd&d ↓ 画像のパスをMediainfoに送り、縦横のピクセル数を求めさせ、結果を何らかの方法でプログラムに返す。(いろんな形式の画像に対応するにはライブラリを色々積まねばならないようなので、既存品を流用とした。) ↓ 結果をもとに計算する ↓ 表示 ``` そして、現在このように実装しようとしています。 ``` #include #include int main(int argc,char *argv[]){ char all-pass[8192]={};//送るコマンドの格納配列。 char image-pass[]={};//画像のパスの仮置き配列。テスト後はargvが担う予定...? int i;//カウンタ char app-pass[]={};//ここにmediainfoのパス for(i=1;i<3;i++){//将来用のforループ。今は意味がない。 sprintf(all-pass,"%s %s>test%d.txt",app-pass,image-pass,i);//コマンド生成。txtに実行結果を出す。後でtxtからデータを抽出予定。 if ( system(all-pass) != EXIT_SUCCESS ) {//コマンド送る puts("file read error"); exit(EXIT_FAILURE); } } system("pause");//d&dでやるとき、画面がすぐ消えられると困るので。 return 0; } ``` ### 発生している問題・エラーメッセージ しかし、ファイルパスに日本語が混じると、ダメ文字と俗に言われているらしいエスケープシーケンスのあれこれでバグります。 UTF8BOMでやれば、ダメ文字問題解決と、PowerShellの文字化け回避を両立できると思いましたが、今度はShiftJIS時点で普通に動いた奴でもダメになりました。 如何様にすればよいでしょうかね? もっと良い方法や、既存でそういうのがあればそれらを教えてもらえるととてもうれしいです。 他には、アプリ起動後にd&dできるようにする方法が知りたいです。 現在はアイコンにd&dするほかない状態ですので。 WinAPIはさっぱりですわい。 ### 細かい経緯 ネットで拾った解像度が悪いコラ画像を画質のいい元画像とあわせて高画質化するためにこのプログラムの原型ができました。 手作業でMediainfoにまず画像をぶち込み、そこで表示された2枚の画像の解像度をお手製プログラムに打ち込むと、縦横の拡大倍率が表示される。 縦横わざわざ両方だしてる理由は、コラ画像が、元画像のどちらか一方の辺をトリミングしていても、対応できるようにですね。 あと、どちらの画像の大きさに合わせてもいいように、倍率は逆数も出しています。 その、手作業部分が面倒に感じたので組み込んでしまおうと思いました。
回答: もっと簡単にはC# + XAMLで書くことですね。文字コードとWin32APIとの格闘からとりあえず逃れられます。 https://code.msdn.microsoft.com/windowsdesktop/XAMLCVB-WPF-Windows-WPF-a1c048ae 追記 興味が湧いたのでC# + XAMLで作ってしまいました。D&DしたあとWindowをクリックしてCtrl+Cすればクリップボードに結果が入ります。 !before !after 大して長いコードでもないしMVVMパターンとかもやってないのでGithub見れば1分で理解できるとは思うのですが、一応解説。 GUIでD&Dするとこと結果表示するところは高さが3:1になるようにしてます。`MinHeight`は保険。 ``` ``` `PreviewDragOver`イベントでファイルのD&Dのみ検知して`Drop`イベントで非同期に画像の大きさを求める処理を書いています。非同期にしないとGUIが固まるかもしれないので非同期大事です。この辺はMSが出してるサンプルほぼそのままです [XAML/C#] WPF におけるドラッグ アンド ドロップ (Windows フォームから WPF へ) 画像の大きさは`System.Drawing.Image.Size`に丸投げしています。DLLへの参照を追加しないとビルドできないですが。`System.Drawing.Image.FromFile`の非同期版が見つからなかったので雑に`Task.Run`してますがまあ大丈夫でしょう、しらんけど。`Task.WhenAll`と`.Select`の組み合わせの使い方は neue cc - 非同期時代のLINQ に解説ありますね。 ``` var sizes = await Task.WhenAll(files.Select(async fileName => await Task.Run(() => System.Drawing.Image.FromFile(fileName).Size))); ``` あとは結果表示の方に`Name="result"`とidつけて ``` ``` とりあえず小数第四位までに四捨五入して適当に文字列作って`result.Text`に代入すれば表示されます。 ``` result.Text = $"縦: x{Math.Round(sizes[0].Height * 1.0 / sizes[1].Height, 4)} x{Math.Round(sizes[1].Height * 1.0 / sizes[0].Height, 4)}\n" + $"横: x{Math.Round(sizes[0].Width * 1.0 / sizes[1].Width, 4)} x{Math.Round(sizes[1].Width * 1.0 / sizes[0].Width, 4)}"; ``` Ctrl+Cは 3秒でわかるWPFでCtrl+C(Copy)のときになんか実行する方法 で書いた方法で拾ってます。 ``` private void OnCtrlC(object sender, RoutedEventArgs e) { if (string.Empty != result.Text) { Clipboard.SetData(DataFormats.Text, result.Text); } } ```