今だけ人気マンガ100円レンタル特集♪

他のアプリケーションのテキストフィールドがフォーカスを持っていて、そこにテンキーの「1」を入力した場合、「おはよう」と表示され、さらに改行コードも送れるプログラムを作りたいと思っています。

ヒントが掲載されているHPや書籍などの情報があれば教えていただきたいと思います。 また、お手数でなければ、具体的なコードも教えていただければありがたいです。

開発環境は VB6、OSはXP ProSP2 です。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

キーフックを使って作るのが王道のようですが、


どうもややこしそうなので思いついたソースだけ記述します。
質問者さんの思っている動きとは違うかもしれませんが、、。

以下ソースをVBで実行後、
Windows標準のメモ帳を起動し1を入力してみてください

'--------------以下貼り付けてください-----------------
Private Declare Function FindWindowA Lib "user32" (ByVal cnm As String, ByVal cap As String) As Long
Private Declare Function FindWindowExA Lib "user32" (ByVal hpar As Long, ByVal hchi As Long, ByVal cnm As String, ByVal cap As String) As Long
Private Declare Function SendMessageA Lib "user32" (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, ByVal lParam As Any) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Const WM_GETTEXT = &HD
Const WM_SETTEXT = &HC

Private Sub Form_Load()

Dim hwd As Long, hwd_c As Long
Dim cap As String, ret As Long

cap = Space$(200)

Do

'メモ帳のハンドル取得
hwd = FindWindowA(vbNullString, "無題 - メモ帳")

'メモ帳のテキストハンドル取得
hwd_c = FindWindowExA(hwd, 0, "Edit", "")

'メモ帳のテキストを取得
ret = SendMessageA(hwd_c, WM_GETTEXT, 200, cap)

'メモ帳のテキストを検索
If InStr(1, cap, "1", vbTextCompare) > 0 Then
'1が入力されているなら置き換えて送信
Call SendMessageA(hwd_c, WM_SETTEXT, 0, "おはよう" & vbCrLf)
End If

DoEvents
Sleep (1000)

Loop

End Sub
'---------------------------------------------

'以下参考にしたURLです
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd …
http://hpcgi1.nifty.com/MADIA/VBBBS/wwwlng.cgi?p …
    • good
    • 0
この回答へのお礼

早速のお返事とコードありがとうございます。
なんとなく、わかったような気がしました。

参考URLも使っていろいろ研究してみたいと思います。

お礼日時:2007/06/02 10:41

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q他のアプリケーションとの連携

 VBを使って他の既存のソフトなどへ何らかの命令をかけることは可能でしょうか?
 
 具体的には起動中のほかのアプリケーションへキー操作をさせる…というようなことは可能でしょうか?

 たとえば、コマンドを設置しておいて、そのコマンドをクリックすると起動中の別のアプリケーション上でEnterキーを押した状態を引き起こさせるというようなことです。
 
 また、それとは逆に他のアプリケーションを監視して、キーが押されたときに反応させるというようなことは可能でしょうか?

 API関数等を使用するのでしたらどういう関数を使用すればよいか教えてください。
 よろしくお願いします。

Aベストアンサー

># 反論~にどうぞ。
(゜ .゜)ノ カンシャ デス
真意をわかっていただいて、うれしいです。^^


サンプルです。

このサンプルを実行するには二つのプロジェクトが必要となります。

Project1
└Form1
  ├Command1
  └Command2
'Form1の中身
Option Explicit

Private Sub Command1_Click()
  MsgBox 1
End Sub

Private Sub Command2_Click()
  MsgBox 2
End Sub
と記載して、ボタンが押されたらメッセージボックスを表示するようにしておきます。
これをEXEにして起動しておいてください。



Project2
└標準モジュール
'標準モジュールの中身
Option Explicit

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_COMMAND = &H111
Private Const BN_CLICKED = &H0&

Sub Main()
  Dim lngWindWnd As Long 'ウィンドウハンドル
  Dim lngBtnWnd1 As Long '最初に見つかったボタン
  Dim lngBtnWnd2 As Long '2番目に見つかったボタン
  
  
  'アプリケーションタイトルより、ウィンドウハンドル得ます
  lngWindWnd = FindWindow(vbNullString, "Form1")
  
  
  '指定のウィンドウハンドル内の、最初に見つかったクラス名[ThunderRT6CommandButton](VB6で作成したコマンドボタン)のハンドルを得ます
  '【注意:2番目の引数が0(Nullポインタ)のとき、最初に見つかったものを返すように指定している】
  lngBtnWnd1 = FindWindowEx(lngWindWnd, 0, "ThunderRT6CommandButton", vbNullString)
  Call SendMessage(lngWindWnd, WM_COMMAND, BN_CLICKED, ByVal lngBtnWnd1)
  
  
  '指定のウィンドウハンドル内の、2番目に見つかったクラス名[ThunderRT6CommandButton](VB6で作成したコマンドボタン)のハンドルを得ます
  '【注意:2番目の引数が0以外(Nullポインタではない)とき、2番目のパラメータ以降に見つかったハンドルを返すように指定している】
  lngBtnWnd2 = FindWindowEx(lngWindWnd, lngBtnWnd1, "ThunderRT6CommandButton", vbNullString)
  Call SendMessage(lngWindWnd, WM_COMMAND, BN_CLICKED, ByVal lngBtnWnd2)
End Sub




といった感じです。
一番最初にサンプルを載せたかったのですが、ちょっと納期前ということで、説明を簡略化してしまいました。


>一文字(Enterキー)を渡すだけならSendKeysでも問題はないかな..
たしかにそうですね。。。
話を戻しますが、#3で書いた電子電○帳と連携したソフトですが、目的のボタンにたどりつくために、[TAB]を数回送った後に[ENTER]を送っていました。最初から目的のボタンにフォーカスがあるのであれば、全然問題ないのですが、、、

なので、処理によってはSendkeysで十分だと思いますが、2回以上のSendkeysが連続するようなのであれば、OSの状況に影響されないAPIを使うことをお奨めします。

># 反論~にどうぞ。
(゜ .゜)ノ カンシャ デス
真意をわかっていただいて、うれしいです。^^


サンプルです。

このサンプルを実行するには二つのプロジェクトが必要となります。

Project1
└Form1
  ├Command1
  └Command2
'Form1の中身
Option Explicit

Private Sub Command1_Click()
  MsgBox 1
End Sub

Private Sub Command2_Click()
  MsgBox 2
End Sub
と記載して、ボタンが押されたらメッセージボックスを表示するようにしておきます。
これをEXEにして起動しておい...続きを読む

QEXCEL VBAから他アプリケーションを操作することは可能ですか?

こんばんは。

VBAの本を購入し勉強していますが、VBAと他アプリケーションとの連携について記載が少なく(txtやcsvファイル操作)、どこまで出来るんだろうという不安があり質問しました。

(1)EXCEL VBAから他アプリケーションを起動し、設定操作、命令を送り操作することは可能でしょうか?
イメージとしては他アプリに一方的に命令を送り操作できれば良しです。(アプリ側からのリターン要求はしません。)

(2)第2の質問です。
VBAで他アプリを起動した状態で人が操作している感覚でマウスを操作できますか?(利用方法:他アプリの●ボタンを押したい!!)
目の前にソフトがあるのに触る操作は出来ないものでしょうか?
いろいろ調べて見ましたが、この様な事例はありません。
駄目元ですが、こんな操作を知っていましたら教えてください。
こんな操作ができればいいな~

Aベストアンサー

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  Dim rChange   As Range
  Dim sCommand  As String
  Dim sScriptFile As String

  ' // 実行する UWSC スクリプト
  sScriptFile = "C:\sample.uws"
  ' // UWSC の起動オプションは UWSC のヘルプを参照
  sCommand = DQ & EXE_PATHNAME & DQ & " " & _
        DQ & sScriptFile & DQ
  
  ' // 変更されたのが単一セルかつ A 列でなければ終了
  If Target.Cells.Count > 1 Then Exit Sub
  Set rChange = Intersect(Target, Columns("A"))
  If rChange Is Nothing Then
    Exit Sub
  End If
  
  ' // さらに値が TEST だった場合のみ実行
  If rChange.Value = "TEST" Then
    Shell sCommand, vbNormalFocus
  End If

End Sub

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  ...続きを読む

Q他のウィンドウのボタンを自動的に押したい

VisualC++で作ったアプリケーションから、例えばWindowsに標準搭載の「電卓アプリケーション」のウィンドウをアクティブにして、さらにその中の「1」ボタンを認識して押す、テキストボックスを認識してそこに文字列を入れるといったソフトを作りたいです。

簡単にいうと、他のアプリケーションを自動的に操作するソフトを作りたいのです。

これを実現するために、Web検索してみましたが、関連する技術の名前やMFCでのAPI名がわからないです。これはどういった名前の技術で、VisualC++でどういった名前の関数を使うのでしょうか?

当方の環境はWindowsXP&VisualC++6.0です。

以上、よろしくお願いします。

Aベストアンサー

★列挙方法のアドバイス
・補足になる仕様の
>(1)ウィンドウのタイトルバーの名前(例:「電卓」)、
>またはウィンドウのIDでウィンドウを探す
 ↑
 これなら FindWindow() 関数でウインドウ・ハンドルを探せます。
 例: HWND hWnd = FindWindow( "SciCalc", "電卓" );
>(2)最初にヒットしたウィンドウをアクティブにする
 ↑
 最初にヒットした hWnd を SetForegroundWindow() 関数でアクティブにします。
 例: SetForegroundWindow( hWnd );
>(3)アクティブにしたウィンドウの中にあるボタンを探す
 ↑
 (1)で取得しているウインドウに対して子ウインドウ(ボタンなど)を列挙します。
 列挙には EnumChildWindows() 関数と EnumChildProc() のコールバック関数を使います。
>(4)「1」のボタン、またはボタンのIDがヒットしたらそのボタンを押す
 ↑
 列挙のコールバック関数(EnumChildProc)でボタンのキャプションを調べて
 『1』となっている文字列が電卓の『1』ボタンです。
 このときにボタンを押す処理をプログラムから行います。
 例: SendMessage( hChild, BM_CLICK, 0, 0 );
 URL: http://wisdom.sakura.ne.jp/system/winapi/win32/win53.html
・上記のような感じで操作できます。
 一番重要なのは操作するウインドウのハンドルを正しく見つけ出すことです。
 このウインドウ・ハンドルを見つけるには次の方法があります。
 (1)FindWindow() 関数を使う
 (2)EnumWindows() 関数を使う
 (3)Process32First()、Process32Next() 関数を使う
 (4)EnumProcesses() 関数を使う
 などがあります。
 今回は簡単な(1)を紹介しました。
 もしもウインドウのクラス名やキャプション名以外で詳しく捜査対象の
 ウインドウを検索するには(2)の EnumWindows() 関数や起動パス名を
 調べて特定できる (3)、(4)の関数群を利用します。
>テキストの内容の認識や保存など色々な機能を盛り込んだソフトを作りたいからです。
 ↑
 ボタンなどのテキストを認識、保存には GetWindowText()、WM_GETTEXT メッセージを
 使います。メッセージの場合は SendMessage() 関数でキャプション文字列を取得します。
 例: SendMessage( hChild, WM_GETTEXT, sizeof(szBuff), szBuff );
・下に簡単なボタンの列挙を載せます。これを活用して下さい。

サンプル:
#include <stdio.h>
#include <windows.h>

// コールバック関数
BOOL CALLBACK EnumChildProc( HWND hWnd, LPARAM lParam )
{
 TCHAR szBuff[ 1024 ];
 
 // キャプションの取得
 GetWindowText( hWnd, szBuff, sizeof(szBuff) );
 printf( "├[%s]\n", szBuff );
 return TRUE;
}

// メイン関数
int main( void )
{
 HWND hCalc;
 
 if ( (hCalc = FindWindow("SciCalc","電卓")) != NULL ){
  printf( "◆電卓のコントロール列挙\n" );
  EnumChildWindows( hCalc, EnumChildProc, NULL );
 }
 return 0;
}
以上。

★列挙方法のアドバイス
・補足になる仕様の
>(1)ウィンドウのタイトルバーの名前(例:「電卓」)、
>またはウィンドウのIDでウィンドウを探す
 ↑
 これなら FindWindow() 関数でウインドウ・ハンドルを探せます。
 例: HWND hWnd = FindWindow( "SciCalc", "電卓" );
>(2)最初にヒットしたウィンドウをアクティブにする
 ↑
 最初にヒットした hWnd を SetForegroundWindow() 関数でアクティブにします。
 例: SetForegroundWindow( hWnd );
>(3)アクティブにしたウィンドウの中にあるボタンを...続きを読む

QExcelVBAでAPIを使って外部ウインドウのエディットテキストを取得する方法

●やりたいこと
ExcelVBAで、APIを実行し、外部ソフトのウィンドウに含まれている
エディットテキストを取得して、セルに出力したい

使用する関数・宣言、できればコードを教えていただけませんでしょうか。

イメージはこちらをご参考いただけると幸いです。
​http://situmon-img.blogspot.com/2008/08/1.html​

変数hwindowに親ウィンドウのハンドルが取得されています。
エディットボックスのハンドル、IDは分かりません。


エディットボックスのハンドルを取得し、
分かっているクラス・ハンドルの文字列を取得
といった流れになるのではと思っております。

変数にさえ文字列が取得できれば、
当然ですが、Range("B2")=変数 で大丈夫です。
変数は、ひとつを使いまわしで構いません。
変数をエディットテキストの数だけ用意しても構いません。

Aベストアンサー

あの QNo.4256138の質問でも、同じ様な事を質問されていたと思います。
出来たらそちらで質問された方がよかったのではと思います。

テキストボックスの取得も、私の回答した全く同じ方法で
取得出来ると思います。クラス名が Edit になるだけです。

 EnumChildWindows(hWnd,lpEnumFunc,0&) は、親ウィンドウに含まれる

子ウィンドウがすべて返ってきます。ボタンもテキストボックスも、その他の
子ウィンドウがすべて、何個あっても、取得できます。

ただ EnumChildWindows(hWnd,lpEnumFunc,0&) で与える子ウィンドウを
受け取る関数は、コールバック関数なので、1回のコールで1個の子ウィンドウ
しか返ってきません。ただ、子ウィンドウがある分だけ何度も同じ関数が
呼び出されます。よび出される度に

 GetClassName(hWnd,lpClassName,nMaxCount) でクラス名を取得し

クラス名が Edit ならテキストボックスになります。

SendMessage(テキストボックスハンドル, &HD, 240, ByVal cbuf)

で cbuf にテキストボックスの文字が取得出来ます。

尚、cbuf は文字長を多い目に事前に確保しておきましょう。

cbufのNULL値までが実際の文字となります。

また、コールバック関数はデバッグモードで、ブレークさすと、
フリーズするので注意して下さい。通常はデバッグしにくいので、
コールバック関数内では、配列変数にハンドルをためこんでいきます。
その後で、配列にためこんでいるハンドルを順番にクラス名を取得し
テキストがボタンか判断していきます。

あの QNo.4256138の質問でも、同じ様な事を質問されていたと思います。
出来たらそちらで質問された方がよかったのではと思います。

テキストボックスの取得も、私の回答した全く同じ方法で
取得出来ると思います。クラス名が Edit になるだけです。

 EnumChildWindows(hWnd,lpEnumFunc,0&) は、親ウィンドウに含まれる

子ウィンドウがすべて返ってきます。ボタンもテキストボックスも、その他の
子ウィンドウがすべて、何個あっても、取得できます。

ただ EnumChildWindows(hWnd,lpEnumFunc,0...続きを読む

Qc#で他のアプリの文字入力フォームに指定の文字を入力したい

例えばabc.exeというアプリがあったとします。
このアプリには文字列を入力するフォームがいくつかあり、
このアプリのフォームに文字を入れるプログラムを作成したいと思います。

まずはabc.exeをアクティブにし、
アプリのフォームの上から順に配列に代入された文字列の入力をしたいと思います。

つまり、
abc.exeの一番上のフォームにはmoji[0]にある文字列
二番目のフォームにはmoji[1]にある文字列
三番目のフォームにはmoji[2]にある文字列

という形です、こういったことは可能でしょうか?
SendKeys.SendWaitというのはこういうケースでも使えるのでしょうか?
もし可能であれば解説ページ、コードの例をご教示頂ければ幸いです。
よろしくお願いします。

Aベストアンサー

補足説明の方ありがとうございます。
かなり力技になってしまいますが・・・よければご参考までに

まず市販ソフトということなのでTabIndexが設定されてると思います。
そこで、Button押下後Tabキーと入力文字キーを送ってやります。
下記にサンプルを記述します。



using System.Runtime.InteropServices;

[DllImport("user32.dll")]
extern static IntPtr GetWindow(IntPtr hWnd, uint uCmd);

[DllImport("user32.dll")]
extern static IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
extern static int GetWindowText(IntPtr hWnd, StringBuilder lpStr, int nMaxCount);

[DllImport("user32.dll")]
extern static bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll")]
extern static bool SetForegroundWindow(IntPtr hWnd);


//ButtonClickイベント
const int GW_HWNDNEXT = 2;
StringBuilder sb = new StringBuilder(100);
IntPtr hwnd = GetForegroundWindow();
while (hwnd != IntPtr.Zero)
{
if (IsWindowVisible(hwnd))
{
GetWindowText(hwnd, sb, sb.Capacity); // タイトルバー文字列を取得
if (sb.ToString().IndexOf(textBox1.Text) != -1)
{

SetForegroundWindow(hwnd); // アクティブ

/***
*ここにSendKeys.SendWaitでキーを送ります。
*ラジオボタンがある場合Tabキーでラジオボタンをアクティブにし「↑」「↓」ボタンで変更
*チェックボックスの場合スペースキーでOnOff切り替え可能
*下記にキーコードが記述されています。
*MSDN SendKeys:http://msdn.microsoft.com/ja-jp/library/system.windows.forms.sendkeys(VS.80).aspx
*
*
***/


break;
}
}
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
}


この例ではTextBox1に別アプリケーションの名前の一部を入れることでアクティブにしています。
Ex)GoogleChrome → Google を入力し、Button1をクリックでGoogleChromeがアクティブになります。

力技すぎて汎用性も何もありませんが・・・ご参考までに

補足説明の方ありがとうございます。
かなり力技になってしまいますが・・・よければご参考までに

まず市販ソフトということなのでTabIndexが設定されてると思います。
そこで、Button押下後Tabキーと入力文字キーを送ってやります。
下記にサンプルを記述します。



using System.Runtime.InteropServices;

[DllImport("user32.dll")]
extern static IntPtr GetWindow(IntPtr hWnd, uint uCmd);

[DllImport("user32.dll")]
extern static IntPtr GetForegroundWindow...続きを読む

QVBAで既に開いている別アプリケーションのオブジェクトを得る

 VBAで別のアプリケーションにアクセスするには、CreateObject関数を使ってアプリケーションのオブジェクトを作るようにすると思います。例えば、ワード文書にアクセスするなら次の構文になると思います。
  Set appWord = CreateObject("Word.Application")
  appWord.Visible = True
 しかしこれだと新しいワード文書を作ったり、既存のワードファイルを開いて扱うことしかできません。GetObject関数を用いても同様のようです。既に別ウィンドウで開いているワード文書があって、そこへアクセスするにはどうしたらよいのでしょうか。
 また、同じアプリで複数のファイルを開いている場合には、どうやって目的のファイルへのオブジェクトを得るのでしょうか。(ファイル名などを参照して判断?)

Aベストアンサー

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Application")
For Each ObjWindow In ObjShell.Windows
If TypeName(ObjWindow.Document) = "HTMLDocument" Then
 WinExist = True
 Set ObjIE = ObjWindow
End If
Next
Set ObjShell = Nothing

If Not WinExist = True Then
Set ObjIE = CreateObject("InternetExplorer.Application")
End If

ObjIE.Navigate "http://nantokakantoka.html"
ObjIE.Visible = True


というような感じです。
Wordの場合はわからなくてすみません。
独学なのでもっといい方法があるかもしれないですが。

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Applicatio...続きを読む

QVB.NETのSendMessageを教えてください

SendMessageというAPIを試しているのですが、まず試しに
Button2.Text = "test"
と同じ結果をSendMessageでやってみたいのですが
下のようにしてみたのですが、変更になりませんでした。
どのようにすれば良いかご教授頂ければ幸いです。よろしくお願致します。

Private Declare Function SendMessage Lib "user32"
Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer

Private Const WM_SETTEXT As Integer = &HC

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim h As Integer
h = Me.Button2.Handle.ToInt32
SendMessage(h, WM_SETTEXT, 0&, "test")
End Sub

VB.NET2003
FrameWork1.1
WindowsXP-PRO(SP2)
です。

SendMessageというAPIを試しているのですが、まず試しに
Button2.Text = "test"
と同じ結果をSendMessageでやってみたいのですが
下のようにしてみたのですが、変更になりませんでした。
どのようにすれば良いかご教授頂ければ幸いです。よろしくお願致します。

Private Declare Function SendMessage Lib "user32"
Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer

Private Const WM_SETTEXT As Integer = &HC

...続きを読む

Aベストアンサー

ボタンの場合はうまく行かないようです

LabelやTextBoxやComboBoxなどはこの方法で変更出来るようです
ただし API呼び出しの後でコントロールのRefreshメソッドなどを呼び出して描画を更新しないといけないようです

CheckBox、RadioButton、Button、ListBoxは変更出来ませんでした

SendMessageのAPI宣言は
  Declare Ansi Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
      ByVal wParam As Integer, _
      <MarshalAsAttribute(UnmanagedType.AsAny)> ByVal lParam As Object) As Integer
といった具合の方がより実情に合うかと思います

QVBAでエクセル内の情報を他のアプリケーションへ自動入力したいです

業務効率を上げるために、VBAでエクセル内の情報を他のアプリケーションに自動入力させたいです。

入力する情報は、複数の項目があり、固定されています。
できれば、ワンクリックですべての入力フォームに自動入力させたいです。

これらのことは、VBAで実現可能なのでしょうか?
また、実現可能な場合、どのようにすればよろしいのでしょうか?

VBAを始めたばかりで何が出来て何が出来ないか、あまりわかっておりません。
VBAを習熟している方にとっては、簡単に質問であるかも知れませんが、どうぞご教授ください。

よろしくお願いいたします。

Aベストアンサー

下記で紹介されているシェアウェアを試されてはいかが?
http://okwave.jp/qa5392790.html
リンク先で、興味半分でWin32APIによる貼り付けにトライしてみましたが、同じテキストボックスに見えてもハンドル(Windowsがウィンドウやコントロールを識別する背番号の様なもの)が取得できるものと、出来ないものがあり、たとえばOKWaveのページを表示した状態で、上部のアドレス欄には貼り付けられますが、検索ボックスや、ログインのボックスには貼り付けられませんでした。ただ、IEや、MS Officeアプリケーションは、ActiveX Exeとして、独立して動作するだけでなく、他のプログラムから操作できる様に作られていますので、別の方法でVBAから操作できます。#1,#2の方が「他アプリケーションというだけでは分からない」とおっしゃっているのは、そのためです。

QVB.netでFindWindowExやると・・・9222812402616107008!?

VB.netでWin32APIのFindWindowExを使うと,
たとえばスタートボタンのHWNDを拾ってくるとき,
本当なら65662(6.0のSpy++で確認+10進変換)が返ってきて欲しいんですが,
9222812402616107008という,異常な数が返ってきます.

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz2 As String) As Long
とやってあります.
VB6.0のAPIビューワからコピペして,MarshalAsをつけてみました. 
 (初心者なので,わけわからないまま付けましたけど;

hWnd_ShellTrayWnd = FindWindowEx(0,0,"Shell_TrayWnd",vbNullString)
hWnd_StartButton = FindWindowEx(hwnd_ShellTrayWnd,0,"Button",vbNullString)
とやってるのですが・・・.
不思議なのは,hWnd_ShellTrayWndが9222812402616238204になっているにもかかわらず,次のFindWindowExで,hWnd_StartBtnが9222812402616107008になってるところです・・・. しかも,ありえないクラス名(KeyBoadぐちゃぐちゃ押し)を指定しても,なぜか数が返ってくるんです.

FindWindowExを成功させる(きちんとした数を取る)方法,またはFindWindowEx以外でhWndを拾ってくる方法,ありましたら,教えてください.

VB.netでWin32APIのFindWindowExを使うと,
たとえばスタートボタンのHWNDを拾ってくるとき,
本当なら65662(6.0のSpy++で確認+10進変換)が返ってきて欲しいんですが,
9222812402616107008という,異常な数が返ってきます.

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpsz2 As String) As Long
とやってあります.
...続きを読む

Aベストアンサー

あちゃぁ、英語のサイトから持ってきたのでコメント診て無かったです。すみません。
翻訳しても良くわからなかったですが、どう見ても記述が違いますね。

で、再度アドバイスです。

>Private Declare Function FindWindowEx ~
Integerを全てLongに書き換えてやってますよね。

引数・戻り値を全てIntegerにしてやって見てください。
当方では、問題なくウィンドウハンドルの取得が出来ましたよ。
ちなみに、MarshalAs属性は使用しなくてOKでした。
使用すると、戻り値が0になりました。

当方で確認したソースを記述します。
以下よりソース。

Option Strict Off
Option Explicit On

Imports System.Runtime.InteropServices

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
  (ByVal hWnd1 As Integer,
  ByVal hWnd2 As Integer,
  ByVal lpsz1 As String,
  ByVal lpsz2 As String) As Integer

  Private Sub Form1_Load(ByVal eventSender As System.Object, _
             ByVal eventArgs As System.EventArgs) Handles MyBase.Load
    Dim hWnd_StartButton As Integer
    Dim hwnd_ShellTrayWnd As Integer

    hwnd_ShellTrayWnd = FindWindowEx(0, 0, "Shell_TrayWnd", vbNullString)
    hWnd_StartButton = FindWindowEx(hwnd_ShellTrayWnd, 0, "Button", vbNullString)

    System.Diagnostics.Debug.WriteLine(hwnd_ShellTrayWnd & ";" & hWnd_StartButton)
End Sub

あちゃぁ、英語のサイトから持ってきたのでコメント診て無かったです。すみません。
翻訳しても良くわからなかったですが、どう見ても記述が違いますね。

で、再度アドバイスです。

>Private Declare Function FindWindowEx ~
Integerを全てLongに書き換えてやってますよね。

引数・戻り値を全てIntegerにしてやって見てください。
当方では、問題なくウィンドウハンドルの取得が出来ましたよ。
ちなみに、MarshalAs属性は使用しなくてOKでした。
使用すると、戻り値が0になりました。

当方で確...続きを読む

QAlt+P,Alt+NをPostmessageで送るには

あるアプリがあり、そのハンドルを取得してからメッセージを送るプログラムを作っています。
PageUp,PageDownをそれぞれAlt+P,Alt+Nに変換して送るものです。
関数・定数宣言部は省略しています。

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  Dim hTest As Long
  hTest = FindWindow(vbNullString, "Test")
  If KeyCode = 33 Then 'PageUp
    PostMessage MPL, WM_SYSKEYDOWN, VK_ALT, 0
    PostMessage MPL, WM_KEYDOWN, VK_N, 0
    PostMessage MPL, WM_KEYUP, VK_N, 0
    PostMessage MPL, WM_SYSKEYUP, VK_ALT, 0
  ElseIf KeyCode = 34 Then 'PageDown
    PostMessage MPL, WM_SYSKEYDOWN, VK_ALT, 0
    PostMessage MPL, WM_KEYDOWN, VK_P, 0
    PostMessage MPL, WM_KEYUP, VK_P, 0
    PostMessage MPL, WM_SYSKEYUP, VK_ALT, 0
  End If
End Sub

送り先(Test.exe)では、
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  Dim L As String
  L = ""
  If Shift = 4 Then L = "Alt + "
  Label1.Caption = L & KeyCode
End Sub

ラベルで「Alt+P」などが来ているかどうか見ています。こちらのウィンドウで「Alt+P」を押すとちゃんと表示されます。

しかし、この2つを組み合わせるとPのみやNのみしか送られてきません。どこかおかしいのでしょうか。

Alt+PなどをPostMessageで送る方法でよい方法があれば、お教え下さい。
よろしくお願いします。

あるアプリがあり、そのハンドルを取得してからメッセージを送るプログラムを作っています。
PageUp,PageDownをそれぞれAlt+P,Alt+Nに変換して送るものです。
関数・定数宣言部は省略しています。

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  Dim hTest As Long
  hTest = FindWindow(vbNullString, "Test")
  If KeyCode = 33 Then 'PageUp
    PostMessage MPL, WM_SYSKEYDOWN, VK_ALT, 0
    PostMessage MPL, WM_KEYDOWN, VK_N, 0
    PostMessage MPL,...続きを読む

Aベストアンサー

ALTキーとの組み合わせでしたら、WM_SYSCHARのほうがいいのでは?
たぶん、送り先もVB製でしたら内部でTranslateMessageような感じですし。


あと、
>PostMessage MPL, WM_SYSKEYDOWN, VK_ALT, 0

MPLってなんですか?
>hTest = FindWindow(vbNullString, "Test")
で取得したウィンドウにPostMessageするんじゃないんですか?


次に、
>Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

KeyDownイベントに処理が書かれてますが、このイベント自体は呼ばれてますか?キー操作を受け付けるコントロールが張り付いてるのにKeyPreviewプロパティがFalseなんてことは無いですか?

#ちなみに、普通はVK_ALTではなくVK_MENUですので。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング