C# WinformのReoGridで図形描画をしたい

タグの編集
投稿者 えんぴー  (社会人) 投稿日時 2023/9/7 10:43:39
・画像の選択/表示/削除 (エクセルに読み込んで表示したり消したりしたい)
・図形描画 (基本的には四角形だけあれば問題ないと思われます)
  →できたら、この図形を右クリックしたときにメニューを出したい

・描画した図形の情報(表示位置や色などの)取得


まず、図形を描画出来るようにしました。

        private void Form1_Load(object sender, EventArgs e)
        {
            // 現在選択されているワークシートを取得します
            var worksheet = reoGridControl1.CurrentWorksheet;


            var rectObj = new unvell.ReoGrid.Drawing.Shapes.RectangleShape();
            rectObj.X = 0; 
            rectObj.Y = 0;
            rectObj.Width = 100;
            rectObj.Height = 100;
            rectObj.Style.LineWidth = 2;
            rectObj.Style.FillColor = SolidColor.Transparent;
            rectObj.Style.LineColor =SolidColor.Red;

            // ワークシートに四角形を追加します
            worksheet.FloatingObjects.Add(rectObj);

        }

上記のように実施しても、移動できる四角形ではないようです。
図形移動や拡縮など、自分で組まないといけないのでしょうか…?

また、ReoGridでの図形その他の書き方について
どのように調べたら見つけられますか?
ReoGrid Rect などで調べてもそこまで見つけられず
ソースを途中まで打って出てくるヒントを元に試している状態です。

unvell.ReoGrid.dll 3.0.0 を利用しています。


Winform .net 6.0
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/7 12:07:29
機能としては、Issues #337 で enhancement ラベルが付けられていますね。
Closed ではないので、実装はされていないかも。
https://github.com/unvell/ReoGrid/issues/337

ただしマージはされていないものの、一応、プルリク #339 の実装があるようです。
こちらを参考にしてみてください。
https://github.com/unvell/ReoGrid/pull/339
https://github.com/unvell/ReoGrid/pull/339/commits/62f9efa814046f8945a0349d7d98a6370ba93156

浮動オブジェクトでは無くセルオブジェクトの場合は、
Drawings\DrawingObjectStyleDemo.cs から呼ばれている
CustomCell\SlideCellDemo.cs 内の
Demo.CellTypeDemo.SlideCell クラスのような実装パターンもありますね。
投稿者 (削除されました)  () 投稿日時 2023/9/7 12:59:13
(削除されました)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/7 13:03:03
> Drawings\DrawingObjectStyleDemo.cs から呼ばれている

上記は DemoJp サンプルのことです。

ただし https://github.com/unvell/ReoGrid にある日本語デモソースではなく、
https://reogrid.net/jp/download/ の日本語デモソース (2.1.0) を見ただけなので、
現行バージョン (3.1.0) とは振る舞いが違うかもしれません。多分ほぼ同じと思いますが。

なお、v2 系と v3 系の差異はここに書かれています。
https://github.com/unvell/ReoGrid/releases/tag/v3.0.0


> また、ReoGridでの図形その他の書き方について
> どのように調べたら見つけられますか?
サンプル以外だと、ドキュメントにあるのはこのぐらいですね。
https://reogrid.net/jp/document/floating-image/
https://reogrid.net/document/floating-objects/
投稿者 えんぴー  (社会人) 投稿日時 2023/9/8 14:10:21
魔界の仮面弁士様

回答ありがとうございます。返事が遅れて申し訳ありません。
色々と情報ありがとうございます!助かります。
なぜかDemoJp サンプル動かせないんですよね……。

セル内オブジェクトにしてしまうと今後が困るため
浮動オブジェクトにしようと思うのですが難しいですね、困りました。

Excelのオートシェイプのようなものを利用したいと思っています。
良い手段はありませんでしょうか。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/8 15:34:46
シート操作自体は不要で、オートシェイプっぽい操作ができれば良いのでしょうか。
それとも、オートシェイプ入りの Excel ファイルの編集が必要な状況なのでしょうか。

前者の場合、描いたり編集したりするだけならば、InkEdit コントロールなどの選択肢があります。
シートなどに重ねて描画する目的には使えません。

後者の場合、ReoGrid 以外のソリューション、たとえば SpreadSheetGear などでも、
シェイプの座標処理が難しいと言われているので、何か技術的な制限があるのかも。
https://www.xlsoft.com/jp/products/spreadsheetgear/faq-japan.html#4-1


ReoGrid で実装するなら、GitHub からリポジトリをクローンして、
該当機能を作りこむしか無いと思います。

現状だと、たとえば超手抜き実装でこんな感じにしてみても、
操作できるのは一部のメンバーに限られます

// 手抜きでシェイプそのものをバインド。実際はラッパークラスを設けた方が良い
this.listBox1.DataSource = this.bindingSource1;
this.bindingSource1.DataSource = worksheet.FloatingObjects;

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
  // 編集画面を作りこむのが面倒なので、PropertyGrid に渡すだけの手抜き処理
    this.propertyGrid1.SelectedObject = listBox1.SelectedItem;
}

private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
  // シェイプが変更通知イベントを有していないので、手動で再描画を依頼する
    this.reoGridControl1.Invalidate();
}



・Style プロパティや Location プロパティなどの階層構造のメンバーを操作できない
 → これは Point 構造体などに EditorAttribute がないためであり、
   コードから差し替えることはできる。
   (PropertyGrid に対応させるなら、自前で中継クラスにラッピングする)

・シェイプが変更通知イベントを有していないので、シェイプ座標を書き換えても
 グリッド側が即座に変更できない(マウスやペンがホバーすれば反応する)
  → 自前で Invalidate を呼び出すか、ソースを弄って変更通知イベントを自分で追加する

・シェイプをクリックで選択したり、重なったシェイプのレイヤーを入れ替えたり、
 ドラッグで移動させるといった機能が不足している
 → rectObj.IsSelected = true; にしてやれば、ドラッグ可能な見た目のハンドルを
  シェイプに追加することができますが、それはあくまで見た目だけの話。
 → マウス操作を捉える場合、描画オブジェクトそのものだけでなく、
  グリッド側のカスタマイズも必要になってくるので、
  元ソースに手を入れる必要がありそう


> Excelのオートシェイプのようなものを利用したいと思っています。
有償で構わなければ、 SpreadsheetGear はどうでしょう。
私は使ったことが無いので確証は持てませんが、
どうやらシェイプの追加や選択もできそうにみえます。
https://github.com/SpreadsheetGear/SpreadsheetGearExplorerSamples


VB6 なら、OLE コンテナ コントロールを使う手もあるのですけれどね…。(Excel 本体が必要)

Private Sub Command1_Click()
    Dim wb As Object
    Set wb = Me.OLE1.object
    Dim shp As Object
    Set shp = wb.Worksheets("Sheet1").Shapes.AddShape(1, 20, 10, 60, 40)
    shp.Fill.Visible = False
    shp.Line.ForeColor.RGB = RGB(255, 0, 0)
End Sub
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/8 15:52:36
>  rectObj.IsSelected = true; にしてやれば、ドラッグ可能な見た目のハンドルを
> シェイプに追加することができますが、それはあくまで見た目だけの話。

あれ。IsSelected = false に戻せないな…と思ってソースを見たら、
false から true にはできるのに、true から false に戻せるようになっていない。
多分バグですね(汗)
https://github.com/unvell/ReoGrid/blob/master/ReoGrid/Drawing/DrawingObjects.cs#L325


> if (this.isSelected != value)
> {
>  this.isSelected = true;
ここ、「this.isSelected = value;」の書き間違いじゃないかなぁ。
どっちにしても、 NuGet から得たライブラリをそのまま使うのではなく、
GitHub からクローンして手なおしした方が融通が利きそう。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/11 21:30:11
> IsSelected = false に戻せないな…と思ってソースを見たら、
> false から true にはできるのに、true から false に戻せるようになっていない。
> 多分バグですね(汗)
上記修正のプルリクがマージされました。最新ソースを pull すれば修正されます。
https://github.com/unvell/ReoGrid/pull/506

IsSelected プロパティが修正されたので、描画系はこれで何とかなるかも…?
ドラッグ移動などに拘らなければ、FloatingObjects プロパティ経由で列挙したり、
プロパティ変更などの機能を作りこむことはできそうな予感。
(マウス操作に対応させようとすると、修正対象のクラスが増えるので、先の PR#339 規模の修正になりそうですが)