質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

2回答

2336閲覧

Winform AutoScrollを表示していると、思った位置にLabelを置けない

nya-3

総合スコア27

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

1グッド

2クリップ

投稿2022/04/06 02:33

実現したいこと

表のようなものを作成し、
SplitContenerの左側に項目名、右側にクリックでバーなどを追加できるものを
作ろうとしています。
DataGirdの見た目は少々気に入らないけれど、他に良い方法が思いつきませんでした。
Labelで罫線を作成し、スクロールバーを連動させて動かせば
自分が欲しいものを作れるかと思ってます。
Labelで作ったグリッドにあわせてスナップする機能も付けたいなと思ってますし、
やりたい事はたくさんあります。

いま出来なくて困っている事

動的生成したラベルをLabelListの配列に入れています。
splitContainerをクリックした時にピンク色のラベルを自動生成しています。
それにハマるようにHeightを合わせたりしているのですが、
クリックを数回していると、ラベルの位置がズレます。

Console.WriteLineは、50で割り切れる正しそうな数値がでるのですが、
なぜかラベルの描画が罫線にぴったりでなくズレます。
xやyなどの座標は、intで宣言しています。

splitContainer1にはスクロールバーが表示されており、
そのせいかもしれないと気づきました。
splitContainerにはAutoScrollをTrueにしているため、
Locationの値が見ている範囲だけという判断になっている可能性
はあります。

でも、どのように対応したらいいのかが思いつきません。
最終的にはSplitContainerの左側と連動してスクロールさせたりしたいとも思っています。

発生している問題・エラーメッセージ

イメージ説明
不要な部分は白塗りしました。
少しだけスクロールしてからクリックしたら、位置が罫線からズレました。

やりたい事

見えている位置のクリック座標ではなく、
SplitContainerの左上を基準としたクリック座標が知りたい

該当のソースコード

C#

1 List<Label> LabelList = new List<Label>(); 2 private void createCustomLabel(string MyText,int x,int y , int width ,int height) 3 { 4 Label MyLabel = new Label(); 5 LabelList.Add(MyLabel); 6 MyLabel.BackColor = System.Drawing.Color.MistyRose; 7 MyLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 8 MyLabel.Location = new System.Drawing.Point(x, y); 9 MyLabel.Name = "myLabel"; 10 MyLabel.Size = new System.Drawing.Size(width,height); 11 MyLabel.TabIndex = 0; 12 MyLabel.Text = MyText; 13 MyLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 14 splitContainer1.Panel2.Controls.Add(MyLabel); 15 } 16 17 private void splitContainer1_Panel2_MouseDown(object sender, MouseEventArgs e) 18 { 19 before_x = e.X; 20 int a = e.Y / 50; 21 a = a * 50; 22 now_y = a; 23 createCustomLabel("テスト", before_x, now_y, 60, 50); 24 view = true; 25 }

試したこと

スクロールバーを動かす範囲を50ずつ変更するということが出来れば
対応可能かもしれないと思いましたが、現在調査中です。
AutoScrollPositionでも監視は出来なさそうです…。

補足情報(FW/ツールのバージョンなど)

.NET Framework 4.7.2

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2022/04/06 03:29

スクロールの移動量は splitContainer1.Panel2.VerticalScroll splitContainer1.Panel2.HorizontalScroll で調整できます。 スクロールのイベントは splitContainer1.Panel2.Scroll イベントで拾えます。
nya-3

2022/04/06 04:45

ありがとうございます! private void splitContainer1_Panel2_Scroll(object sender, ScrollEventArgs e) { int newData = (e.NewValue / 50) * 50; if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) { splitContainer1.Panel2.VerticalScroll.Value = newData; } if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll) { splitContainer1.Panel2.HorizontalScroll.Value = newData; } Console.WriteLine(newData.ToString()); } 上記のようにしてみましたが、水平側のスクロールの右ボタンを押しても移動できないです。 バーをつかんで移動させれば移動できない事も無いですが…
guest

回答2

0

ベストアンサー

やってみてわかりましたが、AutoScroll関連めちゃくちゃ癖が強いですね^^;
気を利かせてるんでしょうけど、完全に余計なお世話ですね...

見えている位置のクリック座標ではなく、

よくよく考えればe.Xが、そのまま使えてしまっているほうがおかしいです。
見えている位置と実際の位置が違っていても、X座標はクリックされた位置になっているように見えます。
つまり何か補正が自動的にかかっています。

SplitContainerの左上を基準としたクリック座標が知りたい

splitContainer1.Panel2.AutoScrollPositionを足せば実座標になりますが、余計なお世話のおかげでそのままではうまくいきません!
ScrollableControl.AutoScrollPosition プロパティ (System.Windows.Forms) | Microsoft Docs

うまく文章で説明できないので、実行して確認してください^^;

cs

1using System.Drawing; 2using System.Windows.Forms; 3 4namespace Qoa0qgwebrssgdm 5{ 6 public partial class Form1 : Form 7 { 8 private readonly SplitContainer splitContainer1; 9 10 public Form1() 11 { 12 InitializeComponent(); 13 14 splitContainer1 = new SplitContainer { Dock = DockStyle.Fill, }; 15 splitContainer1.Panel2.AutoScroll = true; 16 splitContainer1.Panel2.MouseDown += SplitContainer1_Panel2_MouseDown; 17 Controls.Add(splitContainer1); 18 } 19 20 //private void SplitContainer1_Panel2_MouseDown(object sender, MouseEventArgs e) 21 //{ 22 // // スクロール分を足す(AutoScrollPositionがマイナスで来るので引く) 23 // var p = new Point(e.X, e.Y) - (Size)splitContainer1.Panel2.AutoScrollPosition; 24 // // 同じ意味 25 // //var p = new Point(e.X - splitContainer1.Panel2.AutoScrollPosition.X, e.Y - splitContainer1.Panel2.AutoScrollPosition.Y); 26 27 // var y = p.Y / 50 * 50; 28 29 // var label = new Label 30 // { 31 // BackColor = Color.MistyRose, 32 // BorderStyle = BorderStyle.FixedSingle, 33 // Location = new Point(p.X, y), 34 // Size = new Size(60, 50), 35 // Text = "テスト", 36 // TextAlign = ContentAlignment.MiddleCenter, 37 // }; 38 39 // // スクロールしているときにAddするとずれる 40 // // 普通にe.X,e.Yで追加できるように気を利かせてるんだと思うが、余計なお世話だなぁw 41 // var t = splitContainer1.Panel2.AutoScrollPosition; 42 // // 一旦スクロールを0に 43 // splitContainer1.Panel2.AutoScrollPosition = new Point(0, 0); 44 // splitContainer1.Panel2.Controls.Add(label); 45 // // スクロールを戻す(セットするときは正の数 これも意味が分からん仕様) 46 // splitContainer1.Panel2.AutoScrollPosition = new Point(-t.X, -t.Y); 47 //} 48 49 // 単純やると↑になってしまったが、気持ち悪すぎるのでこっちがいいかな? 50 private void SplitContainer1_Panel2_MouseDown(object sender, MouseEventArgs e) 51 { 52 var offset = splitContainer1.Panel2.AutoScrollPosition; 53 54 // スナップの計算にだけスクロール量を考慮しまた戻す 55 var y = (e.Y - offset.Y) / 50 * 50 + offset.Y; 56 57 var label = new Label 58 { 59 BackColor = Color.MistyRose, 60 BorderStyle = BorderStyle.FixedSingle, 61 Location = new Point(e.X, y), 62 Size = new Size(60, 50), 63 Text = "テスト", 64 TextAlign = ContentAlignment.MiddleCenter, 65 }; 66 67 splitContainer1.Panel2.Controls.Add(label); 68 } 69 } 70}

投稿2022/04/06 09:53

編集2023/07/30 05:43
TN8001

総合スコア10022

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nya-3

2022/04/07 00:06

TN8001様 回答ありがとうございました! 無事、自分のやりたいような動作になりました! スクロール量を元の値にプラスすることで綺麗に合うようになるとは気づきませんでした。 Y軸のスナップが出来、同じ方法を利用させて頂き、X軸もスナップできるようになりました! ありがとうございましたorz
guest

0

splitContainer1.Panel2.VerticalScroll.SmallChange = 50; splitContainer1.Panel2.VerticalScroll.LargeChange = 50; splitContainer1.Panel2.HorizontalScroll.SmallChange = 50; splitContainer1.Panel2.HorizontalScroll.LargeChange = 50; private void splitContainer1_Panel2_Scroll(object sender, ScrollEventArgs e) { int newData = (e.NewValue / 50) * 50; if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) { splitContainer1.Panel2.VerticalScroll.Value = newData; } if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll) { splitContainer1.Panel2.HorizontalScroll.Value = newData; } Console.WriteLine(newData.ToString()); }

これで、50ずつ移動することが出来るようになりました。

ただし、ScrollBerを右や下の端まで移動すると、ズレることがあります。

一番やりたかったことは、グリッド表示したものにスナップすることですが、
これは調べても情報が見つからないため難しいのかもしれません。

16:33 追記
UserForm1
→TabPage(Anchor Top,Left) Dock None Location Y=50  ItemSizeは200,30
→SplitContaine1 Anchor Top,Left Dock Fill SplitterDistance 180
Panel2(右側) AutoScroll True

どうやら、SplitContainer1のPanel2、このAutoScroll内のサイズ?が
50で割り切れるサイズになっていないために動作がおかしい様子。
ホイールでスクロールした場合と、バーを持ってスクロールさせた場合に許容できない動作になります。
でも、どのように対応すれば良いのか分からず断念するかもしれないです。
何かアドバイスがあればください。

投稿2022/04/06 04:50

編集2022/04/06 07:48
nya-3

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問