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

コンテキストメニューストリップでの淡色表示

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

例えばメモ帳だとかで、右クリックの「コピー」はコピーできる部分がなければ(反転させていないとか)淡色表示になって選択できないじゃないですか、
あれを作りたいのですが、
If TextBox1.SelectionLength = 0 Then
Me.CopyText.Enabled = False
End If
としても全く意図した動きをしてくれません。
あれは一体どうすれば実装できるのでしょうか。
■No23894に返信(緑可さんの記事)
> 例えばメモ帳だとかで、右クリックの「コピー」はコピーできる部分がなければ
>(反転させていないとか)淡色表示になって選択できないじゃないですか、
> あれを作りたいのですが、
コードを書かずとも、.NET の TextBox はそのように動作すると思いますよ。


> If TextBox1.SelectionLength = 0 Then
> Me.CopyText.Enabled = False
> End If
> としても全く意図した動きをしてくれません。
どのような動きを意図していて、実際にはどうなってしまうのかを
書かないと、掲示板を見ている他の人には伝わりませんよ。

で。上記 CopyText というのが、メニュー項目なのでしょうか。
だとすると、上記のコードはどこに記述していますか?

「選択範囲が変わったとき」に、Enabled を調整せねばならないので、
たとえば、TextChanged イベントなどでは駄目だと思います。
RichTextBox.SelectionChanged イベントなどであれば良いでしょうけれども。

また、Enabled = False にするだけではなく、True に戻すコードも
必要になるはずですが、その点は大丈夫でしょうか?
■No23895に返信(魔界の仮面弁士さんの記事)
> ■No23894に返信(緑可さんの記事)
>>例えばメモ帳だとかで、右クリックの「コピー」はコピーできる部分がなければ
> >(反転させていないとか)淡色表示になって選択できないじゃないですか、
>>あれを作りたいのですが、
> コードを書かずとも、.NET の TextBox はそのように動作すると思いますよ。
>
そうなんですか……。

>
>>If TextBox1.SelectionLength = 0 Then
>> Me.CopyText.Enabled = False
>>End If
>>としても全く意図した動きをしてくれません。
> どのような動きを意図していて、実際にはどうなってしまうのかを
> 書かないと、掲示板を見ている他の人には伝わりませんよ。

> で。上記 CopyText というのが、メニュー項目なのでしょうか。
> だとすると、上記のコードはどこに記述していますか?

CopyTextはコンテキストメニューストリップの項目に入れています。
で、そこに上のコードを記述しています。というか今はこうなっています。

Private Sub CopyText_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles copy.Click
If TextBox1.SelectionLength > 0 Then
TextBox1.Copy()
End If
End Sub
ここに追加で
If TextBox1.SelectionLength = 0 Then
Me.CopyText.Enabled = False
End If
と、とりあえず入れてみたんです。
デバッグ→フォームのテキストボックスに入力されている文字列は反転表示していませんが、右クリックしても淡色にはなりませんでした。


> 「選択範囲が変わったとき」に、Enabled を調整せねばならないので、
> たとえば、TextChanged イベントなどでは駄目だと思います。
> RichTextBox.SelectionChanged イベントなどであれば良いでしょうけれども。
>
> また、Enabled = False にするだけではなく、True に戻すコードも
> 必要になるはずですが、その点は大丈夫でしょうか?

忘れてました……。
■No23894に返信(緑可さんの記事)
> 例えばメモ帳だとかで、右クリックの「コピー」はコピーできる部分がなければ(反転させていないとか)淡色表示になって選択できないじゃないですか、
> あれを作りたいのですが、
> If TextBox1.SelectionLength = 0 Then
>             Me.CopyText.Enabled = False
>  End If
> としても全く意図した動きをしてくれません。
> あれは一体どうすれば実装できるのでしょうか。

TextBox1に関連付けたContextMenuStripのOpeningイベントに、以下の様なコード
を記述してみては如何でしょうか?(サンプルがC#で申し訳ありません)


private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
     // CopyToolStripMenuItem は "コピー" としている ToolStripMenuItem です。
     CopyToolStripMenuItem.Enabled = textBox1.SelectionLength > 0;
}
■No23898に返信(緑可さんの記事)
>>コードを書かずとも、.NET の TextBox はそのように動作すると思いますよ。
> そうなんですか……。
上記は、ContextMenu プロパティを指定しなかった場合の話です。

その場合、OS 既定のコンテキストメニューが表示され、その[コピー(C)]項目は、
自動的に Enabled の切り替えが行われます。

> Private Sub CopyText_Click(ByVal sender As System.Object, _
> ByVal e As System.EventArgs) Handles copy.Click
Sub の名前と、Handles の指定に食い違いがあるのが気に掛かります。

これは、「CopyText がクリックされた時」のイベントではなく、
「copy がクリックされた時のイベント」ですが、
わざと名前を変えているのでしょうか?

CopyText と copy の関係が分かりません。同一の物ですか?

もし両者が別物で、copy がコンテキストメニュー(ContextMenuStrip)で、
CopyText がメニュー項目(ToolStripMenuItem)なのだとしたら、
下記のようにすると良いでしょう。

 Private Sub copy_Opening(ByVal sender As Object, ByVal e As CancelEventArgs) Handles copy.Opening
  CopyText.Enabled = TextBox1.SelectionLength > 0
 End Sub

こうすると、コンテキストメニューを表示した時点で Enabled が切り替わります。


> ここに追加で
> If TextBox1.SelectionLength = 0 Then
>  Me.CopyText.Enabled = False
> End If
> と、とりあえず入れてみたんです。
CopyText と copy の関係が分かりませんが、想像で回答:

《copy が ContextMenuStrip の場合》
そもそも、copy の Click イベント自体が発生していないと思います。


《copy と CopyText が、同一の ToolStripMenuItem である場合》あるいは
《copy も CopyText も ToolStripMenuItem で、copy が CopyText の親階層の場合》
copy をクリックした時点で、CopyText の Enabled が False になります。
copy をマウスでポイントしただけでは、Enabled は切り替わりません。
■No23900に返信(魔界の仮面弁士さんの記事)

>>Private Sub CopyText_Click(ByVal sender As System.Object, _
>> ByVal e As System.EventArgs) Handles copy.Click
> Sub の名前と、Handles の指定に食い違いがあるのが気に掛かります。
>
> これは、「CopyText がクリックされた時」のイベントではなく、
> 「copy がクリックされた時のイベント」ですが、
> わざと名前を変えているのでしょうか?
>
> CopyText と copy の関係が分かりません。同一の物ですか?
>


あ。すみません。Re2を書く前に作っていたそのプログラムが問題きたして一から作り直していて、その時にもともとCopyTextと入れていたあのnameプロパティをcopyって入れて通したので、今の「右クリックしてコピー」のコードは
Private Sub copy_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles copy.Click
なのですが、それだと最初の書き込みの
If TextBox1.SelectionLength = 0 Then
Me.CopyText.Enabled = False
End If
この記述に食い違いが生じるので、copyをCopyTextに全て直して投稿したつもりだったんですが……。Handlesの後も直すの忘れていました。
同じものです。
■No23899に返信(まことさんの記事)

> TextBox1に関連付けたContextMenuStripのOpeningイベントに、以下の様なコード
> を記述してみては如何でしょうか?(サンプルがC#で申し訳ありません)
>
>
> private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
> {
> // CopyToolStripMenuItem は "コピー" としている ToolStripMenuItem です。
> CopyToolStripMenuItem.Enabled = textBox1.SelectionLength > 0;
> }
>

えっと、つまり
Private Sub CopyText_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles CopyText.Click
CopyText.Enabled = TextBox1.SelectionLength > 0
If TextBox1.SelectionLength > 0 Then
TextBox1.Copy()
End If
End Sub
ですよね?
無理でした……。
■No23903に返信(緑可さんの記事)
> えっと、つまり
> ですよね?

いえ、残念ながら違います。

緑可さんがコードを記述されているのは、CopyText(ToolStripMenuItemクラス)の
Clickイベントですよね。

つまりテキストボックスの上で右クリックして表示されるコンテキストメニュー
の"コピー"の項目をクリックした時に発生するイベントです。

そこには恐らく

  If TextBox1.SelectionLength > 0 Then
    TextBox1.Copy()
  End If

とだけ記述しておけば良いと思います。(選択文字列をクリップボードにコピー)


実現したい事は"テキストボックスの上で右クリックをした時に、コンテキスト
メニューが表示される前に文字列の選択状態を確認し、状態に応じてメニューの
有効・無効を切りかえる"事ですから

  CopyText.Enabled = TextBox1.SelectionLength > 0

を記述するタイミングは"テキストボックスの右クリック"か"コンテキストメニュー
が表示される直前"が妥当という事になります。

そしてその処理を記述する最適なイベントとして、ContextMenuStripクラスの
Openingイベントがあり、私や魔界の仮面弁士さんが提示しているコードがまさに
それに相当しています。

ContextMenuStripクラスは…既にデザイナ上に貼り付けてあると思いますので
見つからない様でしたらプロパティウィンドウの"Form1 System.Windows.Form"等
表示されているコンボボックスの中から探してみて下さい。
■No23904に返信(まことさんの記事)
> 実現したい事は"テキストボックスの上で右クリックをした時に、コンテキスト
> メニューが表示される前に文字列の選択状態を確認し、状態に応じてメニューの
> 有効・無効を切りかえる"事ですから
>
> CopyText.Enabled = TextBox1.SelectionLength > 0
>
> を記述するタイミングは"テキストボックスの右クリック"か"コンテキストメニュー
> が表示される直前"が妥当という事になります。
>
> そしてその処理を記述する最適なイベントとして、ContextMenuStripクラスの
> Openingイベントがあり、私や魔界の仮面弁士さんが提示しているコードがまさに
> それに相当しています。
>
> ContextMenuStripクラスは…既にデザイナ上に貼り付けてあると思いますので
> 見つからない様でしたらプロパティウィンドウの"Form1 System.Windows.Form"等
> 表示されているコンボボックスの中から探してみて下さい。



Private Sub ContextMenuStrip1_Opening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
CopyText.Enabled = TextBox1.SelectionLength > 0
End Sub

できました!
ありがとうございます。私の知識不足ですね。
お二人ともありがとうございました。
解決済み!

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