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

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

ただいまの
回答率

90.50%

  • C#

    7121questions

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

コントロールの縦横比を固定して拡大・縮小する

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 245

k1500

score 4

下記サイト様のコードを参考にpictureBoxをD&Dで縦横比を固定したまま拡大・縮小できるクラスを考えておりますが、うまくいきません。
(https://anis774.net/codevault/danddsizechanger.html)

縦の変化量を常に横の4/3倍としているように書き換えたのですが希望する動きになっていない状態です。

問題点をご指摘頂けると助かります。
宜しくお願いします。

```C#
uclass DAndDSizeChanger
{
Control mouseListner;
Control sizeChangeCtrl;
DAndDArea sizeChangeArea;
Size lastMouseDownSize;
Point lastMouseDownPoint;
DAndDArea status;
int sizeChangeAreaWidth;
Cursor defaultCursor;

const double fixedRate = (double)4 / 3;

/// <param name="mouseListner">マウス入力を受け取るコントロール</param>
/// <param name="sizeChangeCtrl">マウス入力によってサイズが変更されるコントロール</param>
/// <param name="sizeChangeArea">上下左右のサイズ変更が有効になる範囲を指定</param>
/// <param name="sizeChangeAreaWidth">サイズ変更が有効になる範囲の幅を指定</param>
public DAndDSizeChanger(Control mouseListner, Control sizeChangeCtrl, DAndDArea sizeChangeArea, int sizeChangeAreaWidth)
{
this.mouseListner = mouseListner;
this.sizeChangeCtrl = sizeChangeCtrl;
this.sizeChangeAreaWidth = sizeChangeAreaWidth;
this.sizeChangeArea = sizeChangeArea;
defaultCursor = mouseListner.Cursor;

mouseListner.MouseDown += new MouseEventHandler(mouseListner_MouseDown);
mouseListner.MouseMove += new MouseEventHandler(mouseListner_MouseMove);
mouseListner.MouseUp += new MouseEventHandler(mouseListner_MouseUp);
}

void mouseListner_MouseDown(object sender, MouseEventArgs e)
{
lastMouseDownPoint = e.Location;
lastMouseDownSize = sizeChangeCtrl.Size;

//動作を決定
status = DAndDArea.None;
if (getTop().Contains(e.Location))
{
status |= DAndDArea.Top;
}
if (getLeft().Contains(e.Location))
{
status |= DAndDArea.Left;
}
if (getBottom().Contains(e.Location))
{
status |= DAndDArea.Bottom;
}
if (getRight().Contains(e.Location))
{
status |= DAndDArea.Right;
}

if (status != DAndDArea.None)
{
mouseListner.Capture = true;
}
}

void mouseListner_MouseMove(object sender, MouseEventArgs e)
{
//カーソルを変更
if ((getTop().Contains(e.Location) &&
getLeft().Contains(e.Location)) ||
(getBottom().Contains(e.Location) &&
getRight().Contains(e.Location)))
{

mouseListner.Cursor = Cursors.SizeNWSE;
}
else if ((getTop().Contains(e.Location) &&
getRight().Contains(e.Location)) ||
(getBottom().Contains(e.Location) &&
getLeft().Contains(e.Location)))
{
mouseListner.Cursor = Cursors.SizeNESW;
}

else
{
mouseListner.Cursor = defaultCursor;
}

if (e.Button == MouseButtons.Left)
{
int diffX = e.X - lastMouseDownPoint.X;
int diffY = e.Y - lastMouseDownPoint.Y;

if ((status & DAndDArea.Left) == DAndDArea.Left && (status & DAndDArea.Top) == DAndDArea.Top)//左上
{

int w = sizeChangeCtrl.Width;
sizeChangeCtrl.Width -= diffX;
sizeChangeCtrl.Left += w - sizeChangeCtrl.Width;

int h = sizeChangeCtrl.Height;
sizeChangeCtrl.Height -= diffY;
//sizeChangeCtrl.Top += (int)(fixedRate * (h - sizeChangeCtrl.Height) + 0.5);
sizeChangeCtrl.Top += h - sizeChangeCtrl.Height;
}
if ((status & DAndDArea.Right) == DAndDArea.Right && (status & DAndDArea.Top) == DAndDArea.Top)//右上サイド
{

sizeChangeCtrl.Width = lastMouseDownSize.Width + diffX;

int h = sizeChangeCtrl.Height;
sizeChangeCtrl.Height -= diffY;
//sizeChangeCtrl.Top += (int)(fixedRate * (h - sizeChangeCtrl.Height) + 0.5);
sizeChangeCtrl.Top += h - sizeChangeCtrl.Height;
}

if ((status & DAndDArea.Left) == DAndDArea.Left && (status & DAndDArea.Bottom) == DAndDArea.Bottom)//左下
{

int w = sizeChangeCtrl.Width;
sizeChangeCtrl.Width -= diffX;
sizeChangeCtrl.Left += w - sizeChangeCtrl.Width;

//sizeChangeCtrl.Height = (int)(fixedRate * (lastMouseDownSize.Height + diffY) + 0.5);
sizeChangeCtrl.Height = lastMouseDownSize.Height + diffY;
}
if ((status & DAndDArea.Right) == DAndDArea.Right && (status & DAndDArea.Bottom) == DAndDArea.Bottom) //右下
{

sizeChangeCtrl.Width = lastMouseDownSize.Width + diffX;
//sizeChangeCtrl.Height = (int)(fixedRate * (lastMouseDownSize.Height + diffY) + 0.5);
sizeChangeCtrl.Height = lastMouseDownSize.Height + diffY;
}

}
}

void mouseListner_MouseUp(object sender, MouseEventArgs e)
{
mouseListner.Capture = false;
}

/// <summary>
/// ポイントがD&Dするとサイズが変更されるエリア内にあるかどうかを判定します。
/// </summary>
public bool ContainsSizeChangeArea(Point p)
{
return getTop().Contains(p) ||
getBottom().Contains(p) ||
getLeft().Contains(p) ||
getRight().Contains(p);
}

private Rectangle getTop()
{
if ((sizeChangeArea & DAndDArea.Top) == DAndDArea.Top)
{
return new Rectangle(0, 0, mouseListner.Width, sizeChangeAreaWidth);
}
else
{
return new Rectangle();
}
}

private Rectangle getBottom()
{
if ((sizeChangeArea & DAndDArea.Bottom) == DAndDArea.Bottom)
{
return new Rectangle(0, mouseListner.Height - sizeChangeAreaWidth,
mouseListner.Width, sizeChangeAreaWidth);
}
else
{
return new Rectangle();
}
}

private Rectangle getLeft()
{
if ((sizeChangeArea & DAndDArea.Left) == DAndDArea.Left)
{
return new Rectangle(0, 0,
sizeChangeAreaWidth, mouseListner.Height);
}
else
{
return new Rectangle();
}
}

private Rectangle getRight()
{
if ((sizeChangeArea & DAndDArea.Right) == DAndDArea.Right)
{
return new Rectangle(mouseListner.Width - sizeChangeAreaWidth, 0,
sizeChangeAreaWidth, mouseListner.Height);
}
else
{
return new Rectangle();
}
}
}

public enum DAndDArea
{
None = 0,
Top = 1,
Bottom = 2,
Left = 4,
Right = 8,
All = 15

}
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • g_uo

    2018/06/19 10:47

    [お願い] 質問の際クラス内部だけでなく、このクラスを呼び出しているコードも記載してくださいますようお願いします。回答者が動作を確認する際に役立つうえ、より多くの回答を得ることができると思います。

    キャンセル

  • k1500

    2018/06/19 10:49

    わかりました。

    キャンセル

回答 1

checkベストアンサー

0

こんにちは。

ドラッグ後のコントロールの幅または高さをもとに、他方の長さを計算すれば比率は維持されます。
次のソースでは、ドラッグ後の幅(sizeChangeCtrl.Width)に対して高さ、およびTopを計算して反映させています。

修正対象個所はvoid mouseListner_MouseMove(object sender, MouseEventArgs e)だけですので、抜粋しています。

        void mouseListner_MouseMove(object sender, MouseEventArgs e)
        {
            //カーソルを変更
            if ((getTop().Contains(e.Location) &&
                getLeft().Contains(e.Location)) ||
                (getBottom().Contains(e.Location) &&
                getRight().Contains(e.Location)))
            {

                mouseListner.Cursor = Cursors.SizeNWSE;
            }
            else if ((getTop().Contains(e.Location) &&
                getRight().Contains(e.Location)) ||
                (getBottom().Contains(e.Location) &&
                getLeft().Contains(e.Location)))
            {
                mouseListner.Cursor = Cursors.SizeNESW;
            }

            else
            {
                mouseListner.Cursor = defaultCursor;
            }

            if (e.Button == MouseButtons.Left)
            {
                int diffX = e.X - lastMouseDownPoint.X;
                int diffY = e.Y - lastMouseDownPoint.Y;

                if ((status & DAndDArea.Left) == DAndDArea.Left && (status & DAndDArea.Top) == DAndDArea.Top)//左上
                {

                    int w = sizeChangeCtrl.Width;
                    sizeChangeCtrl.Width -= diffX;
                    sizeChangeCtrl.Left += w - sizeChangeCtrl.Width;

                    int h = sizeChangeCtrl.Height;
                    int h2 = sizeChangeCtrl.Width * 3 / 4;
                    sizeChangeCtrl.Height = h2;
                    sizeChangeCtrl.Top += h - h2;
                }
                if ((status & DAndDArea.Right) == DAndDArea.Right && (status & DAndDArea.Top) == DAndDArea.Top)//右上サイド
                {

                    sizeChangeCtrl.Width = lastMouseDownSize.Width + diffX;

                    int h = sizeChangeCtrl.Height;
                    int h2 = sizeChangeCtrl.Width * 3 / 4;
                    sizeChangeCtrl.Height = h2;
                    sizeChangeCtrl.Top += h - h2;
                }

                if ((status & DAndDArea.Left) == DAndDArea.Left && (status & DAndDArea.Bottom) == DAndDArea.Bottom)//左下
                {

                    int w = sizeChangeCtrl.Width;
                    sizeChangeCtrl.Width -= diffX;
                    sizeChangeCtrl.Left += w - sizeChangeCtrl.Width;
                    sizeChangeCtrl.Height = sizeChangeCtrl.Width * 3 / 4;
                }
                if ((status & DAndDArea.Right) == DAndDArea.Right && (status & DAndDArea.Bottom) == DAndDArea.Bottom) //右下
                {

                    sizeChangeCtrl.Width = lastMouseDownSize.Width + diffX;
                    sizeChangeCtrl.Height = sizeChangeCtrl.Width * 3 / 4;
                }

            }
        }

補足

  • 今回の修正は縦横比が4:3固定になっています
  • 参考リンクのソースを基にしているため、TextBoxでテストしています
  • コントロール端をつかんだ瞬間コントロールサイズが変更されます(もともとの動きがそうなってる?)

ご参考になれば幸いでございます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/19 10:49

    ありがとうございます。
    おかげさまでうまくいきました。

    キャンセル

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7121questions

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