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

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

記事リスト ( )内の数字はレス数
NomalExcel Com オブジェクトの増殖(13) | NomalRichTextBoxのテキストをpictureBOXへ(12) | NomalPictureBoxの画像を連続保存(11) | NomalVB.NetでVB6.0と同じFontを指定しても同様に印刷されない(9) | Nomal"−"を縦書きにしたい(9) | Nomal作成した白黒画像をWordに貼り付けてから「図として保存」(8) | NomalTreeViewの現在位置とDataGridViewの現在位置を合わせたい(7) | Nomalラジオボタンの一括設定(7) | NomalLabelで文字単位の背景色(7) | NomalTEXTBOXのプロパティを文字列に(7) | NomalDataViewのFindRowsde(7) | Nomal画像のスクロール(6) | Nomalタイマーの一括処理(6) | Nomal先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える(6) | NomalタッチキーボードでIMEを自動で切替えたい(6) | NomalPDFをフォーム上で表示させる方法につきまして(6) | Nomal特定のPCだけ発生する「パディングは無効なので削除できません」のエラーの原因(6) | Nomal複数のPageに分かれる場合のスクレ―ピング(6) | NomalSeleniumで開いているページのTableを編集したい(5) | NomalMP4動画を再生する方法について(5) | NomalLableのカラー色を文字変数から変更したい(5) | NomalDatagridViewでファンクションキーを止めたい(5) | Nomalフォーム背景のみを半透明にしたい(5) | NomalCommandBuilderによって作られるCommandTextの内容(5) | NomalTaskの入れ子の待ち方(5) | NomalDataGridViewの特定セルにボタンを配置する方法(5) | Nomalランダムファイルを高速化させたい(5) | NomalWebView2のEncodeの問題?(5) | Nomalソケット通信入門 ひらがな(4) | Nomal時間変数(文字列)の扱い(4) | NomalTreeViewとDataGridViewのスクロールを同期(シンクロ)させたい(4) | Nomalフォームのリサイズ時にDataGridViewが再描画されない(4) | NomalPDFをフォーム上で表示させる方法につきまして(4) | NomalアプリでHDMIへ出す解像度を変えたい(4) | Nomal画像の中心を基点に回転(4) | NomalDataGridViewの行ヘッダーに行番号を表示した時のエラー(4) | NomalASP.NET WebApi内でXmlReader.Create(url)がタイムアウトする(4) | Nomal正規表現で文字の繰り返しパターン(4) | Nomal.NET6.0 のWinFormにWPFのユーザーコントロールを配置したい(4) | NomalVB-Report10→11への移行(4) | NomalWindowsエクスプローラへのドロップ先フォルダの取得(4) | NomalVBで開いたExcelでのイベントを取得するには(4) | NomalTaskの入れ子の待ち方2(4) | NomalUsingの使い方が間違っている?(4) | NomalTask.Runの使い方(4) | Nomalシステム時計の設定(3) | NomalVisual Basicでエラーが出る(3) | Nomal継承元フォームで各フォームのボタン動作を検知したい(3) | NomalRichTextBoxへのドラッグ&ドロップしたExcelファイルの扱い(3) | Nomal表示動作が重くなる(3) | NomalLoadOptionのパラメータの意味(3) | Nomal1行で書くことできますか?(3) | NomalDataGridのSetDataBindingに代わるもの?(3) | NomalWindowsMediaPlayerで次のURLを指定しても反映されない。(3) | NomalVSTOとWebView2の共存って可能?(3) | NomalProcessクラスMainModuleプロパティでアクセス拒否(3) | NomalLINQでControlsをEnable=Falseに設定(3) | NomalYahooのHPで、検索文字の入力ができない(3) | NomalRGB値の所得(2) | NomalVB.net からAccessDBへの接続(2) | NomalテキストボックスのValidatingイベントよりも先に発生するボタン発生イベントは何でしょう?(2) | NomalWindowsエクスプローラからのドラッグ&ドロップ(2) | Nomalクリックイベントでexeを作成できるか(2) | Nomalc#で日付型の定義の仕方で質問があります。(2) | Nomal列車の時間ごとの位置情報を表示したいです。(2) | NomalUrlにアクセスするとダウンロードされるファイルを捕まえる(2) | Nomalタブレット等でスワイプによるスクロールを実装(2) | Nomalbitmapを複数スレッドで処理したい(2) | Nomal読み出し元フォームの位置取得方法(2) | Nomalコンストラクターに続く{}の意味(2) | Nomalvb.netで7zの圧縮・解凍をしたい。(2) | NomalNPOIでのエクセル編集で期待通りに書き込めません(2) | NomalFormのサイズ変更で掴める辺を制限したい(2) | Nomalビデオ圧縮のコーデック(2) | NomalDataGridViewの列にコンボボックスを表示する(2) | Nomalデータグリッドビューの特定の列ヘッダの色(2) | NomalpictureBoxとlabelの重ね合わせ(2) | Nomal入力値を元に描画させたい(2) | NomalVisualStudio2019 以降の検索ダイアログが正常に動作しない(2) | Nomal//./の意味は?(2) | Nomalバイナリーファイルの結合と分解(2) | NomalCookieの勉強を始めました。(2) | NomalDataGridViewのセル結合部分にボタンを表示する方法(2) | NomalPictureBox のサイズを設定する(2) | Nomalプロセス間の通信(相互)(2) | NomalWinFormでChromeをSeleriumで操作しているが、Closeの仕方(2) | Nomalアセンブリ情報が載らない(1) | Nomal二次元マップから値の取得(1) | NomalDataGridViewのドロップダウンリストの表示と選択後の値を分けたい(1) | NomalVSTOによるエクセルアドインのインストーラーでのアップデート(1) | NomalASP.net デバッグ時の .js ファイルの変更が反映されない(1) | Nomal表の最後の行の下にDropできない(1) | NomalC#をVBに変換する方法が分かりません(1) | NomalPictureBoxに動的に画像を表示する(1) | Nomalインストーラにて、ローミングフォルダにファイルを配置したい(0) | NomalChart X軸上の描画を切り替えたい(0) | NomalC# NASでのプログレスバー有りのコピー(0) | Nomalデフォルトプリンタの用紙向き変更(0) | NomalデザイナでSystemColorsのような色一覧から選択できるようにしたい(0) |



■記事リスト / ▼下のスレッド
■35241 / 親記事)  Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(15回)-(2022/11/27(Sun) 04:14:52)
  • アイコン環境/言語:[[Windows10 VB.NET .NET Framework 4.7.2 VS2019]] 
    分類:[.NET] 

    環境追記
    [Office 365 Excel バージョン2210]
    [Microsoft Excel 16.0 Object Library]


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

    今回Excelの既存データをまとめようと思いまして、
    VB.NETのExcel Comオブジェクトを使用して2枚のExcelを開いて処理しています。

    Excelの処理部分はクラスにまとめ処理していますが、タスクマネージャーで見ると閉じたはずのExcelが残っています。
    いろいろやってみましたが解決できず、お知恵をお借りしたいと投稿致します。


    <参考にしたサイト>
    https://hironimo.com/prog/vbnet/vb-net-excel/
    https://oreno-it2.info/archives/1043
    http://vbnettips.blog.shinobi.jp/file-folder/excel%20%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%93%8D%E4%BD%9C%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%EF%BC%88microsof
    http://hanatyan.sakura.ne.jp/vb2005/vb2013excel01.htm
    http://up-up-everyday.cocolog-nifty.com/wanco_programming/2015/07/vbnetexcel-81a4.html


    ExcelExクラス(抜粋)
    ----------------------------------------------------------------------------------------------------
      'Excel のアプリケーション参照用オブジェクト
      Friend xlsApplication As Excel.Application = Nothing
      'Excel の Workbooks 参照用オブジェクト (Workbook の Collection)
      Friend xlsWorkbooks As Excel.Workbooks = Nothing
      'Excel の Workbooks 内の1個の Workbook 参照用オブジェクト
      Friend xlsWorkbook As Excel.Workbook = Nothing
      'Excel の Workbook 内の Worksheets 参照用オブジェクト (Worksheet の Collection)
      Friend xlsWorkSheets As Excel.Sheets = Nothing
      'Excel の Sheets 内の1個の Worksheet 参照用オブジェクト
      Friend xlsWorkSheet As Excel.Worksheet = Nothing
      'Excel の Sheet 内の1個のセル Range 参照用オブジェクト
      Friend xlsRange As Excel.Range = Nothing

      Private _WorkBook As String = Nothing
      Private _WorkBookIsNew As Boolean = Nothing
      Public Property WorkBook As String
        Set(value As String)
          _WorkBook = value
          Select Case _WorkBook
            Case ""
              WorkBook_Open()
              _WorkBookIsNew = True
            Case "Close"
              _frgClose = True
              WorkBook_Close()
            Case "Save"
              xlsWorkbook.Save()
            Case "SaveAfterClose", "CloseBeforeSave"
              xlsWorkbook.Save()
              _frgClose = True
              WorkBook_Close()
            Case Else
              WorkBook_Open(_WorkBook)
              _WorkBookIsNew = False
          End Select
        End Set
        Get
          Return _WorkBook
        End Get
      End Property

      Private Sub WorkBook_Open(Optional ByVal strFileName As String = Nothing)
        'Excel アプリケーション起動
        xlsApplication = New Excel.Application
        'Excel の Workbooks 取得
        xlsWorkbooks = xlsApplication.Workbooks
        'Excel非表示
        xlsApplication.Visible = False
        xlsApplication.DisplayAlerts = False
        If IsNothing(strFileName) Then
          '新規 Excel ファイルを開く
          xlsWorkbook = xlsWorkbooks.Add()
        Else
          '既存 Excel ファイルを開く
          xlsWorkbook = xlsWorkbooks.Open(strFileName)
        End If
        'Excel の Worksheets 取得
        xlsWorkSheets = xlsWorkbook.Worksheets
        'Excel の Worksheet 取得
        xlsWorkSheet = xlsWorkSheets.Item(1)
        xlsWorkSheet.Select()
        xlsApplication.Visible = ExcelVisible
      End Sub

      Private Sub WorkBook_Close()
        '終了処理
        'xlsRange の解放
        MRComObject(xlsRange, True)
        'xlsWorkSheet の解放
        MRComObject(xlsWorkSheet, True)
        'xlsWorkSheets の解放
        MRComObject(xlsWorkSheets, True)
        'xlsWorkbookを閉じる
        If Not xlsWorkbook Is Nothing Then xlsWorkbook.Close()
        'xlsWorkbook の解放
        MRComObject(xlsWorkbook, True)
        'xlsWorkbooks の解放
        MRComObject(xlsWorkbooks, True)
        'Excelを閉じる
        If Not xlsApplication Is Nothing Then xlsApplication.Quit()
        'xlsApplication を解放
        MRComObject(xlsApplication, True)
      End Sub

      'COM オブジェクトへの参照を解放
      ''' <summary>
      ''' COMオブジェクトの参照カウントをデクリメントします。
      ''' </summary>
      ''' <typeparam name="T">(省略可能)</typeparam>
      ''' <param name="objCom">
      ''' COM オブジェクト持った変数を指定します。
      ''' このメソッドの呼出し後、この引数の内容は Nothing となります。
      ''' </param>
      ''' <param name="force">
      ''' すべての参照を強制解放する場合はTrue、現在の参照のみを減ずる場合はFalse。
      ''' </param>
      Friend Sub MRComObject(Of T As Class)(ByRef objCom As T, Optional ByVal force As Boolean = False)
        If objCom Is Nothing Then Return
        Try
          If System.Runtime.InteropServices.Marshal.IsComObject(objCom) Then
            If force Then
              System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objCom)
            Else
              System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
            End If
          End If
        Finally
          objCom = Nothing
        End Try
      End Sub
    ----------------------------------------------------------------------------------------------------

    上記ExcelExクラスがベースクラスで、子クラス、孫クラスがあります。
    子クラスで、Data As Microsoft.Office.Interop.Excel.Rangeと言うヶ所があるので、
    (必要無いとは思っているものの)MRComObject(Data)と入れてあります。

    ちょっと書いている途中で思いついたので、ベースクラスのみ呼び出して閉じる…
    ----------------------------------------------------------------------------------------------------
      Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ExEx1 = New ExcelEx()
        ExEx1.WorkBook = path & "Test.xlsx"
        ExEx1.xlsApplication.WindowState = Excel.XlWindowState.xlMaximized
        ExEx1.Sheets(1)
        ExEx1.WorkBook = "Close"
      End Sub
    ----------------------------------------------------------------------------------------------------
    を実行してもやはりゴミが残ります。

    Excelを閉じた時にプロセスは終了・削除されると思っているのですが、認識が違うのでしょうか…

違反を報告
引用返信

▽[全レス13件(ResNo.9-13 表示)]
■35253 / ResNo.9)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ 魔界の仮面弁士 大御所(1492回)-(2022/11/27(Sun) 22:56:50)
  • アイコンNo35251に返信(たこさんの記事)
    > Dim check As Boolean = False
    > For Each sh In xlsSheets
    >   If CType(sh, Excel.Worksheet).Name = strSheetName Then
    >     check = True
    >     Exit For
    >   End If
    > Next

    ここがマズイですね。
    MRComObject(sh) が明らかに漏れています。


    また、 No35252 でも紹介したように、COM オブジェクトに対して For Each を使うと、
    System.Runtime.InteropServices.ComTypes.IEnumVARIANT インターフェイス
    (を実装した EnumeratorViewOfEnumVariant クラス) の解放を行うことが難しくなるので
    For ループ または Do ループ あるいは While ループ に置き換えることをお奨めします。



    > Private _ExcelVisible As Boolean = True
    > Friend Property ExcelVisible As Boolean
    >   Set(value As Boolean)
    >     _ExcelVisible = value
    >     If Not _xlsApplication Is Nothing Then _xlsApplication.Visible = _ExcelVisible
    >   End Set
    >   Get
    >     Return _ExcelVisible
    >   End Get
    > End Property

    フラグ管理したいのであれば _xlsApplication などの COM オブジェクトを公開してはいけません。
    ExEx1.xlsApplication.Visible を直接操作されたら、上記の _ExcelVisible フラグが連動しなくなりますよね?

    同様に、Range や Worksheet や Workbook などを公開するのも問題があります。
    公開したいのであれば、カプセル化した独自のマネージ クラスを Return するようにします。


    逆に、COM オブジェクトを公開する仕様とするのであれば、ExcelEx 側の役目はヘルパーライブラリに徹するものとし、
    COM オブジェクトの解放タイミングは呼び出し側に担当させる仕様の方が良いでしょう。この場合、下記の 2 つをルールとします。

    (1) プロシージャ内で生成された COM オブジェクトは、ExcelEx 自身が即座に解放する。
    (2) 呼び出し元から渡された COM オブジェクトや、呼び出し元に Return する COM オブジェクトは、呼び出し側で解放する。
違反を報告
引用返信
■35255 / ResNo.10)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ 魔界の仮面弁士 大御所(1494回)-(2022/11/28(Mon) 06:16:23)
  • アイコンNo35251に返信(たこさんの記事)
    > 問題は無い様に思えるのですが…
    Friend Sub WorkSheet_Select には、もう一つ問題点がありそうです。

    > If Not check Then
    >   _xlsWorkSheet = CType(xlsSheets.Add(), Excel.Worksheet)
    >   xlsWorkSheet.Name = strSheetName
    > Else
    >   _xlsWorkSheet = CType(xlsSheets(strSheetName), Excel.Worksheet)
    > End If
    これだと、「以前に _xlsWorkSheet が参照していた COM オブジェクト」が
    解放されなくなってしまいます。


    No35247 において、解説の最後に
    >> Dim y As Excel.Workbooks = x.Workbooks
    >> Dim z As Excel.Workbooks = x.Workbooks
    という実験コードを書いていますが、この場合、VBA や VBS とは異なり、
    .NET においては y と z が別インスタンスとなることに注意が必要です。

    この場合、COM の参照カウントは y と z それぞれに対して減じねばなりません。
    y と z の両方を RelaseComObject した場合と、どちらか一方しか
    解放しなかった場合とで、Excel の残存性を確認してみてください。

    仮に同一インスタンスを返す仕様であったとしたら、
     Trace.WriteLine(Marshal.ReleaseComObject(z)) 'ア
     Trace.WriteLine(Marshal.ReleaseComObject(y)) 'イ
    において、ReleaseComObject の戻り値から得られる残存参照カウント数が
    「イ = ア - 1」の関係となるはずですが、実際には別インスタンスであるため
    「イ = ア」な戻り値で返されていると思います。
違反を報告
引用返信
■35256 / ResNo.11)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ radian 一般人(1回)-(2022/11/28(Mon) 11:57:41)
  • アイコンちなみに、OfficeのCOMの自動管理をやってくれるライブラリもあります。
    解放漏れを特定出来ない&コードが煩雑になっている場合、
    導入を検討してみるのも手かもしれません。

    https://www.nuget.org/packages/NetOfficeFw.Excel/
    https://github.com/NetOfficeFw/NetOffice
違反を報告
引用返信
■35257 / ResNo.12)  Re[7]: Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(19回)-(2022/11/28(Mon) 22:38:47)
  • アイコンNo35252に返信(魔界の仮面弁士さんの記事)
    No35253に返信(魔界の仮面弁士さんの記事)
    No35255に返信(魔界の仮面弁士さんの記事)
    No35256に返信(radianさんの記事)

    魔界の仮面弁士様、radian様、返信ありがとうございます。

    返信が前後しますが、まずはradian様ご紹介ありがとうございます。
    どうしようも無くなった時は検討させて頂きます(^^ゞ

    余談にはなりますが…
    元々私、プログラミングは全部独学でして、スキルアップの為に今回の質問をさせて頂いています(^^ゞ
    (いつもはどうしようも無くなって質問させて頂いていますが…(^^ゞ)
    まだしっかりと解ってる訳では無いですが、VB6.0からオブジェクトの概念を解る様になるまでは苦労しました^^;

    最終的には会社で5年分くらいExcelで見積書が溜まっていますので、これをデータベース化するのが目的です。。。
    最初はExcel VBAで5年分の見積書の内容をまとめようかと思っていましたが、クラスの概念を覚えてしまうとクラスを使った方が楽なので(^^ゞ
    VB6.0やVBAにもクラスはありますが、使い方が良く解りません…
    …と言う訳でVB.NETで…(^^ゞ

    お気持ちは有難く頂戴致しました。
    ありがとうございます。



    今回、いろいろ調べてやっとExcelのオブジェクトモデルを発見出来ました。
    https://learn.microsoft.com/ja-jp/office/vba/api/overview/excel/object-model
    VBAと同じなのですね…
    当たり前と言えば当たり前ですが…

    Option Strict Onも調べました…
    https://atmarkit.itmedia.co.jp/fdotnet/vb6tonet/vb6tonet26/vb6tonet26_03.html

    DirectCast、CTypeの違いも調べました…
    http://vb.navi-ch.net/2015/07/18/post-118/
    https://learn.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/directcast-operator



    さて、本題に戻ります。

    No35252に返信(魔界の仮面弁士さんの記事)
    >>  Private _xlsApplication As Excel.Application = Nothing
    >>  Friend ReadOnly Property xlsApplication As Excel.Application
    >>    Get
    >>      Return _xlsApplication
    >>    End Get
    >>  End Property
    > これではあまり意味が無いと思いますよ。結局のところ、
    >  Friend ReadOnly xlsApplication As Excel.Application
    > な読み取り専用フィールドと、さほど変わらないように見えます。
    >
    >
    > COM オブジェクトを直接公開してしまうと、ExcelEx の外部で
    >  ExEx1.xlsApplication.Workbooks.Add()
    > などと書かれてしまえば、COM オブジェクトの解放漏れに繋がります。
    >
    > IDisposable としてカプセル化するのであれば、Excel の COM オブジェクトは
    > 外部からは直接操作できないようにして、すべてクラス内に隠蔽します。
    > 戻り値と返すのも COM オブジェクトではなく、.NET のマネージオブジェクトにします。

    全てをクラス内でやってしまう…と言う考え方で良いのでしょうか…
    例えば…
    -----------------------------------------------------------------
    Private _xlsApplication as Excel.Application = Nothing

    Private _ExcelVisible As Boolean = True
    Public Property ExcelVisible As Boolean
      Set(Value as Boolean)
        _ExcelVisible = Value
        If value then
          _xlsApplication.Visible = True
        Else
          _xlsApplication.Visible = False
        End If
      End Set
      Get
        Return _ExcelVisible
      End Get
    End Property
    -----------------------------------------------------------------
    …の様な感じで…

    >>  _xlsWorkSheet = xlsApplication.Sheets.Add()
    > この処理には、問題点が 2 つあります。
    >
    > 1 つは「.」による COM オブジェクトの連続呼び出しであり、
    > Sheets プロパティから返されるコレクションの解放が漏れています。
    Excel.Applicationオブジェクト(COMモデル)の中の、Application.Sheetsプロパティ…あれ?w
    https://learn.microsoft.com/ja-jp/office/vba/api/excel.application.sheets
    COMオブジェクトの場合は(COMオブジェクトの)プロパティの解放も必要と理解して良いのでしょうか…

    >  Dim obj1 = 対象ワークブック.Sheets 'これは Sheets 型        …と言う事は Dim obj1 As Excel.Sheets
    >  Dim obj2 = obj1(strSheetName) 'これは Object 型となることに注意   …と言う事は Dim obj2 As Object
    …で合ってますかね^^?
    ここの理解はまだ追い付いていません(>_<)

    > ただし厳密にいえば、xlsSheets によって列挙されるシートが Excel.Worksheet である保証はありません。
    > Excel.Chart や Excel.DialogSheet が列挙される可能性もあることは頭の片隅に置いといてください。

    …と言う事は…
    -------------------------------------------------------------------------------------
    Friend Sub WorkSheet_Select(strSheetName As String)
      Dim check As Boolean = False
      For x As Integer = 1 to _xlsSheets.Count
        If _xlsSheets(x) Is Excel.Worksheet then                '← 怒られました^^;
          If CType(_xlsSheets (x), Excel.Worksheet).Name = strSheetName Then
            check = True
            Exit For
          End If
        End If
      Next
      If Not check Then
        _xlsWorkSheet = CType(_xlsSheets.Add(), Excel.Worksheet)
        _xlsWorkSheet.Name = strSheetName
      Else
        _xlsWorkSheet = CType(_xlsSheets(strSheetName), Excel.Worksheet)
      End If
      If SheetVisible Then _xlsWorkSheet.Select()
    End Sub
    -------------------------------------------------------------------------------------

    下の方に書いてありました^^;
    >   Dim ws = DirectCast(xlsSheets(n), Excel.Worksheet)
    これだと『WorkSheet』以外はNothingになるのでしょうか…

    (DirectCastは明示的な型変換と書いてありました…
    http://vb.navi-ch.net/2015/07/18/post-118/
    -------------------------------------------------------------------------------------
    サンプルソース
    Dim a As Object = 3.14
    Dim b As Integer = DirectCast(a, Integer)
    MsgBox(b)
    End Sub
    End Class
    実行結果
    メッセージーボックスも表示されません。
    -------------------------------------------------------------------------------------

    頭大パニック中…
違反を報告
引用返信
■35258 / ResNo.13)  Re[8]: Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(20回)-(2022/11/28(Mon) 23:06:02)
  • アイコンNo35257に返信(たこさんの記事)

    ちょっとした実験をしてみました。
    --------------------------------------------------------------------
    Dim w As Excel.Worksheets
    Dim s = w.Item(1)     '←WorkSheetオブジェクトのItemなので、当然WorkSheet型だと思っている
    Dim n = CType(s, Excel.Worksheets).name    '←怒られる…
    --------------------------------------------------------------------

    Dim s As Excel.Worksheets = w.Item(1)   '←やっぱり怒られる…
                         'Option Strict On では'Object'から'Worksheets'への暗黙的な変換は許可されていません。
                         'ReadOnly Property Excel.Wroksheets.Item(Index As Object) As Object

    Dim s As Object = w.Item(1)        'これが正解の様だ…
                         'ここは戻り値がObjectなので理解出来る。

    Dim n = CType(s, Object).name       '←怒られる…
                         'Option Strict On では、遅延バインディングを使用できません。
    一体何の型にキャストすればシート名が取得できるのだろう…

    >『.』の連続」が見えにくくなる
    .を分解するのも苦労します(>_<)

    あ…そう言えばと思い。。。

    Dim w As Excel.Worksheets
    Dim s As Object = w.Item(1)
    Dim sh As Excel.Worksheet = CType(s, Excel.Worksheet)
    Dim n As String = sh.Name

    怒られなくなりました!

    この場合、MRComObjectをしなければならないのは…
    w、s、shで合っていますでしょうか^^?


違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-9] [10-13]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35270 / 親記事)  RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(28回)-(2022/12/05(Mon) 15:45:30)
  • アイコン環境/言語:[Windows10 VS2022 Basic] 
    分類:[.NET] 

    こんにちは
    以前、
    https://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=35233&rev=&no=0
    でLEDモニタの件で画像にすればと提案頂いて格闘していましたが玉砕気味です。
    現状は
    Dim img As Bitmap
    img = New Bitmap(Me.RichTextBox1.Width, Me.RichTextBox1.Height)
    Using g As Graphics = Graphics.FromImage(img)
    g.CopyFromScreen(Me.PointToScreen(Me.RichTextBox1.Location), New Point(0, 0), Me.RichTextBox1.Size)
    End Using
    Me.PictureBox1.Image = img

    です。転送はて来たのですがRichTextBoxの位置情報が上手く取れずに少しずれてしまいます。
    Me.RichTextBox1.Locationの値が連想出来ない数値になってます。
    色々やってみましたが私のコピペ専門の理解度では難しく教えて下さい
    初歩的な質問で申し訳ないですが宜しくお願いします






違反を報告
引用返信

▽[全レス12件(ResNo.8-12 表示)]
■35279 / ResNo.8)  Re[6]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ KOZ 一般人(11回)-(2022/12/08(Thu) 18:38:13)
  • アイコン
    2022/12/09(Fri) 04:27:45 編集(投稿者)
    
    ■No35275に返信(ま〜さんの記事)
    >>高 DPI 環境で実行している場合は、ズレる可能性がありますね。
    > まさにこれが原因でした。凄いです感激です。
    
    これ動きますか?
    ちょっと問題があって、画像を縮小するせいか、少しぼやけた感じになります。
    ,NET Framework 4.7 以上なら RichTextBox の DrawToBitmap を使ったほうがいいかもしれません。
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        <DllImport("User32.dll")>
        Public Shared Function LogicalToPhysicalPointForPerMonitorDPI(ByVal hwnd As IntPtr, ByRef point As Point) As Boolean
        End Function
    
        Private Shared Function LogicalToPhysicalRectangleForPerMonitorDPI(ByVal hwnd As IntPtr, ByVal r As Rectangle) As Rectangle
            Dim p1 As Point = r.Location
            Dim p2 As Point = New Point(r.Right, r.Bottom)
            LogicalToPhysicalPointForPerMonitorDPI(hwnd, p1)
            LogicalToPhysicalPointForPerMonitorDPI(hwnd, p2)
            Return Rectangle.FromLTRB(p1.X, p1.Y, p2.X, p2.Y)
        End Function
    
        Private Function LogicalToPhysicalRectangleForPerMonitorDPI(ByVal r As Rectangle) As Rectangle
            Return LogicalToPhysicalRectangleForPerMonitorDPI(Handle, r)
        End Function
    
        Public Sub New()
            InitializeComponent()
            PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
            PictureBox1.Size = RichTextBox1.Size
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim rectangle1 = RectangleToScreen(RichTextBox1.Bounds)
            Dim rectangle2 = LogicalToPhysicalRectangleForPerMonitorDPI(rectangle1)
            Dim bmp = New Bitmap(rectangle2.Width, rectangle2.Height)
            Using g = Graphics.FromImage(bmp)
                g.CopyFromScreen(rectangle2.Location, Point.Empty, rectangle2.Size)
            End Using
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Image.Dispose()
            End If
            PictureBox1.Image = bmp
        End Sub
    
    End Class
    

違反を報告
引用返信
■35280 / ResNo.9)  Re[7]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(31回)-(2022/12/15(Thu) 13:11:41)
  • アイコンこんにちは、体調を崩して回答が遅れました。すみません。
    ご指導の様にやってみました。DPI環境でもバッチリでした。
    ありがとうございます

    ですがTabPage環境化ではズレました。
    Parentをと思って色々やってみましたが中々上手くいかずTabPage下の座標知る方法はないのでしょうか?
    以上、宜しくお願いします

違反を報告
引用返信
■35282 / ResNo.10)  Re[8]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ KOZ 一般人(12回)-(2022/12/15(Thu) 18:00:28)
  • アイコン
    No35280に返信(ま〜さんの記事)
    > こんにちは、体調を崩して回答が遅れました。すみません。
    
    お大事に。
    
    > ですがTabPage環境化ではズレました。
    > Parentをと思って色々やってみましたが中々上手くいかずTabPage下の座標知る方法はないのでしょうか?
    
    むむむ、やっかいですね高DPI。
    スクリーン座標を取るのが目的でないなら、以下のコードでキャプチャはできると思います。
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        Public Sub New()
            InitializeComponent()
            PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
            PictureBox1.Size = RichTextBox1.Size
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim bmp = CreateBitmapFromControl(RichTextBox1)
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Image.Dispose()
            End If
            PictureBox1.Image = bmp
        End Sub
    
        Private Const SRCCOPY As Integer = &HCC0020
    
        <DllImport("User32.dll")>
        Private Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")>
        Private Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Boolean
        End Function
    
        <DllImport("gdi32.dll")>
        Private Shared Function BitBlt(hdcDest As IntPtr,
                                       nXDest As Integer, nYDest As Integer,
                                       nWidth As Integer, nHeight As Integer,
                                       hdcSrc As IntPtr,
                                       nXSrc As Integer, nYSrc As Integer,
                                       dwRop As Integer) As Boolean
        End Function
    
        Private Shared Function CreateBitmapFromControl(con As Control) As Bitmap
            Dim cs = con.Size
            Dim bmp As New Bitmap(cs.Width, cs.Height)
            Using g = Graphics.FromImage(bmp)
                Dim hdcDest = g.GetHdc()
                Dim hdcSrc = GetWindowDC(con.Handle)
                BitBlt(hdcDest, 0, 0, cs.Width, cs.Height, hdcSrc, 0, 0, SRCCOPY)
                ReleaseDC(con.Handle, hdcSrc)
                g.ReleaseHdc()
            End Using
            Return bmp
        End Function
    
    End Class
    

違反を報告
引用返信
■35295 / ResNo.11)  Re[9]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(32回)-(2022/12/19(Mon) 13:37:36)
  • アイコンPCを変えたりし確認しました。
    バッチリです。
    沢山勉強になりました。
    ありがとうございます。
違反を報告
引用返信
■35296 / ResNo.12)  Re[10]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(33回)-(2022/12/19(Mon) 13:45:34)
  • アイコンクローズ忘れてました。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-9] [10-12]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35316 / 親記事)  PictureBoxの画像を連続保存
□投稿者/ ま〜 一般人(38回)-(2023/01/10(Tue) 19:41:27)
  • アイコン環境/言語:[VS2022 VB] 
    分類:[.NET] 

    こんばんわ
    また困った事がありましてお教え願います
    15個のPictureBoxの画像をグルグル回してファイルに落としたいのですが
    どうも上手くできないのです。
    ファイル保存の方は問題なく出来ると思うのですが
    PictureBoxからイメージを取ってきて受け渡しをどう考えれば宜しいでしょうか?
    宜しくお願いしまうす

違反を報告
引用返信

▽[全レス11件(ResNo.7-11 表示)]
■35323 / ResNo.7)  Re[7]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(42回)-(2023/01/12(Thu) 14:13:11)
  • アイコンいつもありがとうございます
    フィールド変数の件は棚ぼたです。出来ないと思ってました。助かります。

    本題ですが先のコードでわDisposeした方が良いのか程度で書いてました
    Form LoadでDisposeしてますがボタンクリックでTextBoxから画像を生成して各PictureBoxに書いてますので問題ないと解釈していました
    今二つの問題に当たっています。スレッドを分けなかったのは同じ要因かなと思ってです。

    流れ RichTextBoxへ文字入力 ⇒生成⇒ PictureBox16 ⇒サイズを変えてコピー⇒ 各PictureBox ⇒ すべてのPictureBoxの画像をファイル保存


    ――――――――ボタン@――――――――ー
    Dim bmp = CreateBitmapFromControl(Rbox(PageNo))
    If PictureBox16.Image IsNot Nothing Then
      PictureBox16.Image.Dispose()
    End If

    ‘P PageNo←どのPictureBoxを操作するか
    PictureBox16.Image = bmp ← 自動生成されたイメージが入っている
    ‘ピクチャ1−15へ各個転送
    Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, ・・・・・PictureBox15} 
    Picture(PageNo).Image = PictureBox16.Image

    これは同じ画像を各PictureBoxへ書いたと同じ扱いになりますか?一旦PictureBox16経由で各PictureBoxへ作画されています
    これがやっては駄目な事でしょうか?

    最後の書いたPictureBoxをBで保存する事は出来ました。
    それ以外のPictureBox以外でBのコードを実行するエラーとなる

    ―――――――Bエラーになる箇所――――――――――
    Picture(PageNo).Image.Save(PicturePath"MojiGAZou1.bmp",System.Drawing.Imaging.ImageFormat.Bmp)


    Imageは使わない方がよいのでしょうか?

    ―――――――――ボタンA――――――――――――
    試してみました

    Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5}
    For i As Byte = 0 To 4
    Picture(i).Size = New Size(Picture(i).Size.Width, 320)
    Picture(i).Size = New Size(Picture(i).Size.Height, 160)
    Picture(i).SizeMode = PictureBoxSizeMode.Zoom
    Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" & CStr(i + 1) & ".bmp")
    Next

    Me.PictureBox1.Image.Save(PicturePath + "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox2.Image.Save(PicturePath + "MojiGAZou2.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox3.Image.Save(PicturePath + "MojiGAZou3.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox4.Image.Save(PicturePath + "MojiGAZou4.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox5.Image.Save(PicturePath + "MojiGAZou5.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    これもPictureBox1.のSaveの所でエラーとなります。こんな事は出来ない?

    以下はエラーの内容です

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


    Disposeする必要は無いので何か良い方法はありますか?

    あと

    >No35282 の KOZ さんの実装パターンに相当しますね。
    >
    > PictureBox1.Image?.Dispose() '処分
    > PictureBox1.Image = Nothing '解放

    とありますがこれはどの様な意味ですか?

    以上、長々とすみません

違反を報告
引用返信
■35324 / ResNo.8)  Re[8]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ 魔界の仮面弁士 大御所(1516回)-(2023/01/12(Thu) 16:00:58)
  • アイコンNo35323に返信(ま〜さんの記事)
    > 本題ですが先のコードでわDisposeした方が良いのか程度で書いてました
    でわ→では


    > If PictureBox16.Image IsNot Nothing Then
    >   PictureBox16.Image.Dispose()
    > End If
    上記は『PictureBox16.Image?.Dispose()』の一行で書けます。
    https://learn.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/null-conditional-operators

    そして、Disposed 状態のオブジェクトを参照し続けた状態にするのは問題があるため、
    PictureBox16.Image には直ちに、Nothing (あるいは別の画像)を代入しなおさねばなりません。

    ただし本来は、別の画像(あるいはNothing)を割り当ててから元の画像を Dispose した方が望ましいです。


    > PictureBox16.Image = bmp ← 自動生成されたイメージが入っている
    > Picture(PageNo).Image = PictureBox16.Image
    > これは同じ画像を各PictureBoxへ書いたと同じ扱いになりますか?

    一つの画像を複数の PictureBox から参照している状態になりますね。


    つまり、一枚の絵画を複数人で同時に鑑賞している状態に相当します。
    ということは、その絵画を破損させれば、他の閲覧者も破損した絵画を見ることになってしまいます。
    もしも閲覧者A が、自身が見ている絵画を破棄したとすれば、
    それは閲覧者B や C が見ている絵画も捨てられたことを意味します。

    Picture(0).Image を Dispose() した場合、
    Picture(1).Image も破棄されるので、ArgumentException 等になってしまう所以です。


    しかしあらかじめ、一枚の元絵を人数分複製しておき、それを閲覧させるようにすれば、
    元絵を破損させたとしても、各閲覧者の見ている画像が見えなくなることはありません。

    これはすなわち、
     Picture(PageNo).Image = DirectCast(PictureBox16.Image?.Clone(), Image)
    のようにしておく、ということです。それぞれの画像は元絵の複製にすぎないわけですから、
    Picture(0).Image を Dispose() したとしても、
    Picture(1).Image や PictureBox16.Image には影響がありません。


    > 一旦PictureBox16経由で各PictureBoxへ作画されています
    > これがやっては駄目な事でしょうか?
    何を経由させても構いません。
    変数であろうと PictureBox16.Image であろうと大丈夫です。

    問題になっているのは、PictureBox16 を経由させたことではなく、
    「使用中のオブジェクトを Dispose したこと」です。


    Picture(0) がその画像を使わなくなったとしても、他の PictureBox が
    同じインスタンスを使用しているのなら、Dispose してはいけません。
    捨てるなら、「誰も使わなくなってから」にしましょう。



    > ―――――――Bエラーになる箇所――――――――――
    > Picture(PageNo).Image.Save(PicturePath"MojiGAZou1.bmp",System.Drawing.Imaging.ImageFormat.Bmp)
    そもそも文法違反になるでしょうね。(^_^;)


    > Imageは使わない方がよいのでしょうか?
    いいえ。「誰かが使用している最中の Image を勝手に Dispose してはいけない」というだけです。

    「使い終わった Image は Dispose しなければならない」ルールであるのは確かですが、
    「私が使い終わったので、他の人が使っていたとしても勝手に捨ててしまおう」はルール違反です。


    > Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5}
    > For i As Byte = 0 To 4
    配列のインデックスは常に Integer 型です。Byte 型ではありません。

    Byte/SByte/Short/UShort は Integer 型への暗黙変換が可能なのでエラーにはなりませんが、
    わざわざ Byte 型を経由させると、無駄な変換処理が増えることになってしまいます。

    そのため普通は As Byte とはせず、「For i = 0 To 4」もしくは「For i As Integer = 0 To 4」と書きます。


    > Picture(i).Size = New Size(Picture(i).Size.Width, 320)
    > Picture(i).Size = New Size(Picture(i).Size.Height, 160)

    これって、
     Picture(i).Width = Picture(i).Size.Width
     Picture(i).Height = 320
     Picture(i).Width = Picture(i).Size.Height
     Picture(i).Height = 160
    に相当する処理ですよね。何故こんなことを…?

    幅と高さを指定するだけならば、
     Picture(i).Size = New Size(320, 160)
    では駄目なのでしょうか。SizeMode 指定のために必要だったとか?

    > Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" & CStr(i + 1) & ".bmp")
    前 1 つが「+ 演算子」で、
    後 2 つが「& 演算子」なのは何故ですか?


    > Me.PictureBox1.Image.Save(PicturePath + "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox2.Image.Save(PicturePath + "MojiGAZou2.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox3.Image.Save(PicturePath + "MojiGAZou3.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox4.Image.Save(PicturePath + "MojiGAZou4.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox5.Image.Save(PicturePath + "MojiGAZou5.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > これもPictureBox1.のSaveの所でエラーとなります。こんな事は出来ない?

    「Image が Dispose されていない」かつ「指定のパスに書き込みが可能」な状態にしておけば
    上記のコードでもエラーにはならないと思いますよ。

    仮に Dispose していなかったとしても、その画像が Image.FromFile で読み込まれていて、
    かつ、そのインスタンスがまだ破棄されていなかったとしたら、ファイルがロックされたままになるので
    また別のエラーを誘発する可能性がありますね。


    >> PictureBox1.Image?.Dispose() '処分
    >> PictureBox1.Image = Nothing '解放
    > とありますがこれはどの様な意味ですか?

    If PictureBox1.Image IsNot Nothing Then
     PictureBox1.Image.Dispose() '処分
    End If
    PictureBox1.Image = Nothing '解放

    という意味です。

    KOZ さんの書かれた No35282 の場合は、
     Dim bmp = CreateBitmapFromControl(RichTextBox1)
     If PictureBox1.Image IsNot Nothing Then
       PictureBox1.Image.Dispose()
     End If
     PictureBox1.Image = bmp
    ですね。

    いずれも、「bmp (または Nothing)を参照させる前に、以前の画像があれば Dispose する」という処理です。
    以前の画像を「処分してから解放」の順序になっているので、本当は「解放してから処分」の方が良いのですが。

    上記 No35282 のコードを「解放してから処分」にするのであれば
     Using PictureBox1.Image
      PictureBox1.Image = CreateBitmapFromControl(RichTextBox1)
     End Using
    または
     Dim oldImage = PictureBox1.Image
     PictureBox1.Image = CreateBitmapFromControl(RichTextBox1)
     oldImage?.Dispose()
    と書きます。自分は後者の方が好みですが、 No35282 のままでも問題はありません。
違反を報告
引用返信
■35330 / ResNo.9)  Re[9]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(44回)-(2023/01/16(Mon) 14:20:51)
  • アイコンいつもありがとうございます
    貴重なお時間割いて頂きご指導ありがとうございます
    今回も知らない事が多く大変勉強になりました
    最終目標はテキストから生成した画像を保存なので道のり長いですが宜しくお願いします

    テスト的にやって見た所。下記の2行目でエラーとなります。まさに沼です

      Me.PictureBox1.Image = Image.FromFile(PicturePath & "MojiGAZou1.bmp")
      Me.PictureBox1.Image.Save(PicturePath & "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    2行目をコメントアウトして確認した所、表示はされてるのでファイルとかの問題ではなさそうです。。
    何か基本的なのが抜けてる気がしてきました。読み込んだだけでは保存出来ないのでしょうか?


    ーーーーーーーーーエラーの内容-----
    System.Runtime.InteropServices.ExternalException
    HResult=0x80004005
    Message=GDI+ で汎用エラーが発生しました。
    Source=System.Drawing

    余談ですが「は」「わ」の件ですが私も違和感あったのですが最近の若者からのメールが
    「わ」使う子が多くいつの間にか私も影響受けてるみたいです。(笑)

    あと+と&は修正途中でした。。意味はありません
違反を報告
引用返信
■35331 / ResNo.10)  Re[10]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ 魔界の仮面弁士 大御所(1519回)-(2023/01/16(Mon) 16:14:25)
  • アイコン2023/01/16(Mon) 16:30:46 編集(投稿者)

    No35330に返信(ま〜さんの記事)
    > テスト的にやって見た所。下記の2行目でエラーとなります。まさに沼です
    >   Me.PictureBox1.Image = Image.FromFile(PicturePath & "MojiGAZou1.bmp")
    >   Me.PictureBox1.Image.Save(PicturePath & "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    先の No35322 で紹介した通り、 Image.FromFile がファイルをロックしているためです。


    '駄目な例1
    PictureBox1.Image = Image.FromFile(bmpFile)
    'System.Runtime.InteropServices.ExternalException: 'GDI+ で汎用エラーが発生しました。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な例2
    PictureBox1.Image = Image.FromFile(bmpFile)
    PictureBox1.Image.Dipose()
    'System.ArgumentException: '使用されたパラメーターが有効ではありません。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '★修正例★
    PictureBox1.Image = Image.FromStream(New MemoryStream(File.ReadAllBytes(bmpFile)))
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例1
    PictureBox1.Image = Image.FromStream(New MemoryStream(File.ReadAllBytes(bmpFile)))
    PictureBox1.Image.Dipose()
    'System.ArgumentException: '使用されたパラメーターが有効ではありません。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例2
    Using stm As New FileStream(bmpFile, FileMode.Open, FileAccess.Read)
     PictureBox1.Image = Image.FromStream(stm)
    End Using
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例3
    Using stm As New MemoryStream(File.ReadAllBytes(bmpFile))
     PictureBox1.Image = Image.FromStream(stm)
    End Using
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)



    追記:こういう手もあるかな。

    Using img = Image.FromFile(pngFile)
     PictureBox1.Image = New Bitmap(img)
    End Using
    PictureBox1.Image.Save(pngFile, System.Drawing.Imaging.ImageFormat.Bmp)

    上記は、 No8405 のスレッドの "中 博俊" さん( No8447 )の案です。
    >>> New Bitmap(bmp)
    >>> で、新しいBitmapにコピーされますよ。
    >>>
    >>> ただし全てがコピーされるわけじゃなくってDPIが保持されないとか、現在のページだけ(マルチページな画像の場合)とかやや違いはありますが。
違反を報告
引用返信
■35340 / ResNo.11)  Re[11]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(46回)-(2023/01/20(Fri) 12:55:32)
  • アイコン沢山のアドバイスありがとうございます
    またまた、勉強になりました。

    少しハマりながらもなんとか目的の事が出来ました。

    重ねてありがとうございます

    クローズします。

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

■記事リスト / レス記事表示 → [親記事-9] [10-11]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35185 / 親記事)  VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(1回)-(2022/10/21(Fri) 11:45:23)
  • アイコン環境/言語:[環境(Windows10 64bit)、使用言語(VB.net2017)、.NET Framework 4.6.1 ] 
    分類:[.NET] 

    いつも参照させていただいています。

    現在、VB6.0で書かれた印刷プログラムをVB.Netに移行しています。
    その中で、VB6.0と全く同じ座標とFont種類・サイズを指定しても、
    VB.Netで印刷すると、少し右にずれてしまうし、Fontのサイズが微妙に違ってしまいます。
    Fontの高さは同じようなのですが、文字と文字の隙間が微妙に違うようで、長い文字列を印刷すると、印刷された文字の長さがVB.Netの方が長くなってしまうのです。
    座標系はどちらも、ミリメートルを指定しています。
    VB.Netで印刷された文字列の前に空白が付くことは、下記のサイトを参照して分かったので、ずれる分を引いた座標を指定したら、右にずれる件は解決したのですが、同じFontを指定しても違ってしまう件が解決できません。
    同じプリンタとプリンタドライバを使用しているのに、どうしてVB6.0とVB.Netで違ってしまうのか、まったくわかりません。

    ・使用しているプリンタ ラベルプリンタ SATO CL4NX-J 609dpi
    ・プリンタ解像度 609dpi 24dot/mm

    ・参考にしたサイト
    VB.netで文字を正確な位置に描く。
    https://penguinlab.jp/blog/post/117

    ※VB6.0のサンプル

    Printer.ScaleMode = 6
    Printer.FontName = "MS ゴシック"
    Printer.FontSize = 9
    Printer.CurrentX = 12.5
    Printer.CurrentY = 30.7
    Printer.Print "IN-OUT<AB>CD EFG-HIJK-LMN A<10>"

    ※VB.Netのサンプル

    e.Graphics.PageUnit = GraphicsUnit.Millimeter
    Dim f As New Font("MS ゴシック", 9, FontStyle.Regular)
    e.Graphics.DrawString("IN-OUT<AB>CD EFG-HIJK-LMN A<10>", f, Brushes.Black, 12.5, 30.7)

    こんな感じです。


    どなたかわかる方、どうかアドバイスをお願いいたします。

違反を報告
引用返信

▽[全レス9件(ResNo.5-9 表示)]
■35202 / ResNo.5)  Re[5]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1467回)-(2022/10/26(Wed) 18:29:47)
  • アイコンNo35200に返信(ゆりりんさんの記事)
    > 想定していたよりかなり小さく印刷されてしまい、
    物理単位と論理単位の違いでは無いでしょうか。

    恐らく、最初の回答で述べた「TextRenderer.DrawText」を使った場合と
    同じぐらいのサイズで描画されていませんか?

    GDI+ 側の PageUnit プロパティを操作しても、
    GDI 側のデバイスコンテキストには影響を与えないと思います。


    > 座標は合っているようなのですが、想定していたよりかなり小さく印刷されてしまい
    単位系が未設定の場合、初期値として
    GDI+ 側(PageUnit プロパティ)は Display(1) を返し、
    GDI 側(GetMapMode API)は MM_TEXT(1) を返すようです。

    Sub SetFont でフォントを生成する際に、
    MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    生成するようにしてみては如何でしょうか。


    > Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
    >  Dim mFont As IntPtr
    ここで宣言されたローカル変数の mFont と

    > Private Sub SetFont(ByVal control As IntPtr, ByVal fontFamily As String, ByVal fontSize As Integer)
    >  mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    ここで利用されているフィールド変数の mFont は
    それぞれ別の変数ですが、大丈夫ですか?
違反を報告
引用返信
■35207 / ResNo.6)  Re[6]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(4回)-(2022/10/28(Fri) 10:38:17)
  • アイコンいつもありがとうございます。

    > 物理単位と論理単位の違いでは無いでしょうか。
    >
    > GDI+ 側の PageUnit プロパティを操作しても、
    > GDI 側のデバイスコンテキストには影響を与えないと思います。

     そういうことだったのですね。

    > Sub SetFont でフォントを生成する際に、
    > MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    > 生成するようにしてみては如何でしょうか。

     早速、やってみようと思います。
     
    >> Dim mFont As IntPtr
    > ここで宣言されたローカル変数の mFont と
    >
    >> mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    > ここで利用されているフィールド変数の mFont は
    > それぞれ別の変数ですが、大丈夫ですか?

     すみません。
     ここに載せる時に、間違えました。
     実際には、論理フォントの作成の後に入っています。
     お気づきいただき、ありがとうございました。
違反を報告
引用返信
■35212 / ResNo.7)  Re[6]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(5回)-(2022/10/28(Fri) 16:49:02)
  • アイコン> Sub SetFont でフォントを生成する際に、
    > MM_TEXT から MM_LOMETRIC あるいは MM_HIMETRIC で
    > 生成するようにしてみては如何でしょうか。


    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")>
    Friend Shared Function SetMapMode(ByVal hdc As Integer, ByVal fnMapMode As Integer) As Integer
    End Function

     を追加しまして、

    Private Sub SetFont(ByVal control As IntPtr, ByVal fontFamily As String, ByVal fontSize As Integer)

    Call SetMapMode(control, 2) 'MM_LOMETRIC
    mFont = CreateFont(fontSize * -1, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, fontFamily)
    mFontOld = SelectObject(control, mFont)

    End Sub

     このように書いてみたのですが、
     何も印刷されなくなってしまいました。
     SetMapMode の使い方が、間違っているのでしょうか。

     度々申し訳ございません。
     ご教授いただければと思います。
     どうぞよろしくお願いいたします。


違反を報告
引用返信
■35214 / ResNo.8)  Re[7]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ 魔界の仮面弁士 大御所(1473回)-(2022/10/28(Fri) 21:29:20)
  • アイコン
    No35212に返信(ゆりりんさんの記事)
    > 何も印刷されなくなってしまいました。
    
    『フォントサイズ』の指定、および、『描画位置の座標』は正しいですか?
    
    MM_TEXT から MM_LOMETRIC に変更したのであれば、フォントサイズだけでは無く
    描画座標も MM_LOMETRIC 単位系で計算しなおす必要があります。
    
    
    描画位置を変更したくない場合は、GetMapMode と SetMapMode をペアで使うようにして、
    フォント作成後、描画時に座標系を元に戻してみてください。先の私の回答では、フォントを
    「MM_LOMETRIC あるいは MM_HIMETRIC で生成する」とは書きましたが、
    「MM_LOMETRIC あるいは MM_HIMETRIC で描画する」とは書いていません。
    
    
    MapMode は 1〜8 の 8 種類あります。指定するモードによっては、
    単位だけでなく軸の向きも変化していることに注意してください。
    
     (A) X 座標が右に、Y 座標が上に向かって増加していくもの
     (B) X 座標が右に、Y 座標が下に向かって増加していくもの
     (C) SetWindowExtEx() / SetViewportExtEx() で単位、向き、スケーリングを指定するもの
     http://www.kumei.ne.jp/c_lang/sdk/sdk_55.htm
     http://yamatyuu.net/computer/program/sdk/gdi/mapmode/index.html
    
    ---
    
    (A) 右向き、上向きな MapMode
     1 … MM_TEXT。1 デバイスピクセル単位の物理座標系。
     6 … MM_TWIPS。0.05ポイント単位(1/1440インチ単位)の論理座標系。
    
    (B) 右向き、下向きな MapMode
     2 … MM_LOMETRIC。0.1 ミリ単位の論理座標系。
     3 … MM_HIMETRIC。0.01 ミリ単位の論理座標系。
     4 … MM_LOENGLISH。0.01 インチ単位の論理座標系。
     5 … MM_HIENGLISH。0.001 インチ単位の論理座標系。
    
    (C) 単位、向き、スケーリングを任意に指定できる MapMode
     7 … MM_ISOTROPIC。異方性ユーザー定義単位系。任意の単位、向き、スケーリングを持つ。
     8 … MM_ANISOTROPIC。等方性ユーザー定義単位系。X 軸と Y 軸の 1 単位が等しい。

違反を報告
引用返信
■35215 / ResNo.9)  Re[8]: VB.NetでVB6.0と同じFontを指定しても同様に印刷されない
□投稿者/ ゆりりん 一般人(6回)-(2022/11/02(Wed) 11:23:32)
  • アイコン> 描画位置を変更したくない場合は、GetMapMode と SetMapMode をペアで使うようにして、
    > フォント作成後、描画時に座標系を元に戻してみてください。先の私の回答では、フォントを
    > 「MM_LOMETRIC あるいは MM_HIMETRIC で生成する」とは書きましたが、
    > 「MM_LOMETRIC あるいは MM_HIMETRIC で描画する」とは書いていません。
    >
    そういうことだったのですね。
    よくわかっていませんでした。

    『描画位置の座標』はピクセルで計算していたので、
    MM_TEXTの指定にしたら、きちんと印刷されるようになりました。

    今までどうもありがとうございました。


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

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



■記事リスト / ▲上のスレッド
■35041 / 親記事)  "−"を縦書きにしたい
□投稿者/ キウイ 一般人(1回)-(2022/05/05(Thu) 19:15:33)
  • アイコン環境/言語:[Windows10 / VB.NET2019] 
    分類:[.NET] 

    VB.NET2019において、PictureBoxに縦書きで文字を書くコードを作成しています。
    '指定座標に一文字描画
    Sub DrawChar(ByVal drawChar As String, ByVal font As Font, ByVal pt As Point, ByVal g As Graphics)

    Dim ZenkakuStf As New StringFormat(StringFormatFlags.DirectionVertical)
    Dim brush1 As Brush = New SolidBrush(ForeColorLabel.ForeColor)

    g.DrawString(drawChar, font, brush1, pt, ZenkakuStf)
    End Sub

    PictureBoxに縦書きで1文字表示する、こんな感じのメソッドを作成しました。
    ひらがな、カタカナ、漢字等は問題なく表示されます。
    ここで問題なのが"−"という文字で"|"のように縦線で表示したいのですが、"−"のように横線で表示されてしまいます。
    If (drawChar = "−") Then
    g.DrawString(drawChar, CharFont, brush1, pt)
    Else
    g.DrawString(drawChar, CharFont, brush1, pt, ZenkakuStf)
    End If
    のように"−"だけ縦書き指定を外してみましたが、やはり"−"になってしまいます。
    縦線に表示する方法はないでしょうか。


違反を報告
引用返信

▽[全レス9件(ResNo.5-9 表示)]
■35046 / ResNo.5)  Re[2]: "−"を縦書きにしたい
□投稿者/ キウイ 一般人(3回)-(2022/05/06(Fri) 19:37:49)
  • アイコンNo35043に返信(YuOさんの記事)
    > ■No35041に返信(キウイさんの記事)
    >>ここで問題なのが"−"という文字で"|"のように縦線で表示したいのですが、"−"のように横線で表示されてしまいます。
    >
    > 以下のようなコードを使って試してみましたが (VS 2022)、
    > ・.NET Framework 4.8
    > ・.NET 6
    > ・.NET 5
    > ・.NET Core 3.1
    > のすべてにおいて、縦書きで正しく表示されました。
    > 特殊なフォントを指定したりしていないでしょうか。
    >
    > --- コード ---
    > Private Const Message As String = "初めて投稿される方は、必ず「書き込みのルールについて(12/4/2更新)」をお読みください。"
    >
    > Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    > Dim format As New StringFormat(StringFormatFlags.DirectionVertical)
    > Using font As New Font("遊ゴシック", 15.0)
    > e.Graphics.DrawString(Message, font, Brushes.Black, 10.0, 10.0, format)
    > e.Graphics.DrawString(Message, font, Brushes.Black, 40.0, 40.0)
    > End Using
    > End Sub
    > --- コード ---
    >
    指定のフォントはデフォルト値である「MS ゴシック」「14.25」です。

    If (drawChar = "−") Then
    Dim format As New StringFormat(StringFormatFlags.DirectionVertical)
    Using font1 As New Font("遊ゴシック", 14.0)
    g.DrawString("−", font1, Brushes.Black, 10.0, 10.0, format)
    g.DrawString("−", font1, Brushes.Black, 40.0, 40.0)
    End Using

    'g.DrawString("|", CharFont, brush1, pt)
    Else
    g.DrawString(drawChar, CharFont, brush1, pt, ZenkakuStf)
    End If
    ↑のようにしてみましたが、表示されるのは横線でした。

違反を報告
引用返信
■35047 / ResNo.6)  Re[3]: "−"を縦書きにしたい
□投稿者/ 魔界の仮面弁士 大御所(1422回)-(2022/05/06(Fri) 19:58:42)
  • アイコンNo35046に返信(キウイさんの記事)
    > 指定のフォントはデフォルト値である「MS ゴシック」「14.25」です。

    "MS ゴシック" ではなく
    "MS ゴシック" ですよね?


    > Using font1 As New Font("遊ゴシック", 14.0)

    "遊ゴシック" ではなく
    "游ゴシック" ですよね?



    また、OS の正確なバージョン番号も御提示ください。
    https://answers.microsoft.com/ja-jp/windows/forum/all/windows-10-april-2018/2c82da6b-ddec-4a9f-8f48-c1c4255242ea
    https://answers.microsoft.com/ja-jp/msoffice/forum/all/excel%E3%81%A7meiryoui%E3%81%AE%E7%B8%A6%E6%9B%B8/9fd56af1-cc77-4725-9a07-ecf8a667dfdc
違反を報告
引用返信
■35050 / ResNo.7)  Re[4]: "−"を縦書きにしたい
□投稿者/ キウイ 一般人(5回)-(2022/05/07(Sat) 00:14:06)
  • アイコンNo35047に返信(魔界の仮面弁士さんの記事)
    > ■No35046に返信(キウイさんの記事)
    >>指定のフォントはデフォルト値である「MS ゴシック」「14.25」です。
    >
    > "MS ゴシック" ではなく
    > "MS ゴシック" ですよね?
    >
    >
    >>Using font1 As New Font("遊ゴシック", 14.0)
    >
    > "遊ゴシック" ではなく
    > "游ゴシック" ですよね?
    >
    >
    >
    > また、OS の正確なバージョン番号も御提示ください。
    > https://answers.microsoft.com/ja-jp/windows/forum/all/windows-10-april-2018/2c82da6b-ddec-4a9f-8f48-c1c4255242ea
    > https://answers.microsoft.com/ja-jp/msoffice/forum/all/excel%E3%81%A7meiryoui%E3%81%AE%E7%B8%A6%E6%9B%B8/9fd56af1-cc77-4725-9a07-ecf8a667dfdc

    すみません。
    "MS ゴシック"
    です。

    "遊ゴシック"→"游ゴシック"に修正してみましたが、横線でした。
    念のため、"メイリオ"、"MS Pゴシック"にしてやってもみましたが、横線でした。


    OSバージョンは
    -------------------------------------------------
    エディション Windows 10 Home
    バージョン 21H2
    インストール日 &#8206;2022/&#8206;01/&#8206;05
    OS ビルド 19044.1645
    エクスペリエンス Windows Feature Experience Pack 120.2212.4170.0
    -------------------------------------------------


    以下のコードで、
    Dim CharFont As Font
    Dim fontFam As FontFamily
    Dim ZenkakuStf As New StringFormat(StringFormatFlags.DirectionVertical)

    fontFam = font.FontFamily
    CharFont = New Font(fontFam, 14)

    Dim brush1 As Brush = New SolidBrush(ForeColorLabel.ForeColor)

    g.DrawString(drawChar, CharFont, brush1, pt, ZenkakuStf)

    "−…「」"という文字列で実行した結果が添付画像です。
    左から
    "MS ゴシック"、"メイリオ"、"游ゴシック"の順です。
    fontFam変数に上記フォント名が入っているのは確認しています。

    >https://answers.microsoft.com/ja-jp/msoffice/forum/all/excel%E3%81%A7meiryoui%E3%81%AE%E7%B8%A6%E6%9B%B8/9fd56af1-cc77-4725-9a07-ecf8a667dfdc
    こちらに書かれていた記事を追跡してメイリオのフォントが6.50なのは確認しましたが、古いものに戻すというのはモノがないので無理です。
    もしかしてOSレベルのバグなのでしょうか。うーん。

103×100
イメージ
font.jpg
/4KB
違反を報告
引用返信
■35052 / ResNo.8)  Re[5]: "−"を縦書きにしたい
□投稿者/ 魔界の仮面弁士 大御所(1424回)-(2022/05/07(Sat) 14:11:59)
  • アイコンNo35050に返信(キウイさんの記事)
    > インストール日 &#8206;2022/&#8206;01/&#8206;05
    最近の WinApp って、不可視文字な LRM が混入することが増えてきていて、
    Unicode 非対応の環境にコピペした時に文字化けして困りますね…。
    (たとえば、ファイルのプロパティの作成日時などの欄など)

    化けてしまっている 8206 は、Left-to-Right Mark の不可視文字ですね。
    アラビア語やヘブライ語のように、文章を右から左に書く言語において
    英単語などの左から右に記述する語を挿入する際に使われます。


    ――閑話休題。


    > "−…「」"という文字列で実行した結果が添付画像です。
    当方の 21H2 環境 (Win10 および Win11) でも同様でした。
    "NSimSun" だと回転しましたが…。※Microsoft Word の縦書きでも同様。

    U+002D,U+2010-2015,U+FF0D あたりの文字は、フォントによって
    縦書き用字形を持っているかどうかが異なるので、個別対応が必要になるかも。


    > CharFont = New Font(fontFam, 14)
    > Dim brush1 As Brush = New SolidBrush(ForeColorLabel.ForeColor)
    New した Font や Brush は、使用後に Dispose (Using) しましょう。


    > メイリオのフォントが6.50なのは確認しましたが、
    フォントバージョンの違いについては調べ切れていませんが、手始めに
    ・そもそも書字方向依存グリフであるのか否か。
    ・OS 依存性、フォント依存性があるのかどうか。
    ・GDI+ の場合と GDI の場合で差があるかどうか
    などを調査して、対応を考えていくという方針ではどうでしょう?
    (別フォントで代用、別文字で代用、別の描画方法を併用など)


    参考情報として、VerticalOrientation.txt を紹介しておきます。
    UAX #50 (Unicode Vertical Text Layout)
    https://www.unicode.org/Public/UCD/latest/ucd/VerticalOrientation.txt

    FF0D '−' や 002D '-' は「R」で、
    30FC 'ー' は「Tr」だそうな。

    # U - Upright, the same orientation as in the code charts
    # R - Rotated 90 degrees clockwise compared to the code charts
    # Tu - Transformed typographically, with fallback to Upright
    # Tr - Transformed typographically, with fallback to Rotated


    YuO さんが試された 30FC 'ー' にしても、フォントによっては
    左右非対称の字形だったりしますから、たとえ横書きするにしても、
    Left-to-Right で描画した時と、Right-to-Left の時とで、
    描画を反転させるべきか否か、という問題があったりします。


    参考までに、当方の描画結果と実験コードを載せておきます。
    DpiAwareneww は PerMonitorV2 設定です。

    Option Strict On
    Public Class Form1
      Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
        Const LANGID_JA_JP As Integer = &H411
        'NoFontFallback は、非対応の文字を代替フォントではなく豆腐文字で描画するための指定
        Dim vertFmt As New StringFormat(StringFormatFlags.DirectionVertical Or StringFormatFlags.NoFontFallback, LANGID_JA_JP)
        Dim horiFmt As New StringFormat(StringFormatFlags.NoFontFallback, LANGID_JA_JP)
        Dim charcters = ChrW(&H201C) & ChrW(&HFF0D) & ChrW(&H2026) _
            & ChrW(&H300C) & ChrW(&H300D) & ChrW(&H2D) & ChrW(&H30FC) _
            & ChrW(&HFE31) & ChrW(&HFE32) & ChrW(&HFE33) _
            & ChrW(&H7C) & ChrW(&HFF5C) & ChrW(&H201D)
        Dim fontNames = {"MS ゴシック", "メイリオ", "游ゴシック", "NSimSun", "Microsoft JhengHei"}
        e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
        For x = 0 To fontNames.Length - 1
          'Dim fontName = $"@{fontNames(x)}"
          Dim fontName = fontNames(x)
          Using charFont As New Font(fontName, 14.0F)
            Dim pt1 As New Point(15 + x * 65, 15)
            e.Graphics.DrawString($"{charcters}//{fontName}", charFont, Brushes.MediumBlue, pt1, vertFmt)
            Dim pt2 As New Point(350, 15 + x * 45)
            e.Graphics.DrawString($"{charcters}//{fontName}", charFont, Brushes.Crimson, pt2, horiFmt)
          End Using
        Next
      End Sub
    End Class
1161×861 => 250×185
イメージ
Vertical.png
/18KB
違反を報告
引用返信
■35053 / ResNo.9)  Re[6]: "−"を縦書きにしたい
□投稿者/ キウイ 一般人(6回)-(2022/05/07(Sat) 18:43:17)
  • アイコンNo35052に返信(魔界の仮面弁士さんの記事)
    実験までしていただいて恐縮です。
    このコードでのアプリにおいてはフォント指定もユーザに出来るようにしたいので、フォント限定というのはしたくないし・・・


    'g.DrawString(drawChar, CharFont, brush1, pt, ZenkakuStf)
    Dim flags As TextFormatFlags = TextFormatFlags.VerticalCenter
    TextRenderer.DrawText(g, drawChar, CharFont, New Rectangle(pt.X, pt.Y, 30, 30), ForeColorLabel.ForeColor, flags)
    こんな感じでGDIでの描画も試してみましたが、やはり横線のままでした。

    もういっそ、1文字分を画像処理で90度回転するのが確実な気もしてきました。
    座標と描画サイズはわかっているのだし・・・

    ありがとうございます。

違反を報告
引用返信

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






Mode/  Pass/


- Child Tree -