初めまして、AICOと申します。
スクリーンセーバー復帰(解除)後に、何かメッセージの様なものは、ないのでしょうか?
グローバルフックしてみたのですが、スクリーンセーバー起動中は、引っかかりません。何か通知してくれる方法はないでしょうか?
宜しくお願いします。
> スクリーンセーバー復帰(解除)後に、何かメッセージの様なものは、ないのでしょうか?
うーん…
定期的に監視して、「現在動作中であるか」を調べることならできますが。
SystemParametersInfo 関数と SPI_GETSCREENSAVERRUNNING を調べてみてください。
> グローバルフックしてみたのですが、スクリーンセーバー起動中は、引っかかりません。
スクリーンセーバーはアプリとは違うデスクトップで実行されるからではないでしょうか。
SetUserObjectInformation でフック許可フラグをセットしてみるとか。
シャノン様、ありがとう御座います。
>SystemParametersInfo 関数と SPI_GETSCREENSAVERRUNNING を調べてみてください。
Windows 98, Windows2000以外使用できないみたいで、できればどのバージョンでも受信(取得)できるようにしたいのですが、フックも駄目なら定期的に監視するしかないみたいですネ。
>SetUserObjectInformation でフック許可フラグをセットしてみるとか。
色々調べてみましたが、サンプルも含め参考になるサイトがなく、もう少し詳しく教えて頂けますでしょうか?
宜しくお願いします。
スクリーンセーバーもウィンドウなのでWM_DESTORY等はグローバルフックで
認識できないのでしょうか?
できるならWM_DESTORYするウィンドウハンドルから起動アプリ名を取得し、
拡張子がscrだとスクリーンセーバーウィンドウが終了したとみなすことは
出来ないのでしょうか?
拡張子scrをテキストとかに設定していたら駄目ですけど。
(そんな人はいるのかな?いないとは言いけれないけど。)
リンク様、ありがとう御座います。
>スクリーンセーバーもウィンドウなのでWM_DESTORY等はグローバルフックで
認識できないのでしょうか?
グローバルフックに、WM_DESTORYを入れてみましたが引っかかりませんでした。
>>スクリーンセーバーはアプリとは違うデスクトップで実行されるからではないでしょうか。
Windows XP home + sp2 ですが、
CBTフックでスクリーンセーバーのWM_CREATEとWM_DESTROYが取れます。
ただし、「3Dテキスト」等のOpenGL系?のスクリーンセーバーは、
何故かWM_DESTROYが取れなかったです。
想像ですがWM_CREATEの処理中にスクリーンセーバーを出して、
終了するときはそのまま-1返しててWM_DESTROYが発行されてないのかも?
その場合でもフックプロシージャの入ったDLLのDllMainは普通にロード時
とアンロード時に呼び出されるので、これで判別できるかもです。
また、「画面のプロパティ」でスクリーンセーバーを設定する際、
スクリーンセーバーが多重起動されます。ここらへんも気をつけないと
マズいと思います。
n様、ありがとう御座います。
私も、Windows XP home + sp2 です。
>CBTフックでスクリーンセーバーのWM_CREATEとWM_DESTROYが取れます。
>ただし、「3Dテキスト」等のOpenGL系?のスクリーンセーバーは、
>何故かWM_DESTROYが取れなかったです。
スクリーンセーバーに由っては、仕様がまちまちで取れませんネ?
>その場合でもフックプロシージャの入ったDLLのDllMainは普通にロード時
>とアンロード時に呼び出されるので、これで判別できるかもです。
アタッチ・デタッチ時なら、仕様に関係なく取れそうですね、でも判別の仕方が解りません。
どの様にしたら良いのでしょうか?
宜しくお願いします。
DllMain中で、ロードされたプロセスの実行ファイルのパスを取得すれば、
WM_DESTROYが来なくても判別できるのでは。
n様、ありがとう御座います。
>DllMain中で、ロードされたプロセスの実行ファイルのパスを取得すれば、
パスの取得方法も解らないですが、取得後どの様にして通知すれば良いのでしょうか?
現在 n様に、教えて頂いたCBTフックをしてHCBT_ACTIVATEで判別しようとしているのですが、クラス名ではそれがスクリーンセーバーなのか判別しずらいです。
ウィンドウハンドルかクラス名からファイル名を取得する方法はないでしょうか?
宜しくお願いします。
パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
アプリケーションへの通知はWM_COPYDATAでやりました。
n様、ありがとう御座います。
>パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
>アプリケーションへの通知はWM_COPYDATAでやりました。
GetModuleFileName(0,buf,len)を使用するとSendMessage()でWM_COPYDATAの通知ができません。(GetModuleFileName()無しなら通知できますが、それでは意味がないですしネ)
GetModuleFileName(0,buf,MAX_PATH)
If Right$(buf, 3)="scr" Then SendMessage(hwnd, WM_APP+1, 0, 0)
WM_APP+xxならできるのですが、なぜでしょうか?
"xxx.scr"ファイルの実行では、どんな仕様のスクリーンセーバーでも通知できますが、
PostMessage(hMainWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0)で起動したものは、スクリーンセーバーによっては、通知しないものもあります。
宜しくお願いします。
> If Right$(buf, 3)="scr" Then SendMessage(hwnd, WM_APP+1, 0, 0)
VB?
>VB?
ハイ。
参考に成ら無いでしょうか?
> 参考に成ら無いでしょうか?
いや、VCで開発しているのかどうかといっているのです。
VBならばいた違い。
> VBならばいた違い。
まあここまで乗ったんだからいいでしょ。
> WM_COPYDATAの通知ができません。
> WM_APP+xxならできるのですが、なぜでしょうか?
何故でしょう...??
ところで「GetModuleFileName(0,buf,len)」はC/C++前提の書き方のつもり
ですけど、VBでもこれでOKなんですかね? 私はVBを全然知らないんです。
> PostMessage(hMainWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0)で起動したものは、スクリーンセーバーによっては、通知しないものもあります。
うーん、そうなんでしょうか?
私がやってみたもの(ブランク、3Dテキスト、ベジエ、等のXP付属のやつ)では特に違いはないような...
> ところで「GetModuleFileName(0,buf,len)」はC/C++前提の書き方のつもり
> ですけど、VBでもこれでOKなんですかね? 私はVBを全然知らないんです。
大体使い方はそれでいいと思います。
(C/C++ならば第1引数はモジュールハンドルなのでNULLの方がいいかも)
しかし、
> GetModuleFileName(0,buf,MAX_PATH)
> If Right$(buf, 3)="scr" Then SendMessage(hwnd, WM_APP+1, 0, 0)
これはまずそうです。
GetModuleFileNameを呼ぶ前にbufの領域を確保します。そのときに長さが
MAX_PATHになっているので、Rigth関数はvbNullCharの位置からにしないといけません。
一応VBでの使い方)
Private Declare Function GetModuleFileName Lib "kernel32.dll" Alias "GetModuleFileNameA" _
(ByVal hModule As Long, ByVal lpFilename As String, ByVal nSize As Long) As Long
Private Const MAX_PATH = 260 ' 260でしたっけ?w
Public Sub Test()
Dim buf As String
Dim ret As Long
buf = String(MAX_PATH,vbNullChar)
ret = GetModuleFileName(0,buf,MAX_PATH)
If ret > 0 Then
buf = Left$(buf,InStr(buf,vbNullChar))
MsgBox buf
End If
End Sub
というか、VBだったらApp.Pathで同様のことができるかとおもうのですが。
皆様、ありがとう御座います。
> VBならばいた違い。
VB系の掲示板も質問したのですが、これといって回答も無くいろいろ
調べているうちに、このサイトの過去ログを見てC/C++の掲示板と知りつつ
質問させて頂きました。
>> PostMessage(hMainWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0)で起動したものは、スクリーンセーバーによっては、通知しないものもあります。
>うーん、そうなんでしょうか?
>私がやってみたもの(ブランク、3Dテキスト、ベジエ、等のXP付属のやつ)>では特に違いはないような...
XP付属のやつは、こちらでも通知しますがオリジナルのスクリーンセーバー
だと通知しないものもあります。
>> GetModuleFileName(0,buf,MAX_PATH)
>> If Right$(buf, 3)="scr" Then SendMessage(hwnd, WM_APP+1, 0, 0)
>これはまずそうです。
>GetModuleFileNameを呼ぶ前にbufの領域を確保します。そのときに長さが
>MAX_PATHになっているので、Rigth関数はvbNullCharの位置からにしないといけません。
Dim buf[MAX_PATH] As Byteにしていたのですがマズかったですか?
宜しくお願いします。
> Dim buf[MAX_PATH] As Byteにしていたのですがマズかったですか?
VBってこんなかきかたできったけ?(VB.NETからできるようになった?)
# Dim buf(MAX_PATH) As Byteならできるけど。
VBのバージョンを明記してください。
.NETと6以前では全然違うらしいですから。(私はVB6しかわからん)
まずいかどうか、Debug.Printで確かめてみればいいでしょう。
Byteでとるならば、GetModuleFileNameの戻り値からReDimして、
String変数として扱うならば、StrConvしないとだめです。
よくよんでみたら、
監視しているやつからGetModuleFileNameとっても、スクリーンセーバでないので、
拡張子が"src"になるんでしょうか?
> パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
これは呼び出しているモジュールのフルパスを取るものです。
(App.Pathと同じ)
それと、やっぱり板違いなので、VBの掲示板で聞いたほうがいいです。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi
Blue様、ありがとう御座います。
>>Dim buf[MAX_PATH] As Byteにしていたのですがマズかったですか?
Dim buf(MAX_PATH) As Byteの間違いでした。
>Byteでとるならば、GetModuleFileNameの戻り値からReDimして、
>String変数として扱うならば、StrConvしないとだめです。
教えて頂いたサンプルのStringでやってみます。
> 監視しているやつからGetModuleFileNameとっても、スクリーンセーバでないので、
> 拡張子が"src"になるんでしょうか?
> > パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
> これは呼び出しているモジュールのフルパスを取るものです。
CBTフックプロシージャの入ったDLLはプロセスごとに別々の実体としてロードされるので、
DLL内で GetModuleFileName(0,...) として呼び出せばプロセスごとのパスが取得されます。
> CBTフックプロシージャの入ったDLLはプロセスごとに別々の実体としてロードされるので
間違えていましたね。DLLから呼び出しているのでしたね。
# VBでDLLつくるのメンドソ。。。
皆様、ありがとう御座いました。
途中から「板違い」の質問だと解っても最後まで丁寧に答えて頂きまして、ありがとう御座いました。
調べ足り無いのかも知れませんが、どの過去ログを見てもあんまり参考に成りませんでしたが、皆様の回答は大変参考に成りました。
特にn様、ありがとう御座いました!!(参考に成りました)
Blue様も、最後まで ありがとう御座いました!!
また、ご迷惑かも知れませんが質問させて頂きたいと思います。
その時は、宜しくお願いします。
VBネタと確信していて書き込むのはやめるべきだと思いますけどね。
今度書き込んでもレスは期待しない方が良いと思いますよ。
今回は初回だったからみんな付き合ってくれたのだと思いますし。
ツイート | ![]() |