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

ボタンの真横に別のフォームをだす方法

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

いつも参考にさせて頂いています。
下記の問題に何日も取り組んでいるのですが、どうしてもわかりません。
教えてやってください。

C#で、フォーム(Form1.cs)上にあるボタンをクリックすると、その真横に別のフォーム
(Form2.cs)を出す方法を調べています。

Form2にLocationを設定しておき、Form2の立ち上がる場所を指定する方法を
思いついたのですが、この方法だとForm1を移動させるとForm2の立ち上がる場所が
ボタンの真横ではなくなってしまいます。

また、代替の方法としてMainMenuやContextMenuをそのボタンの横にだせないかなぁ?
とも考えたのですが、それもうまくいきません。

どうしたらいいでしょうか? わかる方、どうかよろしくお願いします。
■No10003に返信(れちりんさんの記事)

こんばんわ okaと申します。

> Form2にLocationを設定しておき、Form2の立ち上がる場所を指定する方法を
> 思いついたのですが、この方法だとForm1を移動させるとForm2の立ち上がる場所が
> ボタンの真横ではなくなってしまいます。

Form2のLocationを設定するタイミングを、ボタン押下時にすればよいのでは?
と思ったのですが、どうでしょうか?
早速の返信、ありがとうございます!

それが、たぶんこっちが根本の問題点なのですが、画面のどの位置に
ボタンがあるかの取得方法がわからないのです。

Form1を移動させてボタンをクリック、そのボタンの隣にForm2を立ち上げるには
Form1が現在画面上のどの座標にあるか把握する必要がありますよね?
(それともそのボタンの横に、Form2をドッキングする等の方法があるのかも・・・)

Locationでは、どうもForm1上の座標みたいですし・・・
ただ、Form1やForm2のプロパティで、Locationを設定するとモニタ上の座標に
なるのですが・・・(悩

MainMenuやContextMenuをボタンの真横に出す方法もあれば、そっちも教えてほしい
です(これは無理かもしれないですよね?)



>
> こんばんわ okaと申します。
>
> Form2のLocationを設定するタイミングを、ボタン押下時にすればよいのでは?
> と思ったのですが、どうでしょうか?
■No10012に返信(れちりんさんの記事)

れちりんさん おはようございます。okaです。

> それが、たぶんこっちが根本の問題点なのですが、画面のどの位置に
> ボタンがあるかの取得方法がわからないのです。
ボタンの位置は this.button1.Topとか this.button.Left で取得可能です。

>
> Form1を移動させてボタンをクリック、そのボタンの隣にForm2を立ち上げるには
> Form1が現在画面上のどの座標にあるか把握する必要がありますよね?
> (それともそのボタンの横に、Form2をドッキングする等の方法があるのかも・・・)

Form1の位置はthis.Topとか this.Leftとかで取得可能です。


> Locationでは、どうもForm1上の座標みたいですし・・・
> ただ、Form1やForm2のプロパティで、Locationを設定するとモニタ上の座標に
> なるのですが・・・(悩

ということは、Form1の位置とForm1上のコントロールンの位置からForm2のスタートポジションが決まりそうですね。

つまり、Form2をForm1のボタンの真右にくっつけて表示するなら、
Form2の左端の位置 = Form1の左端の位置 + Form1のボタンの左端の位置 + Form1のボタンの横幅 となります。
これだけではもちろんだめで、Topの位置も設定してあげてください。

ただ、こちらで試してみた感じでは、Form2のインスタンスを作成後、Form1からForm2のTopとLeftのプロパティに値を入れてもだめでしたが、Form2に2つプロパティを作って、をのプロパティにLeftとTopを設定しました。
それをForm2のLoadのイベントでそれぞれTopとLeftに設定してやると、Form1がどこにいてもForm2は常にForm1のボタンの右にくっついて出てくる処理が出来ます。


> MainMenuやContextMenuをボタンの真横に出す方法もあれば、そっちも教えてほしい
> です(これは無理かもしれないですよね?)

すみません。こちらはまったく試してません。
■No10014に返信(okaさんの記事)

すみません。自己レスです。
上記プロパティを設定・・・というところは無視してください。
そんなややこしいことしなくても、ShowメソッドでForm2を呼出し後にForm1からForm2のTopとLeftを設定すれば問題なしです。
クライアント内のコントロールのスクリーン座標の取得方法として
Control.PointToScreen メソッドなんてものもあります。
ご参考までに。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclasspointtoscreentopic.asp
みなさん返信ありがとうございます!!

上記、返信頂けた件さっそくためしてみます。
なかなか時間がとれなくて返信できず申し訳ありません。
いつもお世話になっています。

現在、Form1の座標を取得することができ、その座標を、
Form2が立ち上がる前にForm2に渡すことができました!
 ありがとうございます(感涙

今、その渡した座標でForm2を立ち上げるところで悩んでます〜
ですが、これはもう少し時間があれば何とかなるかと思います。
もう少し試してみます! ありがとうございます。
また後ほど報告します。


あと、PointToScreenの方がまったくうまくいきません・・・・
これはどんな風に使えるのでしょうか?
いろいろ調べて、例を探してみたのですが・・・

たとえば、Form1上のbutton1を押せば、Form1やbutton1の座標
を取得できるようにしたいのですが・・・
どうすればいいでしょうか?

よろしくお願いしますー!
> あと、PointToScreenの方がまったくうまくいきません・・・・
> これはどんな風に使えるのでしょうか?
> いろいろ調べて、例を探してみたのですが・・・
>
> たとえば、Form1上のbutton1を押せば、Form1やbutton1の座標
> を取得できるようにしたいのですが・・・
> どうすればいいでしょうか?

自分の勉強のために少し試してみました。

例えば、button1.PointToScreen(new Point(0, 0) );
とすればbutton1の左上座標が取得できるようです。

ButtonをPanelの上に配置したりしても
関係ないので、この方が楽だと思います。

ちなみに、form2を表示する前にLocaitonを設定する場合
form2.StartPosition = FormStartPosition.Manual;
を入れておけば大丈夫です。
コントロールの座標(Location)というのはそのコントロールの親からの座標を表しています。
例えばForm1にボタンを(10,10)の座標に貼り付けたとします。
このForm1を画面上の座標(10,10)に表示した場合、Buttonの画面上の位置は(20、20)ですが、
ボタンの座標は変わらず(10,10)の値のまま。これはForm1との相対座標を表示しているためです。
そのままForm2の表示の座標に使用するとButtonの座標は(10,10)のためボタンと同じ場所に表示しようとしても、
Form2は画面上の座標(10,10)に表示されてしまうことになります。(Form1と同じ位置)

つまり、コントロールの位置にフォームを表示したい場合、コントロールの画面上の絶対座標を求める必要があるわけです。

PointToScreenはそのコントロール上の相対座標を画面上の絶対座標に変換して返してくれるものです。
使い方としては上記の例の場合、
Form2.Location = Form1.PointToScreen(Button.Location);
みたいな形でしょうか。
Form2の座標には(20,20)が設定されるはずです。
> 使い方としては上記の例の場合、
> Form2.Location = Form1.PointToScreen(Button.Location);
> みたいな形でしょうか。

これだと、ボタンがパネル上にあったらダメじゃないですか?
■No10100に返信(Dantiさんの記事)
> これだと、ボタンがパネル上にあったらダメじゃないですか?

いえいえ、やっていることはDantiさんの方法とほとんど同じなのです。

Dantiさんの場合は
PointToScreen実行コントロール:対象コントロール
変換座標:対象コントロール内の座標(0,0)

私の場合は
PointToScreen実行コントロール:対象コントロールの親
変換座標:対象コントロールの親内の座標(対象コントロールのLocation)

呼び出し元が違うというだけで動きに違いはありません。

例)
Panelに貼り付けた場合
Panel.PointToClient(Button.Location)
親が色々変わる場合
Button.Parent.PointToScreen(Button.Location)
■No10102に返信(bellさんの記事)
間違えました…
> Panel.PointToClient(Button.Location)

Panel.PointToScreen(Button.Location)
です。
みなさんありがとうございます!

>Okaさん

>ShowメソッドでForm2を呼出し後にForm1からForm2のTopとLeftを設定すれば問題>なしです。

この変をもう少し教えてもらえますか・・・(すいません
Form1から、Form2のTopとLeftを設定ができなかったので
Form2から、Form1のTopとLeftを取得するとその、TopとLeftの
座標は、なぜか"0"になってしまいます・・・

>Dantiさん
取得できました! あれから僕も調べてみて少し違いますが下記の書き方で
できることを確認しました。

Point Z = new Point(0, 0) ;
MessageBox.Show(this.PointToScreen(Z).X.ToString());
ありがとうございます!


>bellさん
Form1上にbutton1、Form2上にbutton1をつくり、Form2のbutton1を
押すと取得できるようにしてみたのですが駄目でした。
クリックするたび座標が変わります??

・・・・お話以前の問題なのかもしれません。たぶん・・・(T_
すいません。教えてください・・・

private void button1_Click(object sender, System.EventArgs e)
{
Form2 f2=new Form2();
Form1 f1=new Form1();
f2.Location = f1.PointToScreen(button1.Location);
MessageBox.Show(f2.Location.ToString());
}
■No10104に返信(れちりんさんの記事)
れちれんさん、こんばんは。okaです。
なかなか色々な方からのアドバイスが出てきて勉強になりますね。
私の方法はそんなに頭を使う必要もないのですが・・・。

> >ShowメソッドでForm2を呼出し後にForm1からForm2のTopとLeftを設定すれば問題>なしです。
>
> この変をもう少し教えてもらえますか・・・(すいません
> Form1から、Form2のTopとLeftを設定ができなかったので

設定が出来ないというのがよくわからないところですが、ごく簡単なコードにすると

private void button1_Click(object sender, System.EventArgs e)
{
Form2 f = new Form2();

f.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
f.Left = this.Left + this.button1.Left + this.button1.Width;
f.Top = this.Top + this.button1.Top;
f.ShowDialog();//またはf.Show();
}

こんな感じでしょうか。
これでどの位置にForm1があってもForm1上のbutton1の右端とForm2の左端がくっついタ状態で、Form2が表示されます。

あとは、Form2の表示位置をもう少し右とか上とか細かく設定するのであれば、
f.Left = ・・・ + 10
とかすれば微調整ができるのでそのあたりはお好みで。
2005/03/28(Mon) 09:56:35 編集(投稿者)

■No10104に返信(れちりんさんの記事)
> private void button1_Click(object sender, System.EventArgs e)
> {
> Form2 f2=new Form2();
> Form1 f1=new Form1();
> f2.Location = f1.PointToScreen(button1.Location);
> MessageBox.Show(f2.Location.ToString());
> }

逆に質問なのですが、
1.このイベントは誰のボタンが呼んでいる?(Form1?Form2?それとも別?)
2.もしForm1/Form2の場合、ここでまた新規にForm1/Form2を定義している意図は?
3.f2座標の設定に使っているbutton1はf1のボタンじゃないけどいいの?
4.f1の座標はどうなっていますか?毎回違っていませんか?(f1のStartPositionは?)
5.最初の話の「"Form1"のボタンを押すと"Form2"がボタンの横に表示」と今回のコードは食い違っているけれどどちらが本当の動作?

どういう構成でどんな状態になればいいのかがいまいちつかめませんでした。

追加
> Form1上にbutton1、Form2上にbutton1をつくり、Form2のbutton1を
> 押すと取得できるようにしてみたのですが駄目でした。
見落としてました。(^^;)
今の動きだと
Form2(A)のボタンを押すと新たにForm2(f2 Aとは別物)とForm1(f1)を作成し、
Aのボタンの座標の値をf1の座標としてf2の画面座標を計算、表示…
…本当にこの動きであってます…?
遅くなって申し訳ありません!!(T_
なぜか家からだと書き込みできなくて・・・ 夜とか祭日だからかもしれないですが・・

>okaさん
 ありがとうございます!! この方法でできました。
 こんな方法があるとは思いもしませんでした。正直何十時間ぐらい悩んだです!!
 ありがとうございました。
 で、実際には他にbellさんに教えてもらったPointToScreenを合わせて
使用しました。this.topを使用するとなぜかForm2の左上と一致しなかったので。
 ソースは・・・すいません。時間がなくなりましたので、夕方アップします・・・(汗

>bellさん
 あううー 時間がなくなりましたので、五時くらいから続き書きますー
 すいません!!!
■No10137に返信(れちりんさんの記事)
れちりんさん okaです。

できたみたいでよかったですね。
で、出来上がってしまってから言うのもあれですが、Topの位置が合わないということでしたが、それは恐らくフォームのタイトルバーの高さ分とフォームの枠の高さ分ではないでしょうか?
そうであれば、単にForm2の高さ設定のところで、その高さ分を足して調節すればよいかと思うのですが・・・。
厳密な値が必要でなければ、目分量で適当な値を足してやってもいいし、厳密にその高さを取得してから足したいのであれば、SystemInformationクラスに必要な値が入っていますので、それを使用してもいいと思います。

SystemInformationクラスについては、どぼんさんの.NET Tips内でも紹介されていますので、ぜひ一度目を通してみてください。
いつもお世話になっています。

■okaさん
なるほど! タイトルバーの大きさですか・・・ 解像度が違えば大きさがかわり
そうなので以下のようなコードにしました。ホントにありがとうございました(ぺこ

f.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
f.Left = this.Left + this.button1.Left + this.button1.Width;
Point Z = new Point(0, 0) ;
f.Top = this.PointToScreen(Z).Y+this.button1.Top;
f.Show();

■bellさん
このコードは、Form2上にあります。新たに定義しているのは、
f2.Location を form2.Locationとしたりするとエラーがでてしまったために
しかたなく書き込みました。
>3
はい、そのbutton1はForm2上にあります。説明悪いですよね・・すいません。
>4.5
 うーんすいません。そういわれるとよくわからんコードです。
たくさんあがいてみて、混乱していたのかもしれないです。

>Form2(A)のボタンを押すと新たにForm2(f2 Aとは別物)とForm1(f1)を作成し、
>Aのボタンの座標の値をf1の座標としてf2の画面座標を計算、表示…
 いえ、Form1上のボタンを押すと、そのボタンの真横にForm2を作成したかった
んです。添付ファイルみたいな感じです。


 それにしてもなんで、家から書き込めないんだろう・・・(汗
(この記事にはファイル"form1form2.GIF"が添付されていましたが、削除されました。)
>  それにしてもなんで、家から書き込めないんだろう・・・(汗

ご自宅からこの掲示板へ書込みができませんか?ちょっと気になりますので、よろしければお気楽掲示板へ詳しい症状を投稿していただけないでしょうか?ちなみにこの掲示板は今のところ誰かを書き込み拒否にしているということはありませんので、その点はご安心ください。

お気楽掲示板
http://dobon.net/cgi-bin/kirakubbs/cbbs.cgi
  • 題名: Re[10]: 書き込めませんか?
  • 著者: れちりん
  • 日時: 2005/03/29 8:59:48
  • ID: 10151
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
管理人様、いつもお世話になっています!

早速家に帰り次第、お気軽掲示板に投稿できるか? またそのアクセスできない内容
を確認してみますので、よろしくお願いします。

わざわざありがとうございます!

■No10150に返信(管理人さんの記事)
>> それにしてもなんで、家から書き込めないんだろう・・・(汗
>
> ご自宅からこの掲示板へ書込みができませんか?ちょっと気になりますので、よろしければお気楽掲示板へ詳しい症状を投稿していただけないでしょうか?ちなみにこの掲示板は今のところ誰かを書き込み拒否にしているということはありませんので、その点はご安心ください。
>
> お気楽掲示板
> http://dobon.net/cgi-bin/kirakubbs/cbbs.cgi
■No10146に返信(れちりんさんの記事)
> このコードは、Form2上にあります。新たに定義しているのは、
> f2.Location を form2.Locationとしたりするとエラーがでてしまったために
> しかたなく書き込みました。
???エラー云々はともかく、Form1のbutton1を押した時に動く処理が何故Form2に…?
また、エラーの根本的な原因を解決せずにその場しのぎの処理でごまかすのは下策だと思いますよ。多分Form2.Locationではなくthis.LocationならOKのはずです。
何故こうなのかは今回の質問とは関係ないので割愛します。調べてみてください。
> >3
> はい、そのbutton1はForm2上にあります。説明悪いですよね・・すいません。
「Form1のbutton」の横に「Form2」を出したいんですよね…?そこに何故「Form2上のbutton」が関わってくるのでしょうか…?
> >4.5
>  うーんすいません。そういわれるとよくわからんコードです。
> たくさんあがいてみて、混乱していたのかもしれないです。
1回落ち着いて自分のやりたい動作とコード上の動きを比較してみたほうがいいと思います。

> >Form2(A)のボタンを押すと新たにForm2(f2 Aとは別物)とForm1(f1)を作成し、
> >Aのボタンの座標の値をf1の座標としてf2の画面座標を計算、表示…
>  いえ、Form1上のボタンを押すと、そのボタンの真横にForm2を作成したかった
> んです。添付ファイルみたいな感じです。
まさか…こういうこと(添付ファイル参照)がしたい…?
だとしたらUserControlを使用すべきだと思います…。
(この記事にはファイル"testpts.lzh"が添付されていましたが、削除されました。)
ゆーざーこんとろーる??

いつもお世話になっています。
早速添付をダウンロードさせてもらい、実行してみました。

ですが、これだけではよくわからなかったので検索をかけてみたところ
・・・ひょっとして、新しいプロジェクトから、ユーザーコントロールを
作成したのでしょうか?
 そこで、初めてユーザーコントロールを作ってみたところ、なにやらデザインの部分で
タイトルバーが最初からないくらいしかわからなかったですorz

 早速いろいろ調べてみますー! ありがとうございます。
少し時間をください。
いつもお世話になっています。

あれからいろいろ調べたり、チュートリアルもやってみました。
bellさんに言われるまで、新規作成時Windowsアプリケーションしか気にも
しなかったんですが、この違いが正直よくわかりません。
どういうときに、Windowsアプリケーションとユーザーコントロールを使い分けるの
でしょうか?

 検索してみるといろいろ出てきたのですが、新規作成時のWindowsアプリケーション
とユーザーコントロールのソースの違いも無いみたいですし、プロパティも
違いがないみたいです。若干、ソリューションエクスプロラーの表示されるアイコン
が違うぐらいにしかわかりません。

 VisualStudio上の取り扱いの違いぐらいですかね? またどう取り扱いが
違うのでしょうか?

 どうしようもない初心者質問ですいませんー!

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