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

水平スクロールバーの非表示

環境/言語:[Windows XP C# VisualStudio2010]
分類:[.NET]

ユーザーコントロールで
ラベルがドラッグアンドドロップで移動可能
というプログラムを作っています。
そこで、AutoScrollがTrueになっており、
スクロールバーが自動的に表示されるようになっています。

そこで質問なのですが
水平(横)スクロールバーを表示したくありません。
ラベルを画面サイズより右にドラッグアンドドロップをすると
スクロールバーが表示されてしまいます。
画面サイズより右にドラッグアンドドロップされたときは
画面サイズのぎりぎりに配置したいです。
水平(横)スクロールバーを表示しないためにはどうしたらいいでしょうか?
■No29955に返信(麻緒さんの記事)

ドラッグ(ドロップ)操作後のラベルの位置は自分で設定されているのでしょうか?
だとしたらスクロールバーが表示される位置にならないよう条件判定
すると良いと思います。(ラベルの左位置+幅がコントロールの右端からはみ出ないようにする)
■No29958に返信(shuさんの記事)
ありがとうございます。
> ドラッグ(ドロップ)操作後のラベルの位置は自分で設定されているのでしょうか?
> だとしたらスクロールバーが表示される位置にならないよう条件判定
> すると良いと思います。(ラベルの左位置+幅がコントロールの右端からはみ出ないようにする)

if((this.label.Location.X + this.label.Width) >= this.Width)
{
 this.label.Location = new Point(this.Width - this.label.Width, this.label.Location.Y)
}
とこんな感じでやってみました。
取得してみると、this.labelは画面の右ぎりぎりに表示されるように設定されています。
ですが、スクロールバーは表示され、スクロールされた一番右に配置されてしまいます。
上記のコーディングでは間違っているのでしょうか?
■No29959に返信(麻緒さんの記事)
> if((this.label.Location.X + this.label.Width) >= this.Width)
> {
>  this.label.Location = new Point(this.Width - this.label.Width, this.label.Location.Y)
> }
> とこんな感じでやってみました。
それをどこに記述されていますか?

ドラッグ & ドロップ操作の部分について、現在のコードがどうなっているか、
第三者が検証可能なソースコードを提示できないでしょうか。

> スクロールバーは表示され、スクロールされた一番右に配置されてしまいます。
具体的には、どの座標までならスクロールバーは表示されませんでしたか?

水平スクロールバーなしに配置できる右端の位置は、
垂直スクロールバーが表示されているかどうかで変化します。

すなわち、垂直スクロールバーが表示されている間は、
その幅(SystemInformation.VerticalScrollBarWidth)の分だけ、
配置可能領域が狭くなるという事になります。


もし、それぞれのスクロールバーの表示状態の変化によって
利用可能領域が変わってしまうことが煩わしいのであれば、
  HorizontalScroll.Visible = false;
  VerticalScroll.Visible = true;
  VerticalScroll.Enabled = (false または false)
のようにする手もありますが……この場合は AutoScroll プロパティを
false にしておく必要があるので、今回は使えないですね。
■No29959に返信(麻緒さんの記事)

this.Widthではなくthis.ClientRectangle.Rightにしてみてはどうでしょう?
this.Widthはフォームの境界部分も含んだ幅になってしまいます。
■No29960に返信(魔界の仮面弁士さんの記事)
ありがとうございます。
> それをどこに記述されていますか?
ドラッグアンドドロップが終わった場所です。
→MouseUp関数内で呼ばれた関数の中です。

> ドラッグ & ドロップ操作の部分について、現在のコードがどうなっているか、
> 第三者が検証可能なソースコードを提示できないでしょうか。
すみません、どこからどこまでが提示できるか判断できません・・・

> 具体的には、どの座標までならスクロールバーは表示されませんでしたか?
ラベルの右端が画面の右端と重なった場所までは表示されませんでした。
→label.Widthとthis.Widthが同じ?
■No29961に返信(shuさんの記事)
ありがとうございます。
> this.Widthではなくthis.ClientRectangle.Rightにしてみてはどうでしょう?
this.ClientRectangle.Rightでも同様にスクロールバーが表示されてしまいました。
■No29962に返信(麻緒さんの記事)

スクロールバーが表示されないときの処理はこの条件の前に
あるのでしょうか?移動前の座標でチェックしているとしたら
意味がないです。

移動想定位置を一旦変数にいれて変数を用いてチェックしてX座標を調整してから
新しい位置を設定した方が良いと思います。
■No29964に返信(shuさんの記事)
返信ありがとうございます。
> スクロールバーが表示されないときの処理はこの条件の前に
> あるのでしょうか?移動前の座標でチェックしているとしたら
> 意味がないです。
移動後の座標でチェックしています。

> 移動想定位置を一旦変数にいれて変数を用いてチェックしてX座標を調整してから
> 新しい位置を設定した方が良いと思います。
int xd = 移動予定位置X
if((xd + this.label.Width) >= this.Width)
{
 this.label.Location = new Point(this.Width - this.label.Width, this.label.Location.Y)
}
こういうことでしょうか?




例えばですが、
AutoScrollをFalseにして、
VScrollBarを使用して仕様を満たすことはできないでしょうか?
■No29965に返信(麻緒さんの記事)

> int xd = 移動予定位置X
> if((xd + this.label.Width) >= this.Width)
> {
>  this.label.Location = new Point(this.Width - this.label.Width, this.label.Location.Y)
> }

int xd = 移動予定位置X;
int yd = 移動予定位置Y;
if((xd + this.label.Width) > this.ClientRectangle.Right)
{
 xd = this.ClientRectangle.Right - this.label.Width;
}
this.label.Location = new Point(xd, yd);

のような感じです。
■No29966に返信(shuさんの記事)
ありがとうございます。
> int xd = 移動予定位置X;
> int yd = 移動予定位置Y;
> if((xd + this.label.Width) > this.ClientRectangle.Right)
> {
>  xd = this.ClientRectangle.Right - this.label.Width;
> }
> this.label.Location = new Point(xd, yd);
やってみましたが、やはりだめでした。
■No29967に返信(麻緒さんの記事)

全然だめですか?
(1)横だけはみ出るように動かす
(2)縦だけはみ出るように動かす
(3)縦横双方にはみ出るように動かす

(a)移動前に縦スクロールバーが表示されていない
(b)移動前に縦スクロールバーが表示されている

というパターンがあると思いますがどうでしょう?
(3)+(a)以外でも駄目でしょうか?
(3)+(a)のみならthis.VerticalScroll.VisibleとSystemInformation.VerticalScrollBarWidth(魔界の仮面弁士 さん提示済み)を
考慮すると良いと思います。

もう少しソースを提示されないと状況が明確に分かりません。
■No29969に返信(shuさんの記事)
返信ありがとうございます。
いろいろやってはみたのですが、
> (1)横だけはみ出るように動かす
> (2)縦だけはみ出るように動かす
> (3)縦横双方にはみ出るように動かす
>
> (a)移動前に縦スクロールバーが表示されていない
> (b)移動前に縦スクロールバーが表示されている

どのパターンもだめでした。

> もう少しソースを提示されないと状況が明確に分かりません。
どういうところを提示できればいいでしょうか?
2012/02/28(Tue) 13:59:06 編集(投稿者)

スクロールバーが表示された時って、
見た目の大きさは変わらないけど
実際には大きくなっていると思うのですが、
その実際の大きさは取得できないのでしょうか?

http://d.hatena.ne.jp/onozaty/20060803/p1
コントロールでこういうことってできないですか?
2012/02/29(Wed) 08:24:34 編集(投稿者)

■No29970に返信(麻緒さんの記事)

> どういうところを提示できればいいでしょうか?

例えばvb.netソースですが、以下のような感じ。最低限動きが読める程度
UserControl1:
  Label1 as Labelが貼り付けてある(プロパティはすべて初期値)

    Public Sub MoveLabel(x As Integer, y As Integer)
        If Not Me.VerticalScroll.Visible AndAlso y + Label1.Height > Me.ClientRectangle.Height Then
            If x + Label1.Width > Me.ClientRectangle.Right - SystemInformation.VerticalScrollBarWidth Then
                x = Me.ClientRectangle.Right - SystemInformation.VerticalScrollBarWidth - Label1.Width
            End If
        Else
            If x + Label1.Width > Me.ClientRectangle.Right Then
                x = Me.ClientRectangle.Right - Label1.Width
            End If
        End If
        Label1.Location = New Point(x, y)
    End Sub


Form1:
UserControl11 as UserControl1(サイズを適当に調整)
Button1〜4 as Buttonが貼り付けてある。

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        UserControl11.MoveLabel(0, 0)
    End Sub

    Private Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click
        UserControl11.MoveLabel(UserControl11.Width + 20, 0)
    End Sub

    Private Sub Button3_Click(sender As Object, e As System.EventArgs) Handles Button3.Click
        UserControl11.MoveLabel(0, UserControl11.Height + 20)
    End Sub

    Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
        UserControl11.MoveLabel(UserControl11.Width + 20, UserControl11.Height + 20)
    End Sub
■No29979に返信(shuさんの記事)
ラベルはドロップしたときに他のラベルと重ならないようにしています。
何かわからないところや、追加してほしい場所がありましたら
出来る範囲で提示します。

Form1:
UserControlが貼り付けてあるだけ

UserControl:
MouseUp関数から呼ばれたTryMove関数
icon = 移動ラベル
x = 移動予定位置X
y = 移動予定位置Y
_icons = 配置されているラベル全てをUserControl配列で持っている

private bool TryMove(ユーザーコントロール icon, int x, int y)
{
 bool success = false;
 bool flg = false;

 int xd = x;
 int yd = y;

 // 横にラベルがいくつ並ぶか
 int cellX = x / icon.Width;
 // 縦にラベルがいくつ並ぶか
 int cellY = y / icon.Height;

 lock (_icons)
 {
  if((x + icon.Width) > this.ClientRectangle.Right)
  {
   xd = this.ClientRectangle.Right - icon.Width;
  }
  if (this.cell.Count > cellY && this.cell[cellY].Length > cellX)
  {
   flg = 空き地だったらtrue ラベルがあったらfalse;
  }
  if (!flg)
  {
   success = true;
   // ラベル移動予定位置が画面横からはみ出す場合
   if (xd + icon.Width > this.Width)
   {
    xd = icon.Width * (cellX - 1);
   }
  }
  else
  {
   // 空き地を探す順番を設定
   List<___> offsets = ___()

   foreach (var offset in offsets)
   {
    if (offset位置にラベルがある)
    {
     continue;
    }
    if (offset位置が画面外)
    {
     continue;
    }
    else
    {
     // ラベル移動予定位置が画面横からはみ出す場合
     if (offset.X + icon.Width > this.Width)
     {
      continue;
     }

     if (ラベルがおける)
     {
      xd = offset.X;
      yd = offset.Y;
      success = true;
      break;
     }
    }
   }
  }
 }

 if (success)
 {
  icon.Left = xd;
  icon.Top = yd;
 }
 return success;
}
■No29980に返信(麻緒さんの記事)

ぱっと見、 this.Widthがまだいくつかありますね。
多分、このソース内にあるthis.Widthはすべてthis.ClientRectangle.Rightに
した方が良いと思われます。後は再度書きますが、this.VerticalScroll.VisibleとSystemInformation.VerticalScrollBarWidth(魔界の仮面弁士 さん提示済み)を
組み込むと良いと思います。(前レスにサンプル記述済み)
■No29981に返信(shuさんの記事)
ありがとうございます。
> ぱっと見、 this.Widthがまだいくつかありますね。
> 多分、このソース内にあるthis.Widthはすべてthis.ClientRectangle.Rightに
> した方が良いと思われます。後は再度書きますが、this.VerticalScroll.VisibleとSystemInformation.VerticalScrollBarWidth(魔界の仮面弁士 さん提示済み)を
> 組み込むと良いと思います。(前レスにサンプル記述済み)
やってみましたが変わりませんでした。

いろいろ自分でもいじってみたら
if (this.AutoScrollPosition.X < 0)
{
 this.AutoScrollPosition = new Point(0, this.AutoScrollPosition.Y);
}
とすることで、右にはみ出したときは右ぎりぎりに配置することが出来ました。
ですが、これでいいのでしょうか・・・
また、ドラッグしている間はスクロールバーが表示されてしまうので
あまり納得いってません・・・
■No29982に返信(麻緒さんの記事)

> また、ドラッグしている間はスクロールバーが表示されてしまうので
> あまり納得いってません・・・
ドラッグしている間の配置はどのように行っているのでしょうか?これも
同様の処理をしないといけないはずです。その他横スクロールバーが表示されてしまう操作があれば未然に処理をしないと駄目です。
■No29984に返信(shuさんの記事)
返信ありがとうございます。
> ドラッグしている間の配置はどのように行っているのでしょうか?これも
> 同様の処理をしないといけないはずです。その他横スクロールバーが表示されてしまう操作があれば未然に処理をしないと駄目です。

ドラッグしている間は下記のようになっています。
同様の処理というのは
if (this.AutoScrollPosition.X < 0)
{
 this.AutoScrollPosition = new Point(0, this.AutoScrollPosition.Y);
}
でしょうか?

/// <summary>
/// ドラッグ開始
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label_MouseDown(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
_previousPos.X = this.Left;
_previousPos.Y = this.Top;
_mousePos.X = e.X;
_mousePos.Y = e.Y;
this.BringToFront();
}
}

/// <summary>
/// ドラッグ中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
this.OnMouseDown(e);

this.Left += e.X - _mousePos.X;
this.Top += e.Y - _mousePos.Y;
}
}
■No29986に返信(麻緒さんの記事)

>                 this.Left += e.X - _mousePos.X;
>                 this.Top += e.Y - _mousePos.Y;
同様の処理というのはこの部分について
  ClientRectangle.Right(-VerticalScrollBarWidth)
より右に配置しないようにするということです。
■No29988に返信(shuさんの記事)
返信ありがとうございます。
> ClientRectangle.Right(-VerticalScrollBarWidth)
> より右に配置しないようにするということです。
int x = e.X - _mousePos.X;
if((x + this.Width) > this.Panel.ClientRectangle.Right)
{
x = this.ClientRectangle.Right - this.Width;
}

this.Left += x;
this.Top += e.Y - _mousePos.Y;
このようにやりましたがスクロールバーは表示されてしまいました。
■No29989に返信(麻緒さんの記事)
> int x = e.X - _mousePos.X;
int x = this.Left + e.X - _mousePos.X;


> this.Left += x;
this.Left = x;


ではどうですか?
■No29990に返信(shuさんの記事)
返信ありがとうございます。
> int x = this.Left + e.X - _mousePos.X;
> this.Left = x;
これで出来ました!!
本当にありがとうございました!
解決済み!

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