久々に登場してしまいました!Miyukiです!!梅雨・・明けそうですねぇ。
環境はWINDOWS2000、VC++6,0、MFCのダイアログベースです。
バイナリファイルをテキストファイルに変換するツールを作ってます。
無事テキストファイルへの変換が終わり、ユーザーのアンサーによってはそのテキ
ストファイルを自動的にOPENしてあげたく、ShellExecuteEx()
を使いました。その後、その開いたファイルをこちらで終了させてあげたいのですが
どうしても出来ません・・・。過去のログにもあって、それを見習ってTryしてみ
たのですが。
//書き込みの処理も終わり、ファイルCloseした後
char che = 0;
SHELLEXECUTEINFO opench;
memset(&opench,0x00,sizeof(SHELLEXECUTEINFO));
//少々省略
opench.lpFile = filetxt. //開くファイル名
opench.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&opench);
EnumWindows(TxtCheck,(LPARAM)&opench);
//ここでチェックして処理して良いのでしょうか・・・。
BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd,LPARAM lparam)
{
char Title[MAX_PATH];
if(::GetWindowText(hwnd,Title,MAX_PATH) != lparam){
return TURE;
}
::SendMessage(hwnd,WM_CLOSE,lparam,lparam);
return FALSE;
}
//TxtChech()のプロトコル宣言はclass CHenkan2Dlgの中で・・・。
これを実行して、テキストファイルに変換!!でもテキストファイルを自動OPEN
後、閉じる気配はありません・・・。 本当は、この処理の延長線で「若しウィンド
ウ上にテキスト変換しようと思っているファイルが開かれていたら。その時はテキス
ト変換はしない!!」みたいな処理にしたいのですが、その前にこういった(殺す??)
自分で開いたファイルを自分で閉じるように出来ないと何も進まないと思って・・・・。
えっと説明不足かも知れませんが、そこは若葉マークの私の事なので、何卒寛大なハート
でご理解の程、宜しくお願いします。 過去のログにあるじゃないか!!と思われるかも
知れませんが、私もそのログを見て一生懸命やったその結果なので・・・。
宜しくお願いします!!
k-miyuki様
直接の回答ではありませんけど。
CALLBACK関数はスタティックでなければなりません。
メンバ関数TxtCheck()はstatic宣言されているのでしょうか?エラーになりませんか?
それから、WM_CLOSEメッセージはPostMessageした方が安全です。
もうひとつ
if(::GetWindowText(hwnd,Title,MAX_PATH) != lparam)は何を判定されていますか?
lparamには SHELLEXECUTEINFO構造体かな? の実体 openchのアドレスが入っているはずなので
必ず != になるような気がします。したがって
::SendMessage(hwnd,WM_CLOSE,lparam,lparam); の行でブレークをかけても、ここには来ないのでは?
いいのでしょうか?
排他制御に関しては無知なので、この程度しかアドバイスできません。 m(__)m っす。
k-miyuki様
直接の回答ではありませんけど。Part2
はずしているかも知れませんが
return TRUE と FALSE の位置は反対では?
それから、梅雨、明けました。(^^;
はい!BUNさん。梅雨明けましたねっ。
アドバイスありがとうございます。
先日BUNさんは「これくらいしかアドバイス出来ません」と仰ってましたが、
それを認識しながらの質問は宜しいでしょうか? いえ・現状報告でも
良いです。
BUNさんのご指摘通り、この間は何と何を比較してるのか全く不明でしたねっ。
今回はプロセスIDがあれば!!と言う事で自動OPENする関数をShell系から
CreateProcess()に変更しました。(本当突然で申し訳ありませんが)
無事プロセスIDも取得して、あとは開いたエディタのIDとウィンドウ上に
IDを比較すれば良いですよね?
if(!CreateProcess(Kanren2,Kanren,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){
//kanrenにはコマンドライン形式のファイル名が入ってます
//ここがなかなか理解出来なくて、お返事に時間掛かっちゃいました。すみません。
AfxMessageBox(_T(起動できませんでした ));
}
EnumWindows(TxtCheck, (long)pi.dwProcessId);
CloseHandle(pi.hProcess);
BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd,LPARAM opench)
{
DWORD pid;
GetWindowThreadProcessId(hwnd,&pid);
if(pid==(DWORD)lParam){
TRACE(一致しましたよ!!);
::PostMessage(hwnd,WM_SYSCOMMAND,SC_CLOSE,0);
}
return TRUE;
}
とやってみました。デバックで確認すると、開いたテキストファイルがウィンドウ上に
まだある時は当然「(pid==(DWORD)lParam)」の条件が一致します。コールバック関数
なので何度も何度もチェックしてますが。
で、そうすると当然その後のPostMessage()で「閉じる」命令を出しているから
閉じるはず!??が・・・全くそのエディタは閉じる気配がありません・・・。
上の「ツール」から「SPY++」というところで、開いたエディタを選択して、
「送られて来たメッセージ」を確認しようと思ったのですが、何もメッセージは
ありませんでした。(この確認方法は今日参考書で初めて知りました)
何かダメな点はありますでしょうか? 私も勉強しながら頑張ってやってるので
何かアドバイス、助言等を頂けたら嬉しいです。
それでは。 梅雨がこのまま明けちゃって水不足が心配されますが、関東(私の
事ですが・・・)の利根川ダムはこの陽気にも関わらず満水状態だそうです。
関係ないっか・・・。
> BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd,LPARAM opench)
とありますが、先にも述べたようにCALLBACK関数はstaticでなければいけません。
エラーにはなりませんでしたか?
> if(pid==(DWORD)lParam){
> TRACE(一致しましたよ!!);
> ::PostMessage(hwnd,WM_SYSCOMMAND,SC_CLOSE,0);
> }
なんか怪しげなんですけど、ここも書くなら
if (pid == (LPARAM)opench) {
TRACE(一致しましたよ!!);
::PostMessage(hwnd,WM_SYSCOMMAND,SC_CLOSE,0);
}
じゃないすか?
エラーになると思うんですけど・・・
実際のコードをのせてくらはい。(涙)
それから、spy++のファインダーツールは使っていますか?
> if(!CreateProcess(Kanren2,Kanren,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){
Kanren2およびKanrenの変数の型とその内容を教えてください。
> ::PostMessage(hwnd,WM_SYSCOMMAND,SC_CLOSE,0);
それから、EnumWindowProc()内では
一致を検出後、PostMessage()の後には(普通)return FALSE; を記述します。
BUNさん。お返事遅れてしまいまして、申し訳ございませんでした。
先日「閉じない!」と一人唸っていた私ですが、その原因は「エディタが起動しないうちにEnumWindowsが実行される
から」だと分りました。 大変お騒がせしてすみませんでした。
えっと・・・この間、書き足りなかった事です。
BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd・・・)の前に「static」。付けてました。書き間違いで・・
すみませんですぅ。(ですので、こちらでのエラー表示は出ませんです)
また、
BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd,LPARAM opench)のopenchのところも
BOOL CALLBACK CHenkan2Dlg::TxtCheck(HWND hwnd,LPARAM lParam)と宣言してました。 あれ?どうしてopench
なんて書いちゃったんだろう・・・あ!色々#if 0や#evenif等で前のソースを残したままやってるので、その前に
やっていた(勿論こっちは間違いだらけ)方の引数を書いてしまいました。 ほんとにほんとにすみません!!
(return FALSE;もPostmessageの後に追加致しました)
Kanren2とKanrenはそれぞれchar型で
Kanren2には開きたいエディターへのパスが入っています。
例えばC:\Program Files\・・・エディター\・・・EXE
Kanrenにはそのエディタへのパスと開きたいテキストのパスが入ってます
例えばC:\Program Files\・・・・・・・・・・EXE C:\My Documents\変換プログラム\・・・・\10Kb.txt
今回の誤り訂正と先に書かせて頂いたコードで「ウィンドウ上に開いてあるテキスト」と「これから開こうとしている
テキスト」のプロセスIDが一致してるかどうかの判断は出来るようになりました。(デバックで)
(例えば、ウィンドウ上に開きっぱなしにしてあると、コールバック関数の中で必ず一致し、一度テキスト閉じると、
決してプロセスIDは一致しない。ハンドルを閉じるまでは)
そこで質問なのですが、コールバック関数でチェックしたIDを何処かにストック置きたいと思っています。HPなどで
は列挙など言われてますが、ちょっと私では理解に乏しいです。
開いてあるテキストファイルと変換したいファイルが同じIDを持つならば、その時はMessageBox等で「只今同名ファイ
ルが開かれています。」という注意を促し(または制御を加える)、若しテキスト変換の処理を続けて、同プロセスIDが無かった場合は、そのIDをストックしておいて、そのまま同IDが来るまでチェックを行えるような処理を加えたい
のですが、どのように処理していいのか?分りません・・・。 配列? ループで回すの? 何?
日に日に変な方向へ行ってしまいがちな私ですが、どうか宜しくお願い致します。(この稚拙な説明でご理解して
頂けるか不安いっぱいです。)
昨日は気分転換に井の頭公園でお散歩して、池の鴨を眺めてたら「真っ赤に日焼け」してしまった私なのでした。
気分転換だったのに・・・。
>今回の誤り訂正と先に書かせて頂いたコードで「ウィンドウ上に開いてあるテキスト」と「これから開こうとしている
>テキスト」のプロセスIDが一致してるかどうかの判断は出来るようになりました。(デバックで)
本当っすか?
プロセスIDって、実行ファイルに対してつけられるのではないでしょうか?
>開いてあるテキストファイルと変換したいファイルが同じIDを持つならば、その時はMessageBox等で
>「只今同名ファイルが開かれています。」という注意を促し(または制御を加える)、若しテキスト変換の処理を
> 続けて、同プロセスIDが無かった場合は、そのIDをストックしておいて、そのまま同IDが来るまでチェックを
> 行えるような処理を加えたいのですが、どのように処理していいのか?分りません・・・。
> 配列? ループで回すの? 何?
したがって、IDでファイルを区別はできません。
なお、冒頭でも述べましたとおり、私は排他制御に関してはしろうと(他もですが(^^;)ですから
これ以上のアドバイスは難しいと思います。 m(__)m
お役にたてず、ゴメンナサイ。
BUNさん。「ごめんなさい」なんてとんでもないわっ。 こちらこそ勝手にぐちゃぐちゃ書いて済みませんでした!!
今までの事だけでもとっても勉強になりました~~。
あとは自分で何とかやってみます!!また何かありましたら宜しくお願いしますねっ。
それでは最近すっごく暑いですが、体調など崩さないようにです。(先週風邪引いた私。説得力無しですねぇ)