DOBON.NETプログラミング道掲示板

■ 「新規作成」から投稿できます。
■ マルチポストされた投稿を見つけたときは、その投稿に返信することによりご報告ください。その際は匿名で投稿し、マルチポストされている場所を併記してください。
■ スパム対策のため、メールアドレスの先頭に"_"という文字が付加されています。
RSS 2.0 RSS 2.0 | RSS 0.91 | 携帯電話用 | 自分専用のアイコンを使用するには | 掲示板への要望 | 管理人に連絡 | お気楽掲示板
■ 24時間以内に作成されたスレッドは New で表示されます。
■ 24時間以内に更新されたスレッドは UpDate で表示されます。

記事リスト ( )内の数字はレス数
NomalExcel Com オブジェクトの増殖(13) | NomalRichTextBoxのテキストをpictureBOXへ(12) | Nomalリソースデザイナの開き方(11) | NomalPictureBoxの画像を連続保存(11) | NomalGetObjectでExcelファイルを加工するとExcelファイルが壊れる(9) | NomalVB.NetでVB6.0と同じFontを指定しても同様に印刷されない(9) | Nomal作成した白黒画像をWordに貼り付けてから「図として保存」(8) | Nomal重なったPictureBox同士を透過する方法(7) | Nomalvb.netでExcelファイル操作(7) | NomalTreeViewの現在位置とDataGridViewの現在位置を合わせたい(7) | Nomalラジオボタンの一括設定(7) | NomalDataAdapter.Updateで構文エラー(6) | Nomalキーボード+バーコードでキーボード入力を無効にしたい(6) | Nomaljumbo icon(256x256)が存在するか知る方法(6) | Nomal画像のスクロール(6) | Nomalタイマーの一括処理(6) | Nomal先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える(6) | NomalタッチキーボードでIMEを自動で切替えたい(6) | Nomalwebformでの制御(5) | Nomalftp接続してファイルアップロード後、別フォルダにコピー(5) | Nomalシステムドライブ以外へのページング設定が反映されない(5) | Nomal全角シフト中にアクセスキーが効かない(5) | NomalVB.NETからcmdでpingを実行した時の結果(5) | NomalTabPageの背景色(5) | Nomalstyle.displayだと効率悪いから違うやり方をしたいです。(5) | Nomalグリッド表示レコードをJSONに変換(5) | NomalSeleniumで開いているページのTableを編集したい(5) | NomalDataGridViewの特定セルにボタンを配置する方法(5) | Nomalロジックの実現お願い(4) | NomalAppActiveが正常に機能しない。(4) | Nomalブラウザでコピーした透過PNGを貼り付けたい(4) | NomalWebView2によるスクレ―ピング(4) | NomalC#でJpeg圧縮のTiffファイルを作成したい(4) | NomalDataGridViewのVirtualModeを有効した場合の実装方法(4) | Nomalテーブルを順番通りに直すプログラムを外部で読み込めるようにしたいです。(4) | Nomalソケット通信入門 ひらがな(4) | Nomal時間変数(文字列)の扱い(4) | NomalTreeViewとDataGridViewのスクロールを同期(シンクロ)させたい(4) | Nomalフォームのリサイズ時にDataGridViewが再描画されない(4) | NomalPDFをフォーム上で表示させる方法につきまして(4) | NomalアプリでHDMIへ出す解像度を変えたい(4) | Nomal画像の中心を基点に回転(4) | NomalDataGridViewの行ヘッダーに行番号を表示した時のエラー(4) | NomalC言語系で使用される書式をVBで使いたい(3) | Nomal抽象クラスで実装したクラスの情報を知る(3) | Nomal兆億万表記の文字列を数値に変換できる?(3) | NomalGetDirectoriesでルートを指定するとエラーになる(3) | NomalLinqにおける明示的型指定の方法(3) | Nomalデータベースからのテーブル名一覧の効率的な取得方法(3) | NomalC# Chart X軸上のグラフ表示(3) | NomalVB.NETでBluetoothデバイスの電池残量を取得する方法(3) | NomalWindowsフォームデザイナについて(3) | NomalDrawstringでの透過文字作成(3) | Nomalワンタイムパスワードのサイトに自動ログインしてアクセストークンを得る(3) | NomalJSONの複雑な入れ子内部の値を取りたい。(3) | Nomalシステム時計の設定(3) | NomalVisual Basicでエラーが出る(3) | Nomal継承元フォームで各フォームのボタン動作を検知したい(3) | Nomal.NET 4.5.2のVB.NETでのデスクトップ環境開発(2) | Nomaltextboxでmultilineでの改行削除について(2) | NomalDataGridViewのイベント中にデータを更新するとエラーが発生(2) | Nomalフォントに登録されていない文字の検出(2) | NomalDataGridViewの複数行選択で歯抜け選択を無効にしたい(2) | Nomalforeachでループ回数を取得(2) | Nomalbitmapが保存できない(2) | Nomal特定ピクセルで画像を読み込みたい(2) | NomalDataGridViewでAlt+Enterで改行したい(2) | NomalProcessクラスからbatファイル実行後、KILLできない(2) | Nomal画面遷移(モーダルとモードレス)(2) | Nomal2つのradの数値から1つの角度を求めるコードを改善できますか?(C++)(2) | Nomalコンソールアプリで、WebView2の利用(2) | NomalEntity Frameworkは、使えるか?(2) | NomalC#のlong型でオーバーフローになる(2) | Nomal正規表現のパターン表記方法(2) | Nomalこういた物を作れますか?(2) | Nomalvb.netでのExcelファイルそうさ(2) | Nomalファイルとして配置したマニフェストを優先したい(2) | NomalVB2022でクリスタルレポートが開けない(2) | Nomalエクセルのみ監視ができない(2) | NomalExcelの数値 -> 日付みたいな関数?(2) | NomalSpinWait()を使う理由(2) | Nomalantecedentってなんですか?(2) | NomalRGB値の所得(2) | NomalVB.net からAccessDBへの接続(2) | NomalテキストボックスのValidatingイベントよりも先に発生するボタン発生イベントは何でしょう?(2) | NomalWindowsエクスプローラからのドラッグ&ドロップ(2) | Nomalクリックイベントでexeを作成できるか(2) | Nomalc#で日付型の定義の仕方で質問があります。(2) | Nomal列車の時間ごとの位置情報を表示したいです。(2) | Nomaloledbでdatatableを取得するときにエラーになる(1) | Nomal証券会社へのログイン(1) | Nomalツールボックスにtableadapterが表示されない(1) | Nomalアセンブリ情報が載らない(1) | Nomal二次元マップから値の取得(1) | NomalDataGridViewのドロップダウンリストの表示と選択後の値を分けたい(1) | NomalVSTOによるエクセルアドインのインストーラーでのアップデート(1) | Nomalユーザーフォームに埋め込んだAutoCADの変化を捉える(0) | Nomalクリスタルレポート 明細部のサブレポート(0) | Nomalインストーラにて、ローミングフォルダにファイルを配置したい(0) |



■記事リスト / ▼下のスレッド
■35233 / 親記事)  アプリでHDMIへ出す解像度を変えたい
□投稿者/ ま〜 一般人(20回)-(2022/11/15(Tue) 18:39:07)
  • アイコン環境/言語:[Windows10 Basic VS2022] 
    分類:[.NET] 

    こんばんわ
    解像度320,160のLEDモニタがあるのですがここに表示する為に作成した文字や画像が実際にどんな感じに表示されるか見たいが目標です。

    特定フォームを開いた時にPCから出力される解像度を一時的に640,480位まで下げ、そのフォームを閉じたときに元の解像度(1920,1080)に戻したいのですがこんな事が出来るのか?不明ですが宜しくお願いします。

違反を報告
引用返信

▽[全レス4件(ResNo.1-4 表示)]
■35235 / ResNo.1)  Re[1]: アプリでHDMIへ出す解像度を変えたい
□投稿者/ 魔界の仮面弁士 大御所(1481回)-(2022/11/15(Tue) 19:21:43)
  • アイコンNo35233に返信(ま〜さんの記事)
    > 解像度を一時的に640,480位まで下げ、そのフォームを閉じたときに
    > 元の解像度(1920,1080)に戻したいのですが

    その LED モニタの仕様が良くわからないので、外しているかもしれませんが…。


    画面キャプチャーを撮って、それを 640x480 に縮小して表示したい、
    という話で良いでしょうか。それとも、Windows の画面解像度を
    一時的に変更したいという話でしょうか。

    前者であれば、
    https://dobon.net/vb/dotnet/graphics/screencapture.html
    https://dobon.net/vb/dotnet/graphics/invokepaint.html
    などで画面を撮影し、
    https://dobon.net/vb/dotnet/graphics/drawimage.html#scaling
    https://dobon.net/vb/dotnet/graphics/interpolationmode.html
    で縮小するという方法が使えます。


    後者であれば、Windows 7 などといった古い OS であれば、
    exe ファイルのショートカットを作成し、プロパティの[互換性]タブにて
     設定:640 x 480 の解像度で実行する
    にチェックを入れて起動すれば良いと思います。

    ただし、この互換性機能は現行 OS では使えません。
    Windows 10 の最小システム要件が『800 x 600』となっているため
    「640x480」に設定することができないためです。同様に、Windows 11 は
    720p ディスプレイすなわち「1280x720」以上がシステム要件です。
違反を報告
引用返信
■35237 / ResNo.2)  Re[2]: アプリでHDMIへ出す解像度を変えたい
□投稿者/ ま〜 一般人(21回)-(2022/11/16(Wed) 15:17:35)
  • アイコンいつもありがとうございます

    320:160サイズのRichTextBoxに書いてる文字が小さすぎて見にくいのでFontDATAをいじらないで文字を拡大表示させたい
    そこで解像度の切替かMouseホールでRichTextBoxの内容を拡大表示みたいな事が出来ないかとの発想です。
    ホイールの方は倍率の設定が難しそうなので解像度の変更と考えた次第です
    確認用なので実際にLEDモニタは接続せず今使っているモニタ出力信号をハード的に解像度(HDMIに出す解像度)を変更したいです。

    でもアドバイスにありました画像でやれば簡単そうに思えたのでやって見ました所
    https://dobon.net/vb/dotnet/graphics/drawimage.html#scaling
    の bmp.Save("C:\test\1.BMp")でコピペなので入力間違いはないと思いますがSaveで例外エラーとなります。

    以下はエラーの内容です。宜しくお願いします。

    System.Runtime.InteropServices.ExternalException
    HResult=0x80004005
    Message=GDI+ で汎用エラーが発生しました。
    Source=System.Drawing
    スタック トレース:
    場所 System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
    場所 System.Drawing.Image.Save(String filename, ImageFormat format)
    場所 System.Drawing.Image.Save(String filename)
    場所 勉強.文字編集Form.Button6_Click(Object sender, EventArgs e) (C:\Users\maeda\source\repos\勉強\文字編集Form.vb):行 818
    場所 System.Windows.Forms.Control.OnClick(EventArgs e)
    場所 System.Windows.Forms.Button.OnClick(EventArgs e)
    場所 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    場所 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    場所 System.Windows.Forms.Control.WndProc(Message& m)
    場所 System.Windows.Forms.ButtonBase.WndProc(Message& m)
    場所 System.Windows.Forms.Button.WndProc(Message& m)
    場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    場所 勉強.My.MyApplication.Main(String[] Args) ():行 23



違反を報告
引用返信
■35238 / ResNo.3)  Re[3]: アプリでHDMIへ出す解像度を変えたい
□投稿者/ 魔界の仮面弁士 大御所(1482回)-(2022/11/16(Wed) 17:03:43)
  • アイコンNo35237に返信(ま〜さんの記事)
    > でもアドバイスにありました画像でやれば簡単そうに思えたのでやって見ました所
    > https://dobon.net/vb/dotnet/graphics/drawimage.html#scaling
    > の bmp.Save("C:\test\1.BMp")でコピペなので入力間違いはないと思いますがSaveで例外エラーとなります。

    その URL には、コピペしたという「bmp.Save」という文字列は見当たらないのですが…?

    ・C:\test\ フォルダーが存在し、書き込み可能になっていますか?
    ・C:\test\ の下に、"1.BMp" というファイルやフォルダーが無い状態になっていますか?
    ・もしも C:\test\1.BMp が既に存在する場合、そのファイルが Image.FromFile 等で開かれた状態になっていませんか?
違反を報告
引用返信
■35239 / ResNo.4)  Re[4]: アプリでHDMIへ出す解像度を変えたい
□投稿者/ ま〜 一般人(22回)-(2022/11/16(Wed) 18:20:19)
  • アイコンありがとうございます。
    スクショの保存できました

    URLはhttps://dobon.net/vb/dotnet/graphics/invokepaint.html
    が正解です。
    Saveの方はフィルダが無かったです。気にも留めなかったです。
    申し訳ないです。以後気を付けます。

    問題はスクショなので全画面でした。当たり前ですが。。。
    なのでRichTextBoxを選択してPictureBoxへ転送して画像化。
    記事を参考にトライしてみます

    解像度の切替が難しそうなので画像にして拡大表示にしてみます。
    取りあえず目的が変わってしまったのでクロースします。
    ありがとうございました。


解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-4]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35222 / 親記事)  画像の中心を基点に回転
□投稿者/ ま〜 一般人(16回)-(2022/11/11(Fri) 15:16:16)
  • アイコン環境/言語:[Vs2022 basic] 
    分類:[.NET] 

    こんにちは
    画像の回転に付いてですが中央を基点に5度単位で回転させたいのですが良い方法はないでしょうか?
    宜しくお願いします

違反を報告
引用返信

▽[全レス4件(ResNo.1-4 表示)]
■35223 / ResNo.1)  Re[1]: 画像の中心を基点に回転
□投稿者/ 魔界の仮面弁士 大御所(1477回)-(2022/11/11(Fri) 16:27:00)
  • アイコンNo35222に返信(ま〜さんの記事)
    > 中央を基点に5度単位で回転させたいのですが

    WPF の話なら、RenderTransformOrigin が (0.5, 0.5) の
    RenderTransform を使用して、Angle に 5 の倍数をセットすれば良いかと。

    <Image Source="/exmaple.jpg" RenderTransformOrigin=".5,.5">
    <Image.RenderTransform>
    <RotateTransform Angle="5" />
    </Image.RenderTransform>
    </Image>


    WinForm なら、Graphics クラスで DrawImage する前に、
    TranslateTransform と RotateTransform を指定する形です。
    https://dobon.net/vb/dotnet/graphics/transform.html#section1
    http://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleRotateBitmap.html
違反を報告
引用返信
■35228 / ResNo.2)  Re[2]: 画像の中心を基点に回転
□投稿者/ ま〜 一般人(17回)-(2022/11/14(Mon) 13:38:53)
  • アイコン魔界さんいつもありがとうございます

    数日前に参考にさせて頂きコピペして試行錯誤でやってみたのですがどうしても
    画像の中心が基点とならないので困ってます。と言うか分からないが。。。

    > TranslateTransform と RotateTransform を指定する形です。
    TranslateTransformは画像の左上の0,0を移動するみたいでここを基点に回転して5度づつ回転させると左上を基点に扇みたいになります(理解してないのかも?)

    希望は元の画像の中心を基点に回転させたい。

    > http://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleRotateBitmap.html
    を試しましたが
    Private Function RotateBitmap( _
    ByVal bmp As Bitmap, ByVal angle As Single, ByVal x As Integer, ByVal y As Integer) As Bitmap

    ByValの所で構文エラーとなってしまいます。
    解決策が分からないです。



違反を報告
引用返信
■35230 / ResNo.3)  Re[3]: 画像の中心を基点に回転
□投稿者/ 魔界の仮面弁士 大御所(1479回)-(2022/11/14(Mon) 18:58:36)
  • アイコンhttp://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleRotateBitmap.html
    ではなく
    http://nonsoft.la.coocan.jp/SoftSample/VB.NET/SampleRotateBitmap.html
    を紹介するべきでしたね。


    No35228に返信(ま〜さんの記事)
    > 魔界さんいつもありがとうございます
    https://twitter.com/Benshi_Orator/status/1580431600499961858


    >> TranslateTransform と RotateTransform を指定する形です。
    > TranslateTransformは画像の左上の0,0を移動するみたいでここを基点に回転して5度づつ回転させると左上を基点に扇みたいになります(理解してないのかも?)

    先に提示した URL で解説されているように
    まず、原点を (0,0) よりさらに左上(マイナス座標)にずらしてから、
    その後、RotateTransform で回転させてから、
    今度は右下方向(プラス座標)に復帰させたのち、
    DrawImage または DrawImageUnscaled で描画します。

    描画した後は座標系が回転したままなので、連続して描画する場合は
    GraphicsState を併用します(Save / Restore メソッド)。
    ※あるいは ResetTransform メソッド。


    なお、元のサンプルでは、「PictureBox の中心」で回転させていますので、
    「画像の中心」で回転させたい場合は
     RotateBitmap(org, ang, PictureBox1.Width \ 2, PictureBox1.Height \ 2)
    ではなく
     RotateBitmap(org, ang, org.Width \ 2, org.Height \ 2)
    とします。

    また、元画像の描画位置を左上以外(x2, y2)にしたい場合は、回転後の
     g.TranslateTransform(x, y, MatrixOrder.Append)
    の後に、さらに
     g.TranslateTransform(x2, y2, MatrixOrder.Append)
    を加えてから描画するようにします。



    > Private Function RotateBitmap( _
    > ByVal bmp As Bitmap, ByVal angle As Single, ByVal x As Integer, ByVal y As Integer) As Bitmap
    > ByValの所で構文エラーとなってしまいます。

    いやいや。
    せめて、どの ByVal が何という構文エラーになっているのかまで
    きちんと内容を示しましょうよ。

    Function を置く場所を、文法的に間違えているということはないですよね…?
    (Class や Module の外側に書こうとしているなど)
違反を報告
引用返信
■35231 / ResNo.4)  Re[4]: 画像の中心を基点に回転
□投稿者/ ま〜 一般人(19回)-(2022/11/15(Tue) 17:03:14)
  • アイコン感謝です。

    出来ました。

    亀速度で勉強中です。少しずつですが理解出来る様になってきました。道のりは長いですが。。。

    魔界さんのおかげです。
    ありがとうございます。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-4]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35216 / 親記事)  DataGridViewの行ヘッダーに行番号を表示した時のエラー
□投稿者/ たこ 一般人(12回)-(2022/11/04(Fri) 02:12:28)
  • アイコン環境/言語:[Windows10 VB.NET .NET Framework 4.7.2 VS2019] 
    分類:[.NET] 

    いつもお世話になります。

    DataGridViewの行ヘッダーに行番号を表示する
    https://dobon.net/vb/dotnet/datagridview/drawrownumber.html

    を使わせて頂いておりますが、1つ目のデータを挿入した際に「System.Configuration.ConfigurationErrorsException: '構成システムを初期化できませんでした。'」と出て停止してしまいます。
    (2つ目のデータ以降はエラーが出ない)
    「例外設定」の「次からスローされた場合を除く」の項目に「Log.dll」とあるので、ログクラスが何かしらいたずらしているとは思うのです。

    何か解決の糸口は無いかと書込みさせて頂きます。


    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
      '列ヘッダーかどうか調べる
        If e.ColumnIndex < 0 And e.RowIndex >= 0 Then
          'セルを描画する
          e.Paint(e.ClipBounds, DataGridViewPaintParts.All)       '←ここで発生 コメントアウトするとフォーム拡大縮小時にゴミが残る…

          '行番号を描画する範囲を決定する
          'e.AdvancedBorderStyleやe.CellStyle.Paddingは無視しています
          Dim indexRect As Rectangle = e.CellBounds
          indexRect.Inflate(-2, -2)
          '行番号を描画する
          TextRenderer.DrawText(e.Graphics,
                    (e.RowIndex + 1).ToString(),
                    e.CellStyle.Font,
                    indexRect,
                    e.CellStyle.ForeColor,
                    TextFormatFlags.Right Or TextFormatFlags.VerticalCenter)
          '描画が完了したことを知らせる
          e.Handled = True
        End If

        DataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray
      End Sub
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------



    呼出し元
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
      Private Sub DGVDataAdd(workStr As List(Of String()))
        DataGridView1.Rows.Clear()
        On Error GoTo ErrorNext
        System.Threading.Monitor.Enter(workStr)
        Dim ws As List(Of String()) = workStr
        System.Threading.Monitor.Exit(workStr)
        System.Threading.Monitor.Enter(ws)
        Dim x As Integer = 0
        For Each work In ws
          System.Threading.Monitor.Enter(work)
          DataGridView1.Rows.Add(work)
          DataGridView1(LogData.LogKinds, x).Style.BackColor = LogKind_ColorChange(work)
          DataGridView1(LogData.Operation, x).Style.ForeColor = Operation_ColorChange(work)
          x += 1
          System.Threading.Monitor.Exit(work)
        Next
        System.Threading.Monitor.Exit(ws)
    ErrorNext:
        DataGridView1.Refresh()
      End Sub
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
    いろんなスレッドに呼ばれるので、エラーが出て最終的に「On Error Resume Next」を付けました^^;



    呼出し元の呼出し元
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
      Private Delegate Sub DGVAddInvoke(DataStr As List(Of String()))

      ''' <summary>
      ''' AlertLog変更イベント
      ''' </summary>
      Private Sub _LogStock__AlartLogEvent(sender As Object, e As EventArgs) Handles _LogStock._AlertLogEvent
        If DispLevel = LogEventArgs.Kinds.Alart Then
          Invoke(New DGVAddInvoke(AddressOf DGVDataAdd), _LogStock.AlertLog)
        End If
      End Sub

      ''' <summary>
      ''' OperateLog変更イベント
      ''' </summary>
      Private Sub _LogStock__OperateLogEvent(sender As Object, e As EventArgs) Handles _LogStock._OperateLogEvent
        If DispLevel = LogEventArgs.Kinds.Operate Then
          Invoke(New DGVAddInvoke(AddressOf DGVDataAdd), _LogStock.OperateLog)
        End If
      End Sub

      ''' <summary>
      ''' SystemLog変更イベント
      ''' </summary>
      Private Sub _LogStock__SystemLogEvent(sender As Object, e As EventArgs) Handles _LogStock._SystemLogEvent
        If DispLevel = LogEventArgs.Kinds.System Then
          Invoke(New DGVAddInvoke(AddressOf DGVDataAdd), _LogStock.SystemLog)
        End If
      End Sub

      ''' <summary>
      ''' DebugLog変更イベント
      ''' </summary>
      Private Sub _LogStock__DebugLogEvent(sender As Object, e As EventArgs) Handles _LogStock._DebugLogEvent
        If DispLevel = LogEventArgs.Kinds.Debug Then
          Invoke(New DGVAddInvoke(AddressOf DGVDataAdd), _LogStock.DebugLog)
        End If
      End Sub
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
    以上3つのメソッドはLogDispクラスで、イベントはLogクラスから飛んできます。



    Logクラス
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
      Public Delegate Sub LogEventHandler(sender As Object, e As EventArgs)
      Public Event _AlertLogEvent As LogEventHandler
      Public Event _OperateLogEvent As LogEventHandler
      Public Event _SystemLogEvent As LogEventHandler
      Public Event _DebugLogEvent As LogEventHandler

      Private _AlertLog As New List(Of String())
      Private _OperateLog As New List(Of String())
      Private _SystemLog As New List(Of String())
      Private _DebugLog As New List(Of String())


      Public Sub Write(sender As Object, e As LogEventArgs)

        〜〜〜 (中略) 〜〜〜

        If e.LogKinds = LogEventArgs.Kinds.System Then
          _DebugLog.Insert(0, WriteData.Split(","))
          _SystemLog.Insert(0, WriteData.Split(","))
          If _SystemLog.Count > _MaxDispLog Then _SystemLog.RemoveAt(_MaxDispLog)
          RaiseEvent _SystemLogEvent(Me, New EventArgs())
          RaiseEvent _DebugLogEvent(Me, New EventArgs())
          Exit Sub
        End If
      End Sub
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    LogクラスもDispLogも同じLogプロジェクト内で、クラスライブラリ
    DispLogはユーザーコントロールです。

    よろしくお願いします。
違反を報告
引用返信

▽[全レス4件(ResNo.1-4 表示)]
■35218 / ResNo.1)  Re[1]: DataGridViewの行ヘッダーに行番号を表示した時のエラー
□投稿者/ 魔界の仮面弁士 大御所(1475回)-(2022/11/04(Fri) 10:44:35)
  • アイコンNo35216に返信(たこさんの記事)
    >「System.Configuration.ConfigurationErrorsException: '構成システムを初期化できませんでした。'」
    プログラムそのものでは無く、アプリケーション構成ファイルである
    exe名.config (開発時は app.config) ファイル、あるいは user.config の
    内容に不整合や破損があると、その例外が発生します。
    user.config の場所についてはこちら。
    https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/558appsettings/appsettings.html


    ということで、ログ関連の設定情報に問題があるのでは無いでしょうか。

    プロジェクトの構成が分からないので具体的なアドバイスはできませんが、
    Log.dll のプロジェクトがあるのなら、確認すべき app.config は Log プロジェクトの app.config ではなく、
    exe 側のプロジェクト側の app.cofing のはずです。exe 側の .config に対して、Log プロジェクト用の
    エントリーが正しく記録されているかどうかを確認してみてください。


    > LogクラスもDispLogも同じLogプロジェクト内で、クラスライブラリ
    > DispLogはユーザーコントロールです。
    NLog や log4net の類では無く、自作のロギングクラスということだとすると、
    第三者には、具体的なアドバイスが難しいかもしれません。


    > 呼出し元
    > Private Sub DGVDataAdd(workStr As List(Of String()))
    >   DataGridView1.Rows.Clear()
    >   On Error GoTo ErrorNext
    DataGridView1.Rows.Clear() が呼ばれているという事は、DGVDataAdd メソッドの呼び出し元が
    UI スレッド上からの呼び出しであることは保証されているのですよね?

    で、引数の List(Of ) は、「別スレッドでも同時に読み書きされる可能性がある」という事でしょうか。


    > いろんなスレッドに呼ばれるので、エラーが出て最終的に「On Error Resume Next」を付けました^^;
    え?「いろんなスレッドに呼ばれる」のですか?
    この実装だと、UI スレッド以外からの呼び出しは NG に見えますが…。

    ワーカースレッドから呼ばれることを前提としているのであれば、
    DataGridView に対する読み書き部分を取り除く必要があるでしょう。


    >   System.Threading.Monitor.Enter(workStr)
    >   Dim ws As List(Of String()) = workStr
    >   System.Threading.Monitor.Exit(workStr)
    >   System.Threading.Monitor.Enter(ws)
    ・ws は、workStr のコピーでは無く、同一インスタンスへの参照ですよね。
     Exit 直後に再 Enterをする実装になっているのは何故ですか?
     ループ全体を ws で囲って、ループ内では workStr で囲っている理由が分からないです。
     (ReaderWriterLock クラスのような事がしたいわけでも無さそうですし…)

    ・もしも処理によって粒度の異なるロックを用意したいという意図であれば、
     ロック範囲のレベルごとに、別々の「Object インスタンス」を設けた方が良いかもしれません。
      Private ReadOnly lockObject As New Object()

    ・UI スレッドで Monitor を扱う場合は、無制限待機になってしまうことを避けるため、
     .Enter ではなく、待機上限時間を指定可能な .TryEnter の方が安全かと思います。
     (ロック失敗時にアプリケーション例外とするのか、処理を無視するのか、リトライ判定させるかは要件次第…)
違反を報告
引用返信
■35219 / ResNo.2)  Re[2]: DataGridViewの行ヘッダーに行番号を表示した時のエラー
□投稿者/ たこ 一般人(14回)-(2022/11/04(Fri) 22:14:40)
  • アイコンNo35218に返信(魔界の仮面弁士さんの記事)
    > ■No35216に返信(たこさんの記事)

    いつもお世話になります。
    魔界の仮面弁士様、早速のご回答ありがとうございます。



    > ということで、ログ関連の設定情報に問題があるのでは無いでしょうか。
    >
    > プロジェクトの構成が分からないので具体的なアドバイスはできませんが、
    > Log.dll のプロジェクトがあるのなら、確認すべき app.config は Log プロジェクトの app.config ではなく、
    > exe 側のプロジェクト側の app.cofing のはずです。exe 側の .config に対して、Log プロジェクト用の
    > エントリーが正しく記録されているかどうかを確認してみてください。


    exe側のApp.config
    ----------------------------------------------------------------------------------------------------
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
      </startup>
    </configuration>
    ----------------------------------------------------------------------------------------------------
    別におかしいところは見当たらず…orz




    > DataGridView1.Rows.Clear() が呼ばれているという事は、DGVDataAdd メソッドの呼び出し元が
    > UI スレッド上からの呼び出しであることは保証されているのですよね?


    InvokeでUIスレッド上からの呼び出しであることは保証されている…と思っています。。。



    > で、引数の List(Of ) は、「別スレッドでも同時に読み書きされる可能性がある」という事でしょうか。


    はい。値渡ししています。


    >>いろんなスレッドに呼ばれるので、エラーが出て最終的に「On Error Resume Next」を付けました^^;
    > え?「いろんなスレッドに呼ばれる」のですか?
    > この実装だと、UI スレッド以外からの呼び出しは NG に見えますが…。


    正確にはいろいろなクラスのメソッドからイベントで呼ばれる…でした^^;



    > ワーカースレッドから呼ばれることを前提としているのであれば、
    > DataGridView に対する読み書き部分を取り除く必要があるでしょう。
    >
    >
    >>  System.Threading.Monitor.Enter(workStr)
    >>  Dim ws As List(Of String()) = workStr
    >>  System.Threading.Monitor.Exit(workStr)
    >>  System.Threading.Monitor.Enter(ws)
    > ・ws は、workStr のコピーでは無く、同一インスタンスへの参照ですよね。
    >  Exit 直後に再 Enterをする実装になっているのは何故ですか?
    >  ループ全体を ws で囲って、ループ内では workStr で囲っている理由が分からないです。
    >  (ReaderWriterLock クラスのような事がしたいわけでも無さそうですし…)
    >
    > ・もしも処理によって粒度の異なるロックを用意したいという意図であれば、
    >  ロック範囲のレベルごとに、別々の「Object インスタンス」を設けた方が良いかもしれません。
    >   Private ReadOnly lockObject As New Object()
    >
    > ・UI スレッドで Monitor を扱う場合は、無制限待機になってしまうことを避けるため、
    >  .Enter ではなく、待機上限時間を指定可能な .TryEnter の方が安全かと思います。
    >  (ロック失敗時にアプリケーション例外とするのか、処理を無視するのか、リトライ判定させるかは要件次第…)


    TryEnterと言うメソッドもあるのですね…
    まだまだスレッドとエラー処理については勉強が必要そうです……


    で、本題の「DataGridViewの行ヘッダーに行番号を表示した時のエラー」について、今回はそこまで厳密にリアルタイムに表示されなくても良い為、
    魔法の言葉「On Error Resume Next」で逃げる事にしました^^;

    最終形
    -----------------------------------------------------------------------------------------------------------------------------------------------------
      Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
        On Error Resume Next
        '列ヘッダーかどうか調べる
        If e.ColumnIndex < 0 And e.RowIndex >= 0 Then
          'セルを描画する
          e.Paint(e.ClipBounds, DataGridViewPaintParts.All)

          '行番号を描画する範囲を決定する
          'e.AdvancedBorderStyleやe.CellStyle.Paddingは無視しています
          Dim indexRect As Rectangle = e.CellBounds
          indexRect.Inflate(-2, -2)
          '行番号を描画する
          TextRenderer.DrawText(e.Graphics,
                     (e.RowIndex + 1).ToString(),
                     e.CellStyle.Font,
                     indexRect,
     e.CellStyle.ForeColor,
                     TextFormatFlags.Right Or TextFormatFlags.VerticalCenter)
          '描画が完了したことを知らせる
          e.Handled = True
        End If

        DataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray
      End Sub


      Private Sub DGVDataAdd(workStr As List(Of String()))
        DataGridView1.Rows.Clear()
        On Error GoTo ErrorNext
        Dim ws As List(Of String()) = workStr
        Dim x As Integer = 0
        For Each work In ws
          DataGridView1.Rows.Add(work)
          DataGridView1(LogData.LogKinds, x).Style.BackColor = LogKind_ColorChange(work)
          DataGridView1(LogData.Operation, x).Style.ForeColor = Operation_ColorChange(work)
          x += 1
        Next
    ErrorNext:
        DataGridView1.Refresh()
      End Sub

    -----------------------------------------------------------------------------------------------------------------------------------------------------


    板汚し失礼致しました。
    またよろしくお願い致します。
    ありがとうございました。
解決み!
違反を報告
引用返信
■35220 / ResNo.3)  Re[3]: DataGridViewの行ヘッダーに行番号を表示した時のエラー
□投稿者/ 魔界の仮面弁士 大御所(1476回)-(2022/11/07(Mon) 17:05:33)
  • アイコンNo35219に返信(たこさんの記事)
    >> あるいは user.config の内容に不整合や破損があると、
    > exe側のApp.config
    > 別におかしいところは見当たらず…orz
    user.config や machine.config は大丈夫なのですね?
    https://ja.stackoverflow.com/questions/65632/%E6%A7%8B%E6%88%90%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%92%E5%88%9D%E6%9C%9F%E5%8C%96%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F-%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6


    また、exe 側は .config 設定が特に無いものの、
    dll 側では connectionStrings や applicationSettings を
    登録してある…という事も無いのですよね。

    とすると、Invoke のタイミングの問題?


    > 正確にはいろいろなクラスのメソッドからイベントで呼ばれる…でした^^;
    常に Invoke であれば「いろんなスレッドに呼ばれる」ことはなく、
    UI スレッドからの呼び出しであると言えそうですが、Invoke し忘れが怖い所。

    呼び出し元の使い方を保証できない場合は、InvokeRequired を使って
    「別スレッドから呼び出された場合は、自身を Invoke しなおす」という
    実装にする手法があります。
    https://atmarkit.itmedia.co.jp/ait/articles/0506/17/news111.html#:~:text=invokeメソット&#12441;か&#12441;必要かと&#12441;うか

    いずれにせよ、イベント再入などが起こらないように注意が必要です。
    フォームを閉じている最中や起動途中に、割り込まれて Invoke されるような
    ケースがありえる場合は、追加の保護機構が必要になるかもしれません。


    >>で、引数の List(Of ) は、「別スレッドでも同時に読み書きされる可能性がある」という事でしょうか。
    > はい。値渡ししています。
    ロギングのため、追記される差分情報のみを同期的に渡すのであれば、
    同一インスタンスでは無く、値のコピーを渡す方が簡単だったりします。
    同一インスタンスへの同時書き込みが発生しなくなるので、
    Monitor や SyncLock などによる同期制御が不要で、Invoke だけで済むかと。
解決み!
違反を報告
引用返信
■35313 / ResNo.4)  Re[4]: DataGridViewの行ヘッダーに行番号を表示した時のエラー
□投稿者/ Aurea 一般人(1回)-(2023/01/04(Wed) 10:41:25)
  • アイコンコメントにあるものはもう試しましたか?最初のコメントは、実際に試してみればうまくいく可能性が高いと思います。私は自分でそれを実行しましたが、これまでのところ良い結果が得られました。これが、コードについて検討できるさまざまな状況が実際にたくさんあると言える理由です。それが私が最初に言えることであり、あなたと私は両方とも、現時点で私たち全員が検討できる選択肢がほとんどないことを知っています.今あなたがしなければならないことは、今のところ私たち全員が得ることができる最善の回答を考え出すことです.
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-4]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35696 / 親記事)  C言語系で使用される書式をVBで使いたい
□投稿者/ かぼちゃプリン 一般人(1回)-(2026/02/19(Thu) 11:07:00)
  • アイコン環境/言語:[VB.NET] 
    分類:[.NET] 

    VS2022
    .NET Framework 4.8

    VBで、C言語系で使用される"%03d"(整数を0埋め3桁にする)のような書式が使えるメソッドは.NET Frameworkに用意されていますか?
    または、VB用の書式指定子に変換してくれるようなメソッドはありますか?
    VBだったら、例えばint変数.ToString("000")のような書式になると思います。

    実は、他システムから呼び出されるプログラムをVBで作成しているのですが、
    引数に"%03d"の書式指定子が含まれていて、これをもとに処理結果を出力する必要があります。
違反を報告
引用返信

▽[全レス3件(ResNo.1-3 表示)]
■35697 / ResNo.1)  Re[1]: C言語系で使用される書式をVBで使いたい
□投稿者/ 魔界の仮面弁士 大御所(1593回)-(2026/02/20(Fri) 22:17:28)
  • アイコンNo35696に返信(かぼちゃプリンさんの記事)
    > VBで、C言語系で使用される"%03d"(整数を0埋め3桁にする)のような書式が使えるメソッドは.NET Frameworkに用意されていますか?
    > VBだったら、例えばint変数.ToString("000")のような書式になると思います。

    .NET Framework には無いので、正規表現で分解して自前解析でしょうかね。

    C++ ランタイムである msvcrt.dll の sprintf 関数や snprintf 関数とか、
    それらの Unicode 対応版とかを呼ぶってのが実装的には確実なんですが、
    .NET Framework ……というか IL ってのが、そもそも C 言語でいうところの
     int sprintf(char* buf, const char* fmt, ...);
    の可変長引数「...」の呼び出しをサポートしていないので、
    DllImport (Declare) するなら引数の数ごとにオーバーロードを用意するしかないという罠。

    C# の __arglist、.NET の RuntimeArgumentHandle も、managed な引数向けであって
    「...」に対する P/Invoke 呼び出しには対応していないんですよね。
    (これは、VB の ParamArray や C# の params とは別の仕組み)


    C++/CLI なら呼べるので、それでブリッジ DLL を作る手はあるけれど、公開関数を
     static String^ Format(String^ fmt, ... array<Object^>^ args)
    としたところで、Object[] を va_list へ変換する部分は自前実装しかないという罠。


    いずれにせよ、可変長引数の扱いが厄介なのですが、引数の数がさほど膨大になることもないでしょうし
    ひとまず 10 個まで渡せるようにしてみました。


    Imports System.Runtime.InteropServices
    Imports System.Text

    Public Class Form1

      ' VB では可変引数を直接宣言できないため、引数を固定して宣言
      ' arg0, arg1, arg2, …の数は、20個でも30個でも必要な分だけ定義する
      ' ここでは例として10個の引数をサポートする関数を宣言
      <DllImport("msvcrt.dll", EntryPoint:="_snwprintf", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)>
      Private Shared Function _snwprintf(
        ByVal buffer As StringBuilder,
        ByVal count As Integer,
        <MarshalAs(UnmanagedType.LPWStr)> ByVal format As String,
        ByVal arg0 As IntPtr, ByVal arg1 As IntPtr, ByVal arg2 As IntPtr, ByVal arg3 As IntPtr, ByVal arg4 As IntPtr,
        ByVal arg5 As IntPtr, ByVal arg6 As IntPtr, ByVal arg7 As IntPtr, ByVal arg8 As IntPtr, ByVal arg9 As IntPtr
      ) As Integer
      End Function


      ' VB 側の printf ラッパー(最大10引数)
      Friend Function CPrintf(format As String, ParamArray args As Object()) As String
        Dim capacity As Integer = 256
        Dim buffer As New StringBuilder(capacity)

        ' 固定 10 引数に展開するための配列
        Dim ptrs(9) As IntPtr
        Dim allocatedStrings As New List(Of IntPtr)()

        Try
          For i = 0 To Math.Min(args.Length - 1, 9)
            If args(i) Is Nothing Then
              ptrs(i) = IntPtr.Zero
            ElseIf TypeOf args(i) Is String Then
              ' 文字列はアンマネージドの Unicode 文字列に変換してそのアドレスを取得
              Dim p As IntPtr = Marshal.StringToHGlobalUni(DirectCast(args(i), String))
              ptrs(i) = p
              allocatedStrings.Add(p)
            Else
              Dim val As Long = Convert.ToInt64(args(i)) ' 数値の場合の処理
              If IntPtr.Size = 8 Then
                ' x64なら 8byte そのまま積んでOK
                ptrs(i) = New IntPtr(val)
              Else
                ' x86なら 32bitに切り詰める(制限事項:%lld 等は非対応)
                ' ここで 32bit 範囲外なら例外を出すか、下位 32bit のみを渡す
                ptrs(i) = New IntPtr(CInt(val And &HFFFFFFFFL))
                ' double などの浮動小数点は非対応(%f 等は非対応)だが
                ' どうしても渡したいなら、該当引数の定義を As Double にしておく手もアリ
              End If
            End If
          Next

          ' 1回目の呼び出し(サイズ確認)
          ' 可変長引数はサポートされていないため、10個の引数を固定で渡す
          Dim required As Integer = _snwprintf(
            buffer, capacity, format,
            ptrs(0), ptrs(1), ptrs(2), ptrs(3), ptrs(4),
            ptrs(5), ptrs(6), ptrs(7), ptrs(8), ptrs(9)
          )

          ' バッファ不足時の再試行
          ' msvcrt/_snwprintf の仕様により、エラー時は -1 を返す場合と必要サイズを返す場合があるため、両方のケースを考慮する
          If required < 0 OrElse required >= capacity Then
            capacity = If(required < 0, 1024, required + 1)
            buffer = New StringBuilder(capacity)
            _snwprintf(
              buffer, capacity, format,
              ptrs(0), ptrs(1), ptrs(2), ptrs(3), ptrs(4),
              ptrs(5), ptrs(6), ptrs(7), ptrs(8), ptrs(9)
            )
          End If

        Finally
          ' 確保したメモリを解放
          For Each ptr In allocatedStrings
            Marshal.FreeHGlobal(ptr)
          Next
        End Try

        Return buffer.ToString()
      End Function

      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim s As String = CPrintf("Hello %s %d %X %03d World. ", "魔界の仮面弁士", 123, 255, 78)

        ' "Hello 魔界の仮面弁士 123 FF 078 World. "
        MessageBox.Show(s)
      End Sub
    End Class
違反を報告
引用返信
■35699 / ResNo.2)  Re[2]: C言語系で使用される書式をVBで使いたい
□投稿者/ 魔界の仮面弁士 大御所(1595回)-(2026/02/20(Fri) 22:46:27)
  • アイコンNo35697に追伸(魔界の仮面弁士の記事)
    > .NET Framework には無いので、正規表現で分解して自前解析でしょうかね。

    その「自前解析」で再実装された C スタイル書式文字列対応実装ソースが
    下記にあります。ライブラリも NuGet できます。
    https://github.com/adamhewitt627/sprintf.NET/tree/master


    上記 README で Adam 氏も書かれていますが、swprintf を
    直接 P/Invoke するのって、そこそこハードルが高いんですよね…。
    ( No35697 はそれを無理矢理呼んでいるわけですが )
違反を報告
引用返信
■35700 / ResNo.3)  Re[3]: C言語系で使用される書式をVBで使いたい
□投稿者/ かぼちゃプリン 一般人(2回)-(2026/02/21(Sat) 13:44:10)
  • アイコン魔界の仮面弁士様、ありがとうございました。
    C言語系の書式を使用するとなると、結構大がかりなのですね。
    また、ライブラリのご紹介もありがとうございました。

    実際問題として、本当にこの方法で対応すべきかどうかは検討します。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-3]



■記事リスト / ▲上のスレッド
■35578 / 親記事)  抽象クラスで実装したクラスの情報を知る
□投稿者/ 夏風 一般人(1回)-(2024/02/20(Tue) 08:27:18)
  • アイコン環境/言語:[C#] 
    分類:[.NET] 

    はじめまして、夏風といいます。

    現在、DOBONさんの「オブジェクトの内容をファイルに保存、復元する
    オブジェクトのXMLシリアル化、逆シリアル化を行う」(https://dobon.net/vb/dotnet/file/xmlserializer.html)の記事を見ながら、抽象化クラスとして定義できないかと思っています。
    その中で、抽象化クラス側で実装クラスの型や実装クラスへのキャストの仕方がわからなく困っています。

    具体的には、
    >//XmlSerializerオブジェクトを作成
    > //オブジェクトの型を指定する
    > System.Xml.Serialization.XmlSerializer serializer =
    > new System.Xml.Serialization.XmlSerializer(typeof(SampleClass));
    のtypeof(SampleClass)の部分と
    > //XMLファイルから読み込み、逆シリアル化する
    > SampleClass obj = (SampleClass)serializer.Deserialize(sr);
    の(SampleClass)の部分をどうすればいいかわかりません。

    そもそも、抽象クラス側でこのようなことをすること自体が間違っているのでしょうか?
違反を報告
引用返信

▽[全レス3件(ResNo.1-3 表示)]
■35579 / ResNo.1)  Re[1]: 抽象クラスで実装したクラスの情報を知る
□投稿者/ 魔界の仮面弁士 大御所(1569回)-(2024/02/20(Tue) 11:51:36)
  • アイコンNo35578に返信(夏風さんの記事)
    > 抽象化クラス側で実装クラスの型や実装クラスへのキャストの仕方がわからなく困っています。

    意図を理解できているか自信がありませんが、こういうことで良いのかな。


    public class SampleClass : SampleClassBase
    {
      public DateTime TimeStamp;
    }
    public class SampleClass2 : SampleClass { }

    public static class SampleClassBaseExtensions
    {
      public static T LoadFromFile<T>(this T @this, string fileName) where T : SampleClassBase => SampleClassBase.LoadFromFile<T>(fileName);
    }
    public abstract class SampleClassBase
    {
      public int Number;
      public string Message;

      public void SaveToFile(string fileName)
      {
        using (var sw = new System.IO.StreamWriter(fileName, false, new System.Text.UTF8Encoding(false)))
        {
          var serializer = new System.Xml.Serialization.XmlSerializer(GetType());
          serializer.Serialize(sw, this);
          sw.Close();
        }
      }

      public static T LoadFromFile<T>(string fileName) where T : SampleClassBase
      {
        using (var sr = new System.IO.StreamReader(fileName, new System.Text.UTF8Encoding(false)))
        {
          var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
          var obj = (T)serializer.Deserialize(sr);
          sr.Close();
          return obj;
        }
      }
    }

    class MainClass
    {
      public static void Main()
      {
        string fileName = @"C:\test\sample.xml";

        SampleClass obj0 = new SampleClass { Message = "テストです。", Number = 123, TimeStamp = DateTime.Now };

        // <SampleClass>〜</SampleClass> な XML として保存される
        obj0.SaveToFile(fileName);

        // <SampleClass> な XML を SampleClass 以外の型に復元することはできない
        // var obj1 = SampleClassBase.LoadFromFile<SampleClassBase>(fileName);
        // var obj2 = SampleClassBase.LoadFromFile<SampleClass2>(fileName);

        // これらは正しい型なので復元できる
        SampleClass obj3 = SampleClassBase.LoadFromFile<SampleClass>(fileName);
        SampleClass obj4 = obj0.LoadFromFile(fileName);

        // SampleClass のインスタンスとして復元してから、SampleClassBase 型の変数に入れるのは OK
        SampleClassBase obj5 = SampleClassBase.LoadFromFile<SampleClass>(fileName);
        SampleClassBase obj6 = obj0.LoadFromFile(fileName);
      }
    }
違反を報告
引用返信
■35580 / ResNo.2)  Re[1]: 抽象クラスで実装したクラスの情報を知る
□投稿者/ とくま 一般人(4回)-(2024/02/20(Tue) 21:37:29)
  • アイコン
    No35578に返信(夏風さんの記事)
    数年前、同じようなこと考えて色々作り込んだ後、ジェネリックの部分だけ
    あれば事足りるんじゃないかという結論になったことがある。。。
        class MainClass
        {
            public static void Main()
            {
                const string strBasePath = @"C:\test\";
                string strForm1XML = Path.Combine(strBasePath, @"Form1Setting.xml");
                string strForm2XML = Path.Combine(strBasePath, @"Form2Setting.xml");
    
                clsGenericsTest<clsForm1Setting> obj1 = new clsGenericsTest<clsForm1Setting>(strForm1XML);
                clsForm1Setting objSaveItem1 = new clsForm1Setting();
                objSaveItem1.TimeStamp = DateTime.Now;
                obj1.SaveFile(objSaveItem1);
    
                clsGenericsTest<clsForm2Setting> obj2 = new clsGenericsTest<clsForm2Setting>(strForm2XML);
                clsForm2Setting objSaveItem2 = new clsForm2Setting();
                objSaveItem2.TimeStamp = DateTime.Now.AddDays(10);
                obj2.SaveFile(objSaveItem2);
            }
        }
        public class clsForm1Setting
        {
            public DateTime TimeStamp;
        }
        public class clsForm2Setting
        {
            public DateTime TimeStamp;
        }
        public class clsGenericsTest<T> where T : class, new()
        {
            private string _filePath;
            private clsGenericsTest() { }
            public clsGenericsTest(string FilePath) { _filePath = FilePath; }
            public void SaveFile(T item)
            {
                XmlSerializer serializer1 = new XmlSerializer(typeof(T));
                StreamWriter sw = new StreamWriter(_filePath, false, Encoding.GetEncoding("Shift_JIS"));
                serializer1.Serialize(sw, item);
                sw.Close();
            }
            public T ReadFile()
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                StreamReader sr = new StreamReader(_filePath, Encoding.GetEncoding("Shift_JIS"));
                T obj = (T)serializer.Deserialize(sr);
                sr.Close();
    
                return obj;
            }
        }

違反を報告
引用返信
■35581 / ResNo.3)  Re[2]: 抽象クラスで実装したクラスの情報を知る
□投稿者/ 夏風 一般人(4回)-(2024/02/21(Wed) 08:11:52)
  • アイコン魔界の仮面弁士さん、とくまさん
    回答ありがとうございます。

    まだ、さらっとしか見ていませんが、お二人とも同じような考え方で復元のところでジェネリックを使うようにするんですね。

    自分は、魔界の仮面弁士さんの例でいうとSampleClass自体がSampleClassBaseを継承して、LoadFromFileを読んだ時点でSampleClassのTimeStampを戻せないかなと考えていました。
    ただ、これだと実行するまで抽象クラス側では実際の型がわからないのでデバッグ時大変そうになりそうですね。

    お二人に提示していただいたものを参考に作成してみます。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-3]






Mode/  Pass/


- Child Tree -