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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

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

Q&A

解決済

3回答

2084閲覧

対象のウィンドウハンドルの特定

bangdoll1002

総合スコア5

C#

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

1グッド

0クリップ

投稿2020/04/09 05:44

編集2020/04/20 09:26

以下サイトにあるのをメモ帳以外で行いたいです。
http://junko036.html.xdomain.jp/reference/code002.html

例えば、ワードやエクセルの編集部分に送信したいです。

どうしたら、編集部分に文字を送れるかを教えていただけませんか?

※ワードやエクセルの親ハンドルの特定はできています。
SPY+++を使用して

====================
申し訳ございません
個々に返信はできていませんが、

やりたいことは、以下のソフトの登録文字の機能の部分です。
これをどうやっているのかを知りたいです。

‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
文字入力支援君
https://www.vector.co.jp/magazine/softnews/090331/n0903313.html

「登録文字」では、あらかじめ「登録語(文字列)」とその「見出し語」を登録する。リストには登録語ではなく、登録した見出し語が表示され、見出し語をクリックすると、指定したカーソル位置に登録語が貼り付けられる仕組み。
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

TN8001👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2020/04/09 06:25

特定できてるなら同じようにすればいいんじゃないですか?
bangdoll1002

2020/04/09 07:15

メモ帳のハンドルは単純でしたので、編集部分が特定が簡単でしたが、 ワードやエクセルは、配下にあるハンドルを固定値としていれても、編集部分に送信されないのです もしかすると、ハンドル以外で特定する必要があるのかもしれません
Zuishin

2020/04/09 07:32

ハンドルは固定値ではありません。引用先のリンクでもその都度ハンドルを求めています。
bangdoll1002

2020/04/09 07:35

誤解をさせても申し訳ございません。 確かに固定値ではないです。 SPY+++で確認できたハンドル値をいれて行っています。 例えば、メモ帳は編集部分がわかっているので、その値をいれて確認しています。
Zuishin

2020/04/09 07:37

親ウィンドウに送ってみましたか?
Zuishin

2020/04/09 07:38

その際、編集部分にフォーカスがあってキャレットが点滅しているかどうか確認してください。
Zuishin

2020/04/20 09:34

> やりたいことは、以下のソフトの登録文字の機能の部分です。 > これをどうやっているのかを知りたいです。 なぜそれを作者に聞かずこんなところで聞くんでしょうか。 ソース公開されてないでしょ? そのソフトを使ったことがなければどんな機能かすらわからないでしょ? 同じ機能を実装したいなら、作者に聞いてください。 質問が変わったので、ヒントだけ残しておきますから自分で調べてください。 アクセシビリティ
TN8001

2020/04/20 11:00

ソフトを試してみましたが任意のEDITに文字を送るわけではなく、もともとキーボードフォーカスがあったところに送るんですね。 であるならターゲットアプリがアクティブになればキーボードフォーカスも復元するので、単に`SendInput`でいいんじゃないですか? アクティブ化の際に`AttachThreadInput`がいるのであれば、ついでに`GetFocus`してもいいでしょうけど。
guest

回答3

0

ベストアンサー

「文字入力支援君」はradianさんの言うようにおそらく、

  1. 対象アプリをアクティブ化
  2. クリップボードに文字をコピー
  3. Ctrl+Vを送る

という動作をしています。

対象アプリがアクティブ化したときにカーソルがない(ボタン等にフォーカスがある)と貼り付けられないので、特に入力エリアを探したりはしていなそうです(特定アプリに特別対応があるかもしれませんが)

最低限動作確認できるサンプルを作りました。

使い方
  1. 支援君のようにピンクの四角を対象アプリにドラッグ&ドロップ
  2. テキストボックスに何か入力
  3. 貼り付けボタンを押す
注意
  • エラーチェック一切なし
  • Word・Excelは手元にないので未確認

cs:Form1.cs

1using System; 2using System.Drawing; 3using System.Runtime.InteropServices; 4using System.Text; 5using System.Windows.Forms; 6 7namespace Questions252432 8{ 9 public partial class Form1 : Form 10 { 11 private IntPtr hWnd; 12 13 public Form1() => InitializeComponent(); 14 15 private void Panel1_MouseDown(object sender, MouseEventArgs e) 16 { 17 if(e.Button == MouseButtons.Left) panel1.Capture = true; 18 } 19 20 private void Panel1_MouseUp(object sender, MouseEventArgs e) 21 { 22 panel1.Capture = false; 23 var p = NativeMethods.GetCursorPos(); 24 var h = NativeMethods.WindowFromPoint(p); 25 hWnd = NativeMethods.GetAncestor(h); 26 27 label_title.Text = $"Title: {NativeMethods.GetWindowText(hWnd)}"; 28 label_class.Text = $"Class: {NativeMethods.GetClassName(hWnd)}"; 29 } 30 31 private void Button1_Click(object sender, EventArgs e) 32 { 33 Clipboard.SetText(textBox1.Text); 34 NativeMethods.SetForegroundWindow(hWnd); 35 SendKeys.Send("^v"); 36 } 37 38 private static class NativeMethods 39 { 40 [DllImport("user32")] 41 private static extern bool GetCursorPos(out Point pPoint); 42 public static Point GetCursorPos() 43 { 44 GetCursorPos(out var p); 45 return p; 46 } 47 48 [DllImport("user32")] 49 public static extern IntPtr WindowFromPoint(Point point); 50 51 [DllImport("user32")] 52 private static extern IntPtr GetAncestor(IntPtr hWnd, uint gaFlags); 53 public static IntPtr GetAncestor(IntPtr hWnd) => GetAncestor(hWnd, GA_ROOTOWNER); 54 private const uint GA_ROOTOWNER = 3; 55 56 [DllImport("user32", CharSet = CharSet.Unicode)] 57 private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); 58 public static string GetWindowText(IntPtr hWnd) 59 { 60 var sb = new StringBuilder(100); 61 GetWindowText(hWnd, sb, sb.Capacity); 62 return sb.ToString(); 63 } 64 65 [DllImport("user32", CharSet = CharSet.Unicode)] 66 private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 67 public static string GetClassName(IntPtr hWnd) 68 { 69 var sb = new StringBuilder(100); 70 GetClassName(hWnd, sb, sb.Capacity); 71 return sb.ToString(); 72 } 73 74 [DllImport("user32")] 75 public static extern bool SetForegroundWindow(IntPtr hWnd); 76 } 77 } 78}

cs:Form1.Designer.cs

1namespace Questions252432 2{ 3 partial class Form1 4 { 5 /// <summary> 6 /// 必要なデザイナー変数です。 7 /// </summary> 8 private System.ComponentModel.IContainer components = null; 9 10 /// <summary> 11 /// 使用中のリソースをすべてクリーンアップします。 12 /// </summary> 13 /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param> 14 protected override void Dispose(bool disposing) 15 { 16 if(disposing && (components != null)) 17 { 18 components.Dispose(); 19 } 20 base.Dispose(disposing); 21 } 22 23 #region Windows フォーム デザイナーで生成されたコード 24 25 /// <summary> 26 /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 27 /// コード エディターで変更しないでください。 28 /// </summary> 29 private void InitializeComponent() 30 { 31 this.button1 = new System.Windows.Forms.Button(); 32 this.label_title = new System.Windows.Forms.Label(); 33 this.label_class = new System.Windows.Forms.Label(); 34 this.textBox1 = new System.Windows.Forms.TextBox(); 35 this.panel1 = new System.Windows.Forms.Panel(); 36 this.SuspendLayout(); 37 // 38 // button1 39 // 40 this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 41 this.button1.Location = new System.Drawing.Point(297, 222); 42 this.button1.Name = "button1"; 43 this.button1.Size = new System.Drawing.Size(75, 23); 44 this.button1.TabIndex = 0; 45 this.button1.Text = "貼り付け"; 46 this.button1.UseVisualStyleBackColor = true; 47 this.button1.Click += new System.EventHandler(this.Button1_Click); 48 // 49 // label_title 50 // 51 this.label_title.AutoSize = true; 52 this.label_title.Location = new System.Drawing.Point(54, 16); 53 this.label_title.Name = "label_title"; 54 this.label_title.Size = new System.Drawing.Size(30, 12); 55 this.label_title.TabIndex = 1; 56 this.label_title.Text = "Title:"; 57 // 58 // label_class 59 // 60 this.label_class.AutoSize = true; 61 this.label_class.Location = new System.Drawing.Point(54, 31); 62 this.label_class.Name = "label_class"; 63 this.label_class.Size = new System.Drawing.Size(36, 12); 64 this.label_class.TabIndex = 2; 65 this.label_class.Text = "Class:"; 66 // 67 // textBox1 68 // 69 this.textBox1.AcceptsReturn = true; 70 this.textBox1.AcceptsTab = true; 71 this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 72 | System.Windows.Forms.AnchorStyles.Left) 73 | System.Windows.Forms.AnchorStyles.Right))); 74 this.textBox1.Location = new System.Drawing.Point(12, 54); 75 this.textBox1.Multiline = true; 76 this.textBox1.Name = "textBox1"; 77 this.textBox1.Size = new System.Drawing.Size(360, 162); 78 this.textBox1.TabIndex = 3; 79 // 80 // panel1 81 // 82 this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(128))))); 83 this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 84 this.panel1.Cursor = System.Windows.Forms.Cursors.Cross; 85 this.panel1.Location = new System.Drawing.Point(12, 12); 86 this.panel1.Name = "panel1"; 87 this.panel1.Size = new System.Drawing.Size(36, 36); 88 this.panel1.TabIndex = 4; 89 this.panel1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Panel1_MouseDown); 90 this.panel1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Panel1_MouseUp); 91 // 92 // Form1 93 // 94 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 95 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 96 this.ClientSize = new System.Drawing.Size(384, 257); 97 this.Controls.Add(this.panel1); 98 this.Controls.Add(this.textBox1); 99 this.Controls.Add(this.label_class); 100 this.Controls.Add(this.label_title); 101 this.Controls.Add(this.button1); 102 this.Name = "Form1"; 103 this.Text = "貼り付けくん"; 104 this.ResumeLayout(false); 105 this.PerformLayout(); 106 107 } 108 109 #endregion 110 111 private System.Windows.Forms.Button button1; 112 private System.Windows.Forms.Label label_title; 113 private System.Windows.Forms.Label label_class; 114 private System.Windows.Forms.TextBox textBox1; 115 private System.Windows.Forms.Panel panel1; 116 } 117}

アプリ画像


SendKeysは(SendInputも)文字列自体を送ることもできますが、明らかに遅いのと改行がアプリによってうまくいかない等なかなか難しいです。

クリップボードが汚れるのを許容できるなら、この方式のほうがいいと思います。

投稿2020/04/20 23:03

編集2023/07/21 10:32
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bangdoll1002

2020/04/21 02:10

ありがとうございます。 試してみます。
bangdoll1002

2020/04/30 01:27

試してみました。 やりたいことができましたので、ベストアンサーとさせていただきました。 感謝です!!!!!
guest

0

メモ帳のような単純なアプリケーションと違って、
複雑な構造のアプリケーションをメモ帳と同様に
ウィンドウメッセージで同様に制御出来るとは考えない方が良いです。
・子ウィンドウを複数持ち、階層構造になっている
(バージョンが変わったりしたら構造が変わる可能性もある)
・WM_CHARのような一般的なウィンドウメッセージを使用していない
・そもそもウィンドウハンドルを持っていない(WPFアプリのコントロールなど)
など、いろいろなパターンが考えられます。
汎用的な方法はありません。

間接的な方法だと、アクティブなウィンドウにSendInput APIでキー操作を送信するみたいなのは出来る
かもしれませんが、特定の編集部分に確実に送る、というのは難しいと思います。
単純な方法だと、クリップボードにデータをコピー⇒CTRL+Vを送信みたいなのが考えられますね。
あと、Excelのウィンドウが二つ立ち上がって居たりしたらどうします?

投稿2020/04/09 15:35

編集2020/04/10 02:44
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

どうしたら、編集部分に文字を送れるかを教えていただけませんか?

ウィンドウハンドルを直接操作するようなプログラムは、ちゃんと動作するものを作るのが簡単ではありませんので、あまりおすすめしません。

Word や Excel が対象でしたら、専用のライブラリ(「Open XML SDK」「NPOI」など )がありますので、そちらを使うのが良いと思います。

投稿2020/04/09 10:17

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問