VB6で、プログラムを作っています。
コマンドボタンを押したら、メモ長がひらかれるようにしたいんです。
ヘルプとかをしらべて、メモ帳が開かれるところまではできました。
そのあと、手入力でテキスト入力をするんじゃなくて、
プログラム内で、メモ帳が開かれたときに、
「ここに文字をいれてください」とすでにテキスト表示をさせたいのですが、
プログラムでは不可能でしょうか?
それを応用して、コマンドプロンプトにもテキストをいれたり、
エクセルにテキストを入れたりしたいんです。
ご存知のかた教えてください。m(__)m
最も簡単な方法:
Shell("notepad.exe", vbNormalFocus)
SendKeys "ここに文字をいれてください."
> SendKeys "ここに文字をいれてください."
それでうまくいくでしょうか?
ShellでNotepadをひらかせるように指示してから、
実際にNotepadが入力できるようになるには、プログラム的にはかなりの差がありますから——。
ファイル名が見えたりして、あんまりよろしくないような気もしますけど、
"ここに文字を入れてください"という文章の書かれたテキストファイルを作って、
Shell("notepad text.txt", vbNormalFocus)
みたいな感じにしてもいいかと。
やってみたこともない code 例示したりはしないけど,必ず上手
くいくわけじゃないのは暗黙値ってことで….
な事のためにこんなんするか?わしゃあの2行で充分だとおもうけどぉ…
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Const PROCESS_QUERY_INFORMATION As Long = &H400&
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
Private Const STILL_ACTIVE As Long = &H103&
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Function ProgramExists(lTask As Long) As Boolean
Dim lProcHandle As Long
Dim lExitCode As Long
Dim lState As Long
lProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION, True, lTask)
If lProcHandle = 0 Then
ProgramExists = False
Exit Function
End If
lState = GetExitCodeProcess(lProcHandle, lExitCode)
If lExitCode = STILL_ACTIVE Then
ProgramExists = True
Else
ProgramExists = False
End If
lState = CloseHandle(lProcHandle)
End Function
Private Sub Command1_Click()
Dim lTask As Long
lTask = Shell("notepad.exe", vbNormalFocus)
Do Until ProgramExists(lTask): Loop
SendKeys "ここに文字をいれてください."
End Sub
ま,なんでもやってみてくれ.
とかいって,
Shell("notepad.exe", vbNormalFocus)
じゃだめじゃん.
Shell "notepad.exe", vbNormalFocus
だよね…はは!
ええーと、SendKeysは"アクティブなフォームにキーを送る"だけの手続きだから、
起動直後に送ったのでは失敗する可能性の方が高いのでは?と思ったのです。
質問者さんのことを考えると、なるべくかんたんにした方がいいかな…とおもっていながら、
結局説明足らずになってしまいましたね^^;ごめんなさいm(__)m
たとえば、その前にSendMessageでWM_NULLを送って、ちょっと待ってみるとか、SetForegroundWindowを使うとか——ですね。
ちなみに、わたしはこういう風にしました。Delphiのものです。
hNotePad, hDebugNoteという変数は、あらかじめHWND型(VBでならLongが適当でしょう)で宣言しておきます。
NotePadClassName, NotePadEditClass定数は、
前から"メモ帳のクラス名"、"メモ帳のエディタのクラス名"です。
// メモ帳を起動し、デバッグモニタ代わりに使う(Delphiの無償版には、デバッグログを表示する機能がないので)
WinExec(NotePadFileName,SW_SHOW);
hNotePad := FindWindow(NotePadClassName,nil);
SendMessage(hNotePad,WM_NULL,0,0);
hDebugNote := FindWindowEx(hNotePad,0,NotePadEditClass,nil);
SetWindowText(hNotePad,'DebugUnitレポート');
// デバッグモニタが下がっちゃ意味ないので、最前面表示
SetWindowPos(hNotePad,HWND_TOPMOST,0,0,0,0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
こうしておいて、送信するときは
SendMessage(hDebugNote, EM_REPLACESEL, 0, lParam(PChar(Str)));
とやります。ただし、この場合メモ帳がすでに起動してるときにはどうなるかわかりません。
メモ帳でキャレット位置をいじっちゃった場合も、挿入場所がおかしくなります。
デバッグモニタなら、もう少ししっかりするべきでしょうね。
WinExecなんかより、ShellExecuteとかを使いなよという意見もあるでしょうが、とりあえずそのつっこみはなしで(^^ゞ
確かに、SendKeys だと active じゃないといかんなぁ・・・
いる、って判っても、どんな状態でいるかは解んないしなぁ・・・
ちょっと待つってのは大事だろうなぁ・・・
VB で SendKeys の debug はきっとやりにくいよなぁ・・・
そうかぁ Window Handle がとれりゃ SetWindowText できるから、
そっちの方がずっと smart だね!
“すでに開かれてたら” ってのも NotPad ならよさそうだけどなぁ・・・
あとは みおくん にがんばってもらおぅっと.
punto様、たかみちえ様、ご教授ありがとうございますm(__)m
とてもわかりやすい文章で、初心者の私でも理解ができました。
ありがとうございます。
いろいろ調べながら、全て実行してみました。
初心者なので、至らない点などあると思うのですが、私が実行してみた
結果です。
まず、punto様の最初の
Shell("notepad.exe", vbNormalFocus)
SendKeys "ここに文字をいれてください."
の2行での実行はノートパッドは開き、文字は表示されるのですが、
表示される文字長がバラバラで、「ここに」までの時や、「ここに文字」までの
時など、全部文字が表示されませんでした。(TT)
たかみちえ様の最初のすでに文字を入力しておき、そのノードパッドを起動させる
方法は、文字が固定なら可能なのですが、ノードパッドのほかに、エクセルや、
コマンドプロンプトでも入力文字は可変長で実行したい箇所があるので、必ず
固定で実行するボタンが1つありますので、そこで実行するとうまくでました!
固定でのノートパッドの問題は解決したのですが、可変長での
ファイル起動後の文字入力(ノートパッドとコマンドプロンプトとエクセル)が
できず、まだ困ってまして、
次にpunto様のFunctionでのプログラムを実行してみました。
ブレークポイントを設定せずにプログラムを起動すると、うまくノートパッドに全て文字が
はいりました!! なのですが、動作を確認したくて、ブレークポイントを2,3点設定して、
プログラムの動きを1行ずつみていくと、文字が1文字も出なくなってしまいました(TT)
ブレークポイントを追いかけて、ノートパッドがアクティブでないからなのでしょうか?
また、こちらの方法は、エクセル、コマンドプロンプトでも起動させるEXEを変更し、
ブレークポイントを設置しなければ、動作可能になるのでしょうか?(今からやってみます)
たかみちえ様のDelphiでの起動もやってみたのですが、
punto様のSENDKEYSと同じで、結果がまばらなものになってしまいました(TT)
もうすこしいろいろ試してみます。
それは私の実行方法がおかしいから、動かないのでは?という点がありましたら、
ご指摘お願いします。
他に方法などありましたら、ご教授お願い致します m(__)m
Delphiが出てきたりして少し錯綜ぎみですが
>コマンドボタンを押したら、メモ長がひらかれるようにしたいんです。
なんで
Dim AppId
Private Sub Command1_Click()
AppId = Shell("notepad.exe", vbNormalFocus) 'メモ帳起動
AppActivate (AppId)
SendKeys ("ここに文字をいれてください") '書き込む
End Sub
これで失敗することは無いと思いますが。
ちなみに
For n = 1 To 20
AppId = Shell("notepad.exe", vbNormalFocus) 'メモ帳起動
AppActivate (AppId)
SendKeys ("ここに文字をいれてください") '書き込む
Next
なんてやっても失敗はしません。かなり過酷だと思いますが。
> プログラムの動きを1行ずつみていくと
ええと、まずわたしが書いたとおり、SendKeysというのは、"アクティブなフォーム上で、キーボード操作をシミュレートする"ものですから、
アクティブなフォームがVBのウィンドウだと、当然結果がおかしくなります。
これはヘルプにもすこし載っていたと思いますから、確認してみてください。
たとえば、SendKeys "ABC"とすると、
今その場で、キーボードで" A B C "とタイプしたのと同じこと"ができます。
つまりSendKeysが、キータイプ操作をシミュレートしてる途中で、アクティブなフォームを切り替えても、もちろん結果がおかしくなりますね。
> 可変長でのファイル起動後の文字入力
全て共通の手段で、確実に…というのは難しいですね。
ExcelはまだActiveXコントロールとか(ExcelのActiveXについては過去ログにあったかも)があるでしょうからいいですが、
コマンドプロンプトみたいに、そもそもアプリケーションのタイプからしてそもそも別のものをどうにかしよう…となると、難しいです。
まあ、バッチファイルを自動生成してやれば、幾分かシミュレートできるかもしれませんが。
そもそも実行されるものがなんなのかわからない状況で、文字を表示するのはたやすいことではないです。そういった意味では、
puntoさんのおっしゃった、"SendKeys"が一番簡単かつ汎用的ではあります。
(じゃあテキスト入力ウィンドウのないソフトの場合は?起動処理が長いソフトの場合は?とか言うと、きりがないですが(^^ゞ)
そういえばSendKeysより確実にキーを送る方法としては、
SendMessageでWM_KEYUP、WM_KEYDOWN などのメッセージを送る方法もあります。
これはSendKeysと違ってウィンドウハンドルを指定して送りますから、SendKeysよりかなり確実です。
ただしSendKeysのように文字列で書くことができない(キーを押して、放して、押して——といった動作を記述していくことになる)ので、難しくなります。
汎用性を求めようとするなら、なおのこと。
VBのコードに、この場で正確に書き直せる自信がないですから、Delphiのコードをそのまま転載…ということになってしまいました(^^ゞ
>AppActivate (AppId)
そういえばShellの戻り値IDを使えばそんなこともできるんでしたっけ…。
これでアクティブにしたあと、GetForegroundWindowでウィンドウハンドルを得て、SendMessageでWM_KEYDOWN——とやると、
SendKeys中のトラブル(キーシミュレート中にユーザーがフォーカスを切り替えてしまうなど)も防げるかも。
>そういえばShellの戻り値IDを使えばそんなこともできるんでしたっけ…。
はい、MSDNのShell関数の使用例に。
>AppActivate (AppId)
>SendKeys ("ここに文字をいれてください") '書き込む
DoEventsでも入れない限りこの間にキーイベントが割り込む可能性は少ないと思いますが。
どうしても心配で夜眠れない様な場合は、
SetClipboardDtat , SendMessage , WM_PASTE
を使ってクリップボード経由で貼り付ける方法もあるかと。
『何もそこまでしなくても』と言う感じですが。
BASP21の Debugメソッドを使うのが簡単かも。
http://www.hi-ho.ne.jp/babaq/basp21.html#0021
Shell("○○.exe ここに文字をいれて",VbNormal)
って入れると、この場合だと、ノートパッドが起動されて、しかも、
スペースの後の文字が入力されるんじゃないですか?
おぃおぃ・・・
編集 削除