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

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

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

dataGridViewの編集中コンテキストからの貼付につい

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

■96720 / inTopicNo.1)  dataGridViewの編集中コンテキストからの貼付につい
  
□投稿者/ かつお (4回)-(2021/01/15(Fri) 13:07:12)

分類:[C#] 

開発環境:vs 2019 community
使用言語:C♯ .net framework 4.5
質問内容:dataGridViewでセル編集中に右クリックから貼付で、半角数字以外の文字が入らないよう制御したいです。普通のテキストボックスであれば、派生クラス作ってWndProcで貼付メッセージを取得した後の処理加えることは出来ましたが、dataGridViewの編集時に生成されるテキストボックスに対し、派生クラスみたいに追加する方法が分からず、単純にWndProcでメッセージを取ってくる方法が分からず困っております。貼付アクションによるイベント取得も見つけることが出来ませんでした。

引用返信 編集キー/
■96722 / inTopicNo.2)  Re[1]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ ニケ (9回)-(2021/01/15(Fri) 14:07:53)
No96720 (かつお さん) に返信
とりあえず、DataGridViewTextBoxEditingControl になりますが、
それが分かっているのかどうかから読み取れませんでした。
TextBox が取得できれば後は出来そうですか?

【DOBON.NET DataGridViewでセルの編集に使われているテキストボックスを取得する】
https://dobon.net/vb/dotnet/datagridview/editingcontrol.html

引用返信 編集キー/
■96723 / inTopicNo.3)  Re[2]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ かつお (5回)-(2021/01/15(Fri) 14:24:12)
No96722 (ニケ さん) に返信
> ■No96720 (かつお さん) に返信
> とりあえず、DataGridViewTextBoxEditingControl になりますが、
> それが分かっているのかどうかから読み取れませんでした。
> TextBox が取得できれば後は出来そうですか?
>
> 【DOBON.NET DataGridViewでセルの編集に使われているテキストボックスを取得する】
> https://dobon.net/vb/dotnet/datagridview/editingcontrol.html
>

ニケさん
早速のご返信ありがとうございます。
記載不足で申し訳ございません。
DataGridViewTextBoxEditingControlは少しながら認識しており、数字以外の文字を打たせない為、キープレスイベント追加することは出来ます。
しかしながら、貼付を感知するイベント自体が分からないのと、イベントの代わりとしてWndProcでメッセージ取る方法は他のサイトを見る限り派生クラス前提の様です。イベントハンドラーのようなプログラムを走らせる所迄動かせれば、後は出来そうです。

引用返信 編集キー/
■96724 / inTopicNo.4)  Re[3]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ 魔界の仮面弁士 (2953回)-(2021/01/15(Fri) 16:00:08)
2021/01/15(Fri) 16:08:38 編集(投稿者)

No96723 (かつお さん) に返信
> イベントの代わりとしてWndProcでメッセージ取る方法は他のサイトを見る限り派生クラス前提の様です。

NativeWindow クラスの AssignHandle / WndProc メソッドはどうでしょうか。
引用返信 編集キー/
■96733 / inTopicNo.5)  Re[3]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ 大谷刑部 (122回)-(2021/01/18(Mon) 14:15:35)
No96723 (かつお さん) に返信
> DataGridViewTextBoxEditingControlは少しながら認識しており、数字以外の文字を打たせない為、キープレスイベント追加することは出来ます。
> しかしながら、貼付を感知するイベント自体が分からないのと、イベントの代わりとしてWndProcでメッセージ取る方法は他のサイトを見る限り派生クラス前提の様です。イベントハンドラーのようなプログラムを走らせる所迄動かせれば、後は出来そうです。

質問の文面にあるように、右クリックメニューコピー→貼り付け、[Ctrl]+C→[Ctrl]+Vを許容しつつ、コピペの数字以外を無効にするのは手軽には多分難しいですね。
要求仕様的に可能かはわかりませんが、私は大概、現場の開発で「数字のみ入力」とある場合は右クリメニューをForm_Load等で当該コントロールに関して無効(コーディング的には初期化)にして、ダメなら、[Ctrl]+C→[Ctrl]+Vも(キープレス等で)無効にしてしまいます。(プラスMaxllengthも設定)
そうすれば型チェックとけたチェックは不要になりますし、短い文字数の入力エリアならさほど不便でもないと思います。(多少ユーザーの主観にもよりますが)

当該項目でコピペを許容するのは仕様的に必須なのでしょうか?
引用返信 編集キー/
■96736 / inTopicNo.6)  Re[4]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ かつお (6回)-(2021/01/19(Tue) 10:22:58)
No96733 (大谷刑部 さん) に返信
> ■No96723 (かつお さん) に返信
>>DataGridViewTextBoxEditingControlは少しながら認識しており、数字以外の文字を打たせない為、キープレスイベント追加することは出来ます。
>>しかしながら、貼付を感知するイベント自体が分からないのと、イベントの代わりとしてWndProcでメッセージ取る方法は他のサイトを見る限り派生クラス前提の様です。イベントハンドラーのようなプログラムを走らせる所迄動かせれば、後は出来そうです。
>
> 質問の文面にあるように、右クリックメニューコピー→貼り付け、[Ctrl]+C→[Ctrl]+Vを許容しつつ、コピペの数字以外を無効にするのは手軽には多分難しいですね。
> 要求仕様的に可能かはわかりませんが、私は大概、現場の開発で「数字のみ入力」とある場合は右クリメニューをForm_Load等で当該コントロールに関して無効(コーディング的には初期化)にして、ダメなら、[Ctrl]+C→[Ctrl]+Vも(キープレス等で)無効にしてしまいます。(プラスMaxllengthも設定)
> そうすれば型チェックとけたチェックは不要になりますし、短い文字数の入力エリアならさほど不便でもないと思います。(多少ユーザーの主観にもよりますが)
>
> 当該項目でコピペを許容するのは仕様的に必須なのでしょうか?

魔界の仮面弁士さん
大谷刑部 さん
さっそくの丁重なご返信、誠にありがとうございます。
「NativeWindow クラスの AssignHandle / WndProc」については、勉強不足すぎて、どういう風にコード書くべきかイメージできず模索中でございます。
「当該項目でコピペを許容するのは仕様的に必須」について、長い半角数字を入力する為、貼付行為が無いと厳しく、かといって許容できない文字が含まれることを阻止したく考えております。一応キー入力については、制御入れており、keypressのイベントハンドラで[Ctrl]+V押された際、クリップボードの中身を確認し、全角あれば半角へ変換して張り付くように改良できました。ただ、利用者がCtrl+Vを知っている方も少なくなく、貼付行為が右クリックからの貼付位しか知らない人も対象にメッセージ抜き取れればと思っております。
面倒な相談で大変恐縮ですが、何とぞよろしくお願いいたします。
引用返信 編集キー/
■96737 / inTopicNo.7)  Re[5]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ 大谷刑部 (123回)-(2021/01/19(Tue) 11:30:43)
No96736 (かつお さん) に返信
> 「当該項目でコピペを許容するのは仕様的に必須」について、長い半角数字を入力する為、貼付行為が無いと厳しく、かといって許容できない文字が含まれることを阻止したく考えております。一応キー入力については、制御入れており、keypressのイベントハンドラで[Ctrl]+V押された際、クリップボードの中身を確認し、全角あれば半角へ変換して張り付くように改良できました。ただ、利用者がCtrl+Vを知っている方も少なくなく、貼付行為が右クリックからの貼付位しか知らない人も対象にメッセージ抜き取れればと思っております。

なるほど。「長い」がどれくらいに該当するかはわかりませんが少なくとも年とか月みたいにコピペできなくてもさほど不便さを感じない文字数ではないのですね。
Ctrl+Vが実装できてるなら、該当する列に関して、ContextMenuStripコントロールを割り当ててあげて、そのメニューに「貼り付け」を設定してContextMenuStripのクリックイベントで「貼り付け」メニューが選択された時(if文で書けるはず)に、
Ctrl+Vと同じロジックを実装してあげれば、やりたいことの半分はできると思います。
なぜ半分かというと、あくまでセル選択状態の時しか挙動しないので、グリッド内テキストボックスの編集中には上記のイベントは挙動しません。
引用返信 編集キー/
■96738 / inTopicNo.8)  Re[5]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ 魔界の仮面弁士 (2954回)-(2021/01/19(Tue) 13:37:55)
No96736 (かつお さん) に返信
> keypressのイベントハンドラで[Ctrl]+V押された際、

音声文字入力 / 手書き文字認識入力からのテキスト入力
キーボードの [Shift]+[Insert] での直接貼り付け
キーボードの [Shift]+[F10] での貼り付けメニュー
キーボードの [Application] からの貼り付けメニュー
スタイラスのジェスチャーによる直接貼り付け
タッチパッドの指2本タップからの貼り付けメニュー
タッチパネルの長押しからの貼り付けメニュー


> 「NativeWindow クラスの AssignHandle / WndProc」については、勉強不足すぎて、どういう風にコード書くべきかイメージできず模索中でございます。
こんな感じ。

using System;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
 public partial class Form1 : Form
 {
  private DataGridView dgv;
  private EditorHook hook = null;
  public Form1()
  {
   InitializeComponent();
   Controls.Add(dgv = new DataGridView { Name = "dgv" });
   dgv.Dock = DockStyle.Fill;
   dgv.RowCount = 100;
   dgv.ColumnCount = 8;
   dgv.EditMode = DataGridViewEditMode.EditOnEnter;
   dgv.EditingControlShowing += Dgv_EditingControlShowing;
  }

  private void Dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
  {
   if (hook != null)
   {
    hook.ReleaseHandle();
    hook = null;
   }
   var txt = e.Control as TextBoxBase;
   if (txt != null)
   {
    hook = new EditorHook(txt);
   }
  }

  private class EditorHook : NativeWindow
  {
   private const int WM_PASTE = 0x302;
   private TextBoxBase txt;
   public EditorHook(TextBoxBase control)
   {
    AssignHandle((txt = control).Handle);
   }
   protected override void WndProc(ref Message m)
   {
    Console.WriteLine(m.ToString());
    if (m.Msg == WM_PASTE)
    {
     txt.SelectedText = GetNarrowNumbers();
     m.Result = new IntPtr(1);
    }
    else
    {
     base.WndProc(ref m);
    }
   }

   private string GetNarrowNumbers()
   {
    var rawText = Clipboard.GetText();
    var replaced = Regex.Replace(rawText, "[0-9]", p => ((char)(p.Value[0] - '0' + '0')).ToString());
    var filtered = replaced.Where("0123456789".Contains);
    return new string(filtered.ToArray());
   }
  }
 }
}
引用返信 編集キー/
■96741 / inTopicNo.9)  Re[6]: dataGridViewの編集中コンテキストからの貼付につい
□投稿者/ かつお (7回)-(2021/01/21(Thu) 11:59:22)
魔界の仮面弁士さん
大谷刑部 さん
反応が遅くなってしまい申し訳ございませんでしたが、早速のご支援ありがとうございます。


ご記載いただいた助言内容を頭で整理しながら、コードをF11で走らせ意味理解でき、無事実装・
解決することができました。
また、NativeWindowを他のことでも流用できそうなので、これから沢山活用をさせていただき
ますので、心から感謝申し上げます。


解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ