20220112のC#に関する記事は5件です。

RichTextBoxに画像を挿入

画像データを WMF に埋め込んで Windows Forms の RichTextBox に挿入します。 概要 RichTextBox には画像を挿入するメソッドがありません。検索するとクリップボード経由で渡す方法がよく紹介されますが、今回は画像を含む RTF を生成して挿入します。 RTF の仕様には PNG など各種形式が含まれますが、RichTextBox が受け付けるのは WMF のみです。検索すると P/Invoke で WMF を生成する方法が見付かりますが、今回は直接 WMF を生成します。 実装 WMF に埋め込む DIB は BMP ファイルの 14 バイト以降です。画像を BMP に書き出して使用します。 using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Text; public class ImageToRtf { public static void Write16(StringBuilder sb, params int[] args) { foreach (int w in args) { sb.AppendFormat("{0:X2}{1:X2}", w & 0xff, (w >> 8) & 0xff); } } public static string Convert(Image img, Color back) { int w = img.Width, h = img.Height; int picw = w * 2540 / 96, pich = h * 2540 / 96; int picwgoal = w * 1440 / 96, pichgoal = h * 1440 / 96; var sb = new StringBuilder(); sb.AppendFormat( @"{{\rtf1{{\pict\wmetafile8\picw{0}\pich{1}\picwgoal{2}\pichgoal{3} ", picw, pich, picwgoal, pichgoal); byte[] bmp; using (var bitmap = new Bitmap(w, h)) { using (var g = Graphics.FromImage(bitmap)) { g.Clear(back); g.DrawImage(img, 0, 0, w, h); } using (var ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Bmp); bmp = ms.ToArray(); } } int size1 = 14 + (bmp.Length - 14) / 2; int size2 = 9 + 5 + 5 + size1 + 3; Write16(sb, // META_HEADER Record 1, 9, 0x300, size2, size2 >> 16, 0, size1, size1 >> 16, 0, // META_SETWINDOWORG Record 5, 0, 0x20b, 0, 0, // META_SETWINDOWEXT Record 5, 0, 0x20c, pich, picw, // META_STRETCHDIB Record size1, size1 >> 16, 0xf43, 0x20, 0xcc, 0, h, w, 0, 0, pich, picw, 0, 0 ); sb.Append(BitConverter.ToString(bmp, 14).Replace("-", "")); Write16(sb, 3, 0, 0); // META_EOF Record sb.Append("}}"); return sb.ToString(); } } 使用例 透過色はサポートされないため、背景色を指定します。 var rtb = new RichTextBox(); using (var bmp = new Bitmap("test.png")) { rtb.SelectedRtf = ImageToRtf.Convert(bmp, Color.White); } 参考 WMF の仕様です。 [MS-WMF]: Windows Metafile Format | Microsoft Docs 同じ目的のコードです。これらをベースに整理しました。 Insert image in RichTextBox without quality loss (WMF) - CodeProject c# - Programmatically adding Images to RTF Document - Stack Overflow [C#][WPF][WinForms]RichTextBoxで画像(JPEG)を挿入する。 - ガラクタの軌跡
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#で行列計算

C#で行列計算 久しぶりの投稿です。 ずっと前に、C#で行列計算をしてディープラーニングをするプログラムを作りました。(過去の記事を参照してください) その時問題だったのは、行列計算するクラスが非常に使いにくかったことです。 今回、そのクラスを0から作り直して使い勝手の良いものを作ろうと思いました。 そして、できあがったのは↓これです。 まだ、行列の足し算しかできませんが、今後引き算、掛け算、転置行列ができるようにして、ディープラーニングをやってみたいと思います。 行列計算クラス Matrix.cs namespace Matrix2 { class Matrix_code { private int code_number; public int Code_number { get { return code_number; } } /// <summary> /// 0:正常 /// 1:配列要素数オーバー /// </summary> /// <param name="c"></param> public Matrix_code(int c) { code_number = c; } } class Matrix { private double[] data = new double[150]; private int _x, _y; public int _X { get { return _x; } //set //{ // _x = value; //} } public int _Y { get { return _y; } //set //{ // _y = value; //} } public double this[int x, int y] //行列の各要素を取得、設定するインデクサー { set { data[((y - 1) * _y) + x - 1] = value; } get { return data[((y - 1) * _y) + x - 1]; } } public Matrix(int x,int y) { _x = x; _y = y; } public Matrix_code setValue(params double[] v) //行列のデータを設定する { if (v.Length > _x * _y) return new Matrix_code(1); for (int i = 0; i < v.Length; i++) { data[i] = v[i]; } return new Matrix_code(0); } public Matrix_code setValue(Matrix matrix) { if ((_x != matrix._x) || (_y != matrix._y)) return new Matrix_code(1); data = matrix.data; return new Matrix_code(0); } public static Matrix operator+(Matrix m1,Matrix m2) //行列の足し算 { if ((m1._x != m2._x) || (m1._y != m2._y)) return new Matrix(1, 1); Matrix matrix = new Matrix(m1._x, m1._y); for (int i = 0; i < m1._x * m1._y; i++) { matrix.data[i] = m1.data[i] + m2.data[i]; } return matrix; } public static Matrix operator +(double v, Matrix m) { Matrix matrix = new Matrix(m._x, m._y); for (int i = 0; i < m._x * m._y; i++) { matrix.data[i] = m.data[i] + v; } return matrix; } public static Matrix operator +(Matrix m, double v) { Matrix matrix = new Matrix(m._x, m._y); for (int i = 0; i < m._x * m._y; i++) { matrix.data[i] = m.data[i] + v; } return matrix; } } } 使用例 Form1.cs using System; using System.Windows.Forms; namespace Matrix2 { public partial class Form1 : Form { Matrix m1 = new Matrix(2, 2); //2✕2の行列 Matrix m2 = new Matrix(2, 2); //2✕2の行列 public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) //ボタン1が押されたとき { m1.setValue( 1, 2, 3, 4); //m1 に行列のデータセット m2.setValue( 10, 11, 12, 13); //m2 に行列のデータセット Matrix m; m = m1 + m2; //足し算 label1.Text = m[1, 2].ToString(); //要素(1,2)を取得し、ラベル1に表示 } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マウスを自動で移動させてスリープさせないアプリ(SoulMouse)

離席中でもWindowsをスリープさせたくない 体は離席しても、魂だけは在席してマウス操作しててほしい。 というわけで、プログラムでマウス操作させてみました。 作ったアプリ ・カーソル移動 → スクロール → 待ち、を繰り返すアプリ ・それぞれの時間はランダム(配布版では「待ち」時間はもう少し長め) ・人がいなくても、人のぬくもりを感じるアプリになりました ソースコード マウスをぷるぷる動かしてスクリーンセーバを抑制するアプリ を参考にさせていただきました。ありがとうございます。 上記ページのソースコードに、以下を追加しています。 (Wait, Move, Wheel のステート追加) Form1.cs const int MOUSEEVENTF_WHEEL = 0x800; INPUT[] mInput = new INPUT[1]; Stopwatch mStopwatch = new Stopwatch(); enum EState { Wait, Move, Wheel } EState mState = EState.Wait; Random mRandom = new Random(); int mTargetX = 0, mTargetY = 0; private async void autoMouseRunStart() { isAppRun = true; int screen_width = Screen.PrimaryScreen.Bounds.Width; int screen_height = Screen.PrimaryScreen.Bounds.Height; mStopwatch.Restart(); mInput[0].mi.dx = Cursor.Position.X * (65535 / screen_width); mInput[0].mi.dy = Cursor.Position.Y * (65535 / screen_height); mInput[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE; // 開始時点でマウスがPrimaryScreenに無い場合、PrimaryScreenに強制移動させる if (Cursor.Position.X > screen_width || Cursor.Position.Y > screen_height) { mInput[0].mi.dx = (screen_width / 2) * (65535 / screen_width); mInput[0].mi.dy = (screen_height / 2) * (65535 / screen_height); SendInput(1, mInput, Marshal.SizeOf(mInput[0])); } await Task.Run(() => { while (isAppRun) { switch (mState) { case EState.Wait: // 一定時間経過したら EState.Move に移行 if (mStopwatch.ElapsedMilliseconds > mWaitTime) { mState = EState.Move; mMoveTime = mRandom.Next(1000, 3000); // 1~3秒でマウス移動 mTargetX = mRandom.Next(0, screen_width); // ランダムなX座標 mTargetY = mRandom.Next(0, screen_height); // ランダムなY座標 mInput[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE; mStopwatch.Restart(); } // 適当にスリープさせる // さもないと、CPU100%で処理してしまう System.Threading.Thread.Sleep(5); break; case EState.Move: // 一定時間経過したら EState.Wheel に移行 if (mStopwatch.ElapsedMilliseconds > mMoveTime) { mState = EState.Wheel; mWheelTime = mRandom.Next(100, 800); // 0.1~0.8秒でマウスホイール mInput[0].mi.dwFlags = MOUSEEVENTF_WHEEL; mInput[0].mi.mouseData = mRandom.Next(-1, 2); mStopwatch.Restart(); } // カーソルを目標に追従させる mInput[0].mi.dx += (int)((mTargetX - Cursor.Position.X) * 0.07) * (65535 / screen_width); mInput[0].mi.dy += (int)((mTargetY - Cursor.Position.Y) * 0.07) * (65535 / screen_height); // 適当にスリープさせる // さもないと、カーソル移動処理が実行されすぎて移動が速くなりすぎてしまう System.Threading.Thread.Sleep(5); break; case EState.Wheel: // 一定時間経過したら EState.Wait に移行 if (mStopwatch.ElapsedMilliseconds > mWheelTime) { mState = EState.Wait; mWaitTime = mRandom.Next(10000, 30000); // 10~300秒でマウス停止 mInput[0].mi.dwFlags = 0; mStopwatch.Restart(); } // マウスホイールではスリープさせない // スリープさせると滑らかなスクロールにならなかった //System.Threading.Thread.Sleep(1); break; } // イベントの実行 // Cursor.Position への代入や、SetCursorPos での座標セットではスリープ状態になってしまうので SendInput を使用 SendInput(1, mInput, Marshal.SizeOf(mInput[0])); } }); } // 機能停止 private void autoMouseRunStop() { isAppRun = false; mState = EState.Wait; mTargetX = mTargetY = 0; mWaitTime = mMoveTime = mWheelTime = 2000; } マウスホイール時に Thread.Sleep するとスクロールがガクガクしていました。 よって、EState.Wheel では Thread.Sleep していません。 CPU速度に依存するコードになっているので、高性能PCでは Thread.Sleep する必要があるかもしれません。 プロジェクトは以下にあります。 アプリを使用してみる こちら の「Download SoulMouse.zip」からダウンロード zip を展開 SoulMouse.exe を実行するとタスクトレイに登場(灰色矢印アイコン) 「CTRL + SHIT + S」で開始(カーソルが自動で動き出す) 「CTRL + SHIT + D」で停止 タスクトレイのアイコンを右クリック「終了」でタスクトレイから削除 ・よくPCスリープになってしまう人は是非 ・テレワーク監視はスリープ時間チェックから行われることが多い ・Webカメラを定期送信するなどの本気の監視には対応できないですが ・いずれにせよ、用法・用量を守って正しくお使いください
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#で書画カメラの映像を表示する。

はじめに C#で書画カメラ(ELMO mo-1)の画像をアプリで表示してみました。 環境 Windows 11 Pro Visual Studio 2017 Express 書画カメラ ELMO mo-1 設定 C#で書画カメラにアクセスするためにVisual Studioで AForgeをインストールしました。 NuGetパッケージマネージャーでAForgeを検索して AForge.Controls、AForge.DirectShowをインストールしました。 フォームへの貼り付けは、ツールボックスを右クリックし、 アイテムの選択で C:\Users\user.nuget\packages\aforge.controls\2.2.5\lib にあるAForge.Controls.dllを選択し、 VideoSourcePlayerを使いました。 これで簡単に表示できます。 プログラムコード 参考urlを見て最低限のコードで作成しました。 以下のurlにアップしました。 問題点 デバッグ中に書画カメラの通信が良く固まりました。 何度もVisual Studioを立ち上げ直したり、書画カメラの 電源のOn/Offを繰り返しましたが一向に改善しませんでした。 PCを再起動したら直しました。 結果 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

webview.hostObjects が async で失敗するのをなんとかする

ver.2:message を汚染せず匿名関数でやりくりするタイプ https://qiita.com/MoyomonDQ/items/f86f7726973693c20c95   JavaScript addEventListener('_exe.Ready',e=>{ var url = `https://script.google.com/macros/s/SampleDeployId/exec`; var text = `SampleText: Fixed newly exposed boat not showing up in the boat yard menu Changed contraptions to drop resources and inventory objects (crates) to drop resources even when killed with fire. Previously anything killed by fire would drop nothing.` chrome.webview.hostObjects.exe.PostError(url,text).then(r=>{ console.log(r)// null、async失敗 }) _exe.post(url,text).then(r=>{ console.log(r)// async成功 }) }) _exe = new class { constructor(){ this.promise = {} //this.on = {} addEventListener('Bridge.Ready',e=>{ chrome.webview.hostObjects.exe.GetMethods().then(a=>{ a.forEach(s=>this.addMethod(...s.split(','))) chrome.webview.addEventListener('message',e=>{ this.message(JSON.parse(e.data)) }) dispatchEvent(new Event('_exe.Ready')) }) },true) } addMethod(m,attr){ var s = m[0].toLowerCase() + m.slice(1); if(this[s]) return if(attr=='async'){ this[s] = (...a)=>new _exe.Promise.Message(m,...a) }else{ this[s] = (...a)=>new _exe.Promise.Json(m,...a) } } message(v){ switch(true){ //case ('type' in v): _exe.on[v.type](v); break case ('id' in v) : this.promise[v.id].resolve(v.value); break default:console.log(v) } } } _exe.Promise = class _exePromise{ constructor(){this.hook = ()=>{}} then(resolve){ this.hook = resolve return this } } _exe.Promise.id = 0 _exe.Promise.Json = class _exePromiseJson extends _exe.Promise{ constructor(s,...a){super() chrome.webview.hostObjects.exe[s](...a).then(r=>{ try{this.hook(JSON.parse(r))} catch(e){this.hook(r)} }) } } _exe.Promise.Message = class _exePromiseMessage extends _exe.Promise{ constructor(s,...a){super() this.id = ++_exe.Promise.id _exe.promise[this.id] = this chrome.webview.hostObjects.exe[s](...a,this.id) } resolve(r){ this.hook(r) delete _exe.promise[this.id] } } Bridge.cs public class Bridge{ protected CoreWebView2 core = null!; public Bridge(WebView2 view) { view.NavigationCompleted+=(s,e) => { core = view.CoreWebView2; core.AddHostObjectToScript("exe",this); Dispatch("Bridge.Ready"); }; } //nullが返る public async Task<string> PostError(string url,string data) { var content = new StringContent(data,Encoding.UTF8); using(var client = new HttpClient()) { var response = await client.PostAsync(url,content); var s = await response.Content.ReadAsStringAsync(); return s; } } //手動でResolve public async void Post(string url,string data,int resolve) { var content = new StringContent(data, Encoding.UTF8); using (var client = new HttpClient()){ var response = await client.PostAsync(url, content); var s = await response.Content.ReadAsStringAsync(); Resolve(resolve,s); } } class ResolveData { public int id { get; set; } = 0; public object value { get; set; } = null!; } protected void Resolve(int i,object v) { var r = new ResolveData() { id=i,value=v }; var s = JsonSerializer.Serialize(r); core?.PostWebMessageAsString(s); } protected async void Dispatch(string type) { if(core!=null) { var s = $"dispatchEvent(new Event('{type}'))"; var r = await core.ExecuteScriptAsync(s); } } public string[] GetMethods(){ var objectMethods = typeof(Object).GetMethods(); var async = typeof(AsyncStateMachineAttribute); var methods = new List<string>(); foreach(MethodInfo m in GetType().GetMethods()) { if(!Array.Exists(objectMethods,v => { return v.Name==m.Name; })){ if(m.GetCustomAttribute(async)==null) { methods.Add(m.Name); } else { methods.Add($"{m.Name},async"); } } } return methods.ToArray(); } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む