C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: エンターを押せないようにする


(過去ログ 122 を表示中)

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■72907 / inTopicNo.1)  エンターを押せないようにする
  
□投稿者/ よしむら (29回)-(2014/08/01(Fri) 00:14:22)

分類:[C#] 

ウェブブラウザ機能を搭載したアプリケーションをC#で開発しています。
処理上どうしてもウェブサイト内のボタンをクリックしてもらいたいところがあるのですが、サイトの作りはテキストボックス入力中にエンターを押すと先へ進んでしまいます。

なんとか、エンターを無効にしたり、「クリックでお願いします」というメッセージを表示したりしたいです。
よろしくおねがいします。
引用返信 編集キー/
■72909 / inTopicNo.2)  Re[1]: エンターを押せないようにする
□投稿者/ WebSurfer (314回)-(2014/08/01(Fri) 09:28:18)
No72907 (よしむら さん) に返信

質問の際には、最初にご自分の環境(OS, .NET, Visual Studio のバージョン、使っている言語)や
何を作っているかなどの情報を書きましょう。

> なんとか、エンターを無効にしたり、

System.Windows.Forms.WebBrowser コントロールを使った Windows Forms アプリを作っていると想像
して・・・

WebBrowser.DocumentCompleted イベントで、当該テキストボックスの HtmlElement オブジェクトを
取得し、HtmlElement.SetAttribute メソッドで onkeydown 属性に以下のようなスクリプトを設定し
たら、Enter キーを無効にできませんか?

if (event.keyCode == 13) return false;

検証してないのでハズレでしたらすみません。
引用返信 編集キー/
■72937 / inTopicNo.3)  Re[2]: エンターを押せないようにする
□投稿者/ よしむら (31回)-(2014/08/01(Fri) 21:50:15)
お返事有り難うございます。
情報がうすくてすみません。
visual studio2010でC#で開発しています。.netは4でした。

たとえば、以下のコードだと、yahooで検索ボタンを押せば「検索しましたね」が表示されますが、エンターで検索してしまうと何も出なくなってしまいます。
これを、エンターではボタンが押せなくするというのが理想です。
よろしくおねがいします。


		private void button29_Click_1(object sender, EventArgs e)
		{

			webBrowser1.Navigate("http://www.yahoo.co.jp/");
			MessageBox.Show("表示されるまで待ってください");
			ボタン押せ("input","srchbtn");
			MessageBox.Show("検索しましたね!");
		}





		public void ボタン押せ(string ボタン要素,string ボタン属性名)
		{
			bool フラグ = false;
			HtmlElementCollection buttonid = webBrowser1.Document.GetElementsByTagName(ボタン要素);
			foreach (HtmlElement button in buttonid)
			{
				Application.DoEvents();
				if (button.Id == ボタン属性名)
				{
					button.AttachEventHandler("onclick", delegate { フラグ = true; });
					break;
				}
			}
			while (フラグ != true)//待機
			{
				Application.DoEvents();
			}
		}

引用返信 編集キー/
■72938 / inTopicNo.4)  Re[3]: エンターを押せないようにする
□投稿者/ 魔界の仮面弁士 (68回)-(2014/08/01(Fri) 23:02:26)
No72937 (よしむら さん) に返信
> これを、エンターではボタンが押せなくするというのが理想です。

こんな感じかな。

ついでに、「DoEvents」併用の待機プログラムではなく、
イベント駆動型のコードに書き換えています。


private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.yahoo.co.jp/");
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
  webBrowser1.Document.Body.AttachEventHandler("onkeypress", (element, args) =>
  {
    var eventObj = ((dynamic)webBrowser1.Document.Window.DomWindow).@event;
    if (eventObj.keyCode == (int)Keys.Enter)
    {
      eventObj.cancelBubble = true;
      eventObj.returnValue = false;
      System.Diagnostics.Debug.WriteLine("Enter cancelled");
    }
  });

  押した時の処理("input", "srchbtn", delegate
  {
    MessageBox.Show("検索しましたね!");
  });
}

private void 押した時の処理(string tagName, string id, EventHandler action)
{
  var tag = webBrowser1.Document.GetElementsByTagName(tagName)
        .OfType<HtmlElement>().Where(b => b.Id == id).FirstOrDefault();

  if (tag != null)
  {
    tag.AttachEventHandler("onclick", delegate { BeginInvoke(action); });
  }
}
引用返信 編集キー/
■72940 / inTopicNo.5)  Re[3]: エンターを押せないようにする
□投稿者/ WebSurfer (315回)-(2014/08/01(Fri) 23:47:59)
No72937 (よしむら さん) に返信

先の私のレスで、

> WebBrowser.DocumentCompleted イベントで、当該テキストボックスの HtmlElement オブジェクトを
> 取得し、HtmlElement.SetAttribute メソッドで onkeydown 属性に以下のようなスクリプトを設定し
> たら、Enter キーを無効にできませんか?

とお尋ねしていますが、それではダメだったのでしょうか? レスを無視しないで、ダメならダメと
回答いただければと思います。
引用返信 編集キー/
■72943 / inTopicNo.6)  Re[4]: エンターを押せないようにする
□投稿者/ よしむら (32回)-(2014/08/02(Sat) 09:12:09)
WebSurferさんすみません。

72937のプログラムに組み込んでみたかったのですが、うまく組み込めませんでした。
お返事してなくてすみません。

if (event.keyCode == 13) return false;
のeventの部分にエラーがでてどのように組み込めばできるのかわかりませんでした。


引用返信 編集キー/
■72944 / inTopicNo.7)  Re[5]: エンターを押せないようにする
□投稿者/ 魔界の仮面弁士 (69回)-(2014/08/02(Sat) 10:29:11)
No72943 (よしむら さん) に返信
> if (event.keyCode == 13) return false;
> のeventの部分にエラーがでてどのように組み込めばできるのかわかりませんでした。

event は C# の予約語です。それがエラーになるという事は、
JavaScript としてではなく、C# のコードとして記述されたのでは無いでしょうか。

こちらでも試してみました。


private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.yahoo.co.jp/");
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
  var textBox = webBrowser1.Document.GetElementById("srchtxt");
  var button = webBrowser1.Document.GetElementById("srchbtn");

  if (button != null) button.AttachEventHandler("onclick", delegate { MessageBox.Show("検索しましたね!"); });

  
  // これらの方法では、ブロックできなかった
  // if (textBox != null) textBox.SetAttribute("onkeydown", "if (event.keyCode == 13) return false;");
  // if (textBox != null) ((dynamic)textBox.DomElement).onkeydown = "if (event.keyCode == 13) { event.returnValue = false; }";

  // これならブロックされた
  //if (textBox != null) textBox.AttachEventHandler("onkeydown", (elm, arg) =>
  //{
  //  // 「event」 は C# の予約語なので、「@event」 と記述する
  //  var evt = ((dynamic)webBrowser1.Document.Window.DomWindow).@event;
  //  if(evt.keycode == 13) evt.returnValue = false;
  //});

  // これでもブロックできた
  //if (textBox != null) textBox.KeyDown += (element, args) =>
  //{
  //  if (args.KeyPressedCode == 13) args.ReturnValue = false;
  //};

  // これでもブロックできた
  //if (textBox != null) textBox.KeyPress += (element, args) =>
  //{
  //  if (args.KeyPressedCode == 13) args.ReturnValue = false;
  //};
}

引用返信 編集キー/
■72945 / inTopicNo.8)  Re[6]: エンターを押せないようにする
□投稿者/ よしむら (34回)-(2014/08/02(Sat) 13:02:40)
No72944 (魔界の仮面弁士 さん) に返信

ありがとうございます。
一つづつ試してみましたが、コメントどおりの動きになりました。

72938に、
>>ついでに、「DoEvents」併用の待機プログラムではなく、
>>イベント駆動型のコードに書き換えています。

と書かれていますが、DocumentCompletedを使わない記述も可能なのでしょうか?
常にエンターが使えないわけではなく、特定のページの時のみ使えないようにしたかったので、方法を考えています。
特定の時のみフラグを立てて
DocumentCompleted内をifで処理を別けるほうがよいのでしょうか?

引用返信 編集キー/
■72946 / inTopicNo.9)  Re[6]: エンターを押せないようにする
□投稿者/ WebSurfer (316回)-(2014/08/02(Sat) 13:46:43)
No72944 (魔界の仮面弁士 さん) に返信
  
>   // これらの方法では、ブロックできなかった
>   // if (textBox != null) textBox.SetAttribute("onkeydown", "if (event.keyCode == 13) return false;");

フォローを有難うございます。

> // これらの方法では、ブロックできなかった
> // if (textBox != null) textBox.SetAttribute("onkeydown", "if (event.keyCode == 13) return false;");

自分も試してみましたけど、ご指摘の通り私が提案した方法ではダメでした。

クライアントスクリプト(リスナー)を登録できない or 有効にならないようです。


No72945 (よしむら さん) に返信

上記のわけで、すみません、ダメでした。

魔界の仮面弁士 さんの紹介された方法で対応ください。

引用返信 編集キー/
■72947 / inTopicNo.10)  Re[7]: エンターを押せないようにする
□投稿者/ 魔界の仮面弁士 (70回)-(2014/08/02(Sat) 15:19:30)
No72945 (よしむら さん) に返信
> 常にエンターが使えないわけではなく、特定のページの時のみ使えないようにしたかったので、方法を考えています。

「特定のページ」とありますが No72937 のコードの場合、一度『検索』して次ページに遷移した後、
そこから右クリック→[前に戻る] などで戻ってきた場合、自作したイベントが処理されませんが、それで良いのでしょうか?


その動作で構わないというのであれば、Navigate 後の最初の DocumentCompleted イベントのみを
捕えるようにし、そのあとはイベントハンドラを解除してしまうという手があります。


private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.yahoo.co.jp/");
  WebBrowserDocumentCompletedEventHandler action = null;
  action = (wb, args) =>
  {
    Func<string, HtmlElement> @id = webBrowser1.Document.GetElementById;
    @id("srchbtn").Click += (t, a) => { MessageBox.Show("検索しましたね!"); };
    @id("srchtxt").KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };
    webBrowser1.DocumentCompleted -= action;  // 一度呼ばれたら直ちに解除
  };
  webBrowser1.DocumentCompleted += action;
}


フレームを切ってある Web サイトなどのように、DocumentCompleted が
複数回発生する場合には、もう少し手直しが必要ですね。
引用返信 編集キー/
■72948 / inTopicNo.11)  Re[8]: エンターを押せないようにする
□投稿者/ 魔界の仮面弁士 (71回)-(2014/08/02(Sat) 15:54:35)
No72947 (魔界の仮面弁士) に追記
> 「特定のページ」とありますが No72937 のコードの場合、一度『検索』して次ページに遷移した後、
> そこから右クリック→[前に戻る] などで戻ってきた場合、自作したイベントが処理されませんが、それで良いのでしょうか?

すべての <input type="text"> に対して、 Enter をキャンセルさせるようにしてみました。

Enter による送信を望まないのであれば、テキストボックス内で Enter が必要になることも
無いので、ページの内容に関わらず、全キャンセルで構わないかと。


private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.yahoo.co.jp/");

  // webBrowser1.DocumentCompleted += (wb, args) =>
  // {
  //   var button = webBrowser1.Document.GetElementById("srchbtn");
  //   if(button != null) button.Click += (t, a) => { MessageBox.Show("検索しましたね!"); };
  // };
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
  var q = webBrowser1.Document.GetElementsByTagName("INPUT").OfType<HtmlElement>()
        .Where(input => input.GetAttribute("type").ToLower() == "text");
  foreach (var text in q)
  {
    text.KeyPress += (tag, args) => { args.ReturnValue = args.KeyPressedCode != 13; };
  }
}
引用返信 編集キー/
■72956 / inTopicNo.12)  Re[9]: エンターを押せないようにする
□投稿者/ よしむら (35回)-(2014/08/04(Mon) 16:23:24)
2014/08/04(Mon) 16:29:42 編集(投稿者)

No72948 (魔界の仮面弁士 さん) に返信
何度もありがとうございます。

別ページで長文を書く場所にinput type=textがあったため、72947の方をうまく使いたいと思います。
頂いた回答に私の知識が全然ついていけないため、意味を調べながら少しづつやっていきたいと思っています。


引用返信 編集キー/
■72957 / inTopicNo.13)  Re[7]: エンターを押せないようにする
□投稿者/ よしむら (36回)-(2014/08/04(Mon) 16:29:23)

No72948 (魔界の仮面弁士 さん) に返信
何度もありがとうございます。

別ページで長文を書く場所にinput type=textがあったため、72947の方をうまく使いたいと思います。
頂いた回答に私の知識が全然ついていけないため、意味を調べながら少しづつやっていきたいと思っています。


引用返信 編集キー/
■72958 / inTopicNo.14)  Re[8]: エンターを押せないようにする
□投稿者/ よしむら (37回)-(2014/08/04(Mon) 17:31:19)
No72948 (魔界の仮面弁士 さん) に返信

質問なのですが、

private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.yahoo.co.jp/");
  WebBrowserDocumentCompletedEventHandler action = null;
  action = (wb, args) =>
  {
    Func<string, HtmlElement> @id = webBrowser1.Document.GetElementById;
    @id("srchbtn").Click += (t, a) => { MessageBox.Show("検索しましたね!"); };
    @id("srchtxt").KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };
    webBrowser1.DocumentCompleted -= action;  // 一度呼ばれたら直ちに解除
  };
  webBrowser1.DocumentCompleted += action;
}

上記の@idのidで判定している部分をnameで判定するにはどのように書いたらよいでしょうか?


Func<string, HtmlElementCollection> @name = webBrowser1.Document.GetElementsByTagName;
@name("p").KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };

だと、KeyPressがないと言われてしまいました。



引用返信 編集キー/
■72959 / inTopicNo.15)  Re[9]: エンターを押せないようにする
□投稿者/ 魔界の仮面弁士 (72回)-(2014/08/04(Mon) 19:52:59)
No72958 (よしむら さん) に返信
> 上記の@idのidで判定している部分をnameで判定するには

id 属性は、HTMLページ内で重複しませんが、
name 属性は、同じ値が複数個所で使われる可能性があります。


だからこそ、
 IHTMLDocument3.getElementById メソッド
 HtmlDocument.GetElementById メソッド
などは、単数形の「Element」の名を冠しており、
 IHTMLDocument3.getElementsByName メソッド
などは、複数形の「Elements」なわけですね。


「複数形」なのは、IHTMLDocument3.getElementsByTagName や
HtmlDocument.GetElementsByTagName も同様なので、提示された
> Func<string, HtmlElementCollection> @name = webBrowser1.Document.GetElementsByTagName;
> @name("p").KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };
の書き方をするなら、
 @name("p")[位置番号].KeyPress += (t, a) => { /***/ };
のように、どの <p> タグなのかを特定しないといけません。



http://www.goo.ne.jp/ をお題としてサンプル化してみました。
今回の処理対象は以下のタグです。(今回は id 属性は使いませんが)
 <input type="text" id="searchtop" name="MT">
 <input type="submit" id="hd-s-1" name="bt_search">


★案1:.Document.All で全列挙し、そこから名前が一致するものを捜索

private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.goo.ne.jp/");
  WebBrowserDocumentCompletedEventHandler action = null;
  Func<string, HtmlElement> @name = delegate(string n)
  {
    // 今回は、LINQ で問い合わせてみた
    return webBrowser1.Document.All.OfType<HtmlElement>().Where(tag => tag.Name == n).FirstOrDefault();
  };
  action = (wb, args) =>
  {
    @name("bt_search").Click += delegate { MessageBox.Show("検索しましたね!"); };
    @name("MT").KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };
    webBrowser1.DocumentCompleted -= action;
  };
  webBrowser1.DocumentCompleted += action;
}



★案2:タグ名で絞り込んでから、さらに name 属性で探す

public IEnumerable<HtmlElement> GetTags(string tagName, string name)
{
  // 今回は反復子を使ってみた
  foreach (HtmlElement tag in webBrowser1.Document.GetElementsByTagName(tagName))
  {
    if (tag.Name == name) yield return tag;
  }
}

private void button1_Click(object sender, EventArgs e)
{
  webBrowser1.Navigate("http://www.goo.ne.jp/");
  WebBrowserDocumentCompletedEventHandler action = null;
  action = (wb, args) =>
  {
    GetTags("input", "bt_search").First().Click += delegate { MessageBox.Show("検索しましたね!"); };
    GetTags("input", "MT").First().KeyPress += (t, a) => { a.ReturnValue = a.KeyPressedCode != 13; };
    webBrowser1.DocumentCompleted -= action;  // 一度呼ばれたら直ちに解除
  };
  webBrowser1.DocumentCompleted += action;
}
引用返信 編集キー/
■72960 / inTopicNo.16)  Re[10]: エンターを押せないようにする
□投稿者/ Atata!! (3回)-(2014/08/05(Tue) 00:51:28)
Atata!!です。横槍失礼。

IMessageFilterを使って WM_KEYDOWN イベントを無視すると言うのはどうでしょうか?
要件を満たすのに完璧なコードではありませんが、以下に示す例でEnterキーは無視できます。

    public partial class Form1 : Form, IMessageFilter
    {
        public Form1()
        {
            InitializeComponent();

            Application.AddMessageFilter(this);
        }

        bool IMessageFilter.PreFilterMessage(ref Message m)
        {
            const int WM_KEYDOWN = 0x0100;
            if (m.Msg == WM_KEYDOWN && m.WParam.ToInt32() == (int)Keys.Enter)
            {
                return true;
            }
            return false;
        }
    }

# SetClientSiteしてごにょごにょするやり方も思いつきましたが、
# サンプル作成と検証がめんどくさいのでやめました。

引用返信 編集キー/
■72992 / inTopicNo.17)  Re[10]: エンターを押せないようにする
□投稿者/ よしむら (39回)-(2014/08/07(Thu) 19:11:54)
No72959 (魔界の仮面弁士 さん) に返信

案位1で行けました。
ありがとうございました。
解決済み
引用返信 編集キー/
■72993 / inTopicNo.18)  Re[11]: エンターを押せないようにする
□投稿者/ よしむら (40回)-(2014/08/07(Thu) 19:13:15)
No72960 (Atata!! さん) に返信

かなり魅力的な方法だったのですが、IMessageFilterをうまく取り扱うことができませんでした。
時間をかけて勉強していきたいと思います。ありがとうございます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -