スクリーンセーバー復帰後に、メッセージを受信するには?

解決


AICO  2005-08-31 23:25:43  No: 58795

初めまして、AICOと申します。 

スクリーンセーバー復帰(解除)後に、何かメッセージの様なものは、ないのでしょうか? 

グローバルフックしてみたのですが、スクリーンセーバー起動中は、引っかかりません。何か通知してくれる方法はないでしょうか? 

宜しくお願いします。


シャノン  2005-09-02 07:47:36  No: 58796

> スクリーンセーバー復帰(解除)後に、何かメッセージの様なものは、ないのでしょうか? 

うーん…
定期的に監視して、「現在動作中であるか」を調べることならできますが。
SystemParametersInfo 関数と SPI_GETSCREENSAVERRUNNING を調べてみてください。

> グローバルフックしてみたのですが、スクリーンセーバー起動中は、引っかかりません。

スクリーンセーバーはアプリとは違うデスクトップで実行されるからではないでしょうか。
SetUserObjectInformation でフック許可フラグをセットしてみるとか。


AICO  2005-09-03 02:59:22  No: 58797

シャノン様、ありがとう御座います。

>SystemParametersInfo 関数と SPI_GETSCREENSAVERRUNNING を調べてみてください。

Windows 98, Windows2000以外使用できないみたいで、できればどのバージョンでも受信(取得)できるようにしたいのですが、フックも駄目なら定期的に監視するしかないみたいですネ。

>SetUserObjectInformation でフック許可フラグをセットしてみるとか。

色々調べてみましたが、サンプルも含め参考になるサイトがなく、もう少し詳しく教えて頂けますでしょうか?

宜しくお願いします。


リンク  2005-09-03 03:55:28  No: 58798

スクリーンセーバーもウィンドウなのでWM_DESTORY等はグローバルフックで
認識できないのでしょうか?

できるならWM_DESTORYするウィンドウハンドルから起動アプリ名を取得し、
拡張子がscrだとスクリーンセーバーウィンドウが終了したとみなすことは
出来ないのでしょうか?

拡張子scrをテキストとかに設定していたら駄目ですけど。
(そんな人はいるのかな?いないとは言いけれないけど。)


AICO  2005-09-03 08:50:41  No: 58799

リンク様、ありがとう御座います。

>スクリーンセーバーもウィンドウなのでWM_DESTORY等はグローバルフックで
認識できないのでしょうか?

グローバルフックに、WM_DESTORYを入れてみましたが引っかかりませんでした。

>>スクリーンセーバーはアプリとは違うデスクトップで実行されるからではないでしょうか。


n  2005-09-03 22:56:41  No: 58800

Windows XP home + sp2 ですが、
CBTフックでスクリーンセーバーのWM_CREATEとWM_DESTROYが取れます。

ただし、「3Dテキスト」等のOpenGL系?のスクリーンセーバーは、
何故かWM_DESTROYが取れなかったです。
想像ですがWM_CREATEの処理中にスクリーンセーバーを出して、
終了するときはそのまま-1返しててWM_DESTROYが発行されてないのかも?
その場合でもフックプロシージャの入ったDLLのDllMainは普通にロード時
とアンロード時に呼び出されるので、これで判別できるかもです。

また、「画面のプロパティ」でスクリーンセーバーを設定する際、
スクリーンセーバーが多重起動されます。ここらへんも気をつけないと
マズいと思います。


AICO  2005-09-04 07:12:20  No: 58801

n様、ありがとう御座います。

私も、Windows XP home + sp2 です。

>CBTフックでスクリーンセーバーのWM_CREATEとWM_DESTROYが取れます。
>ただし、「3Dテキスト」等のOpenGL系?のスクリーンセーバーは、
>何故かWM_DESTROYが取れなかったです。

スクリーンセーバーに由っては、仕様がまちまちで取れませんネ?

>その場合でもフックプロシージャの入ったDLLのDllMainは普通にロード時
>とアンロード時に呼び出されるので、これで判別できるかもです。

アタッチ・デタッチ時なら、仕様に関係なく取れそうですね、でも判別の仕方が解りません。

どの様にしたら良いのでしょうか?

宜しくお願いします。


n  2005-09-05 02:42:04  No: 58802

DllMain中で、ロードされたプロセスの実行ファイルのパスを取得すれば、
WM_DESTROYが来なくても判別できるのでは。


AICO  2005-09-05 05:47:11  No: 58803

n様、ありがとう御座います。

>DllMain中で、ロードされたプロセスの実行ファイルのパスを取得すれば、

パスの取得方法も解らないですが、取得後どの様にして通知すれば良いのでしょうか?

現在 n様に、教えて頂いたCBTフックをしてHCBT_ACTIVATEで判別しようとしているのですが、クラス名ではそれがスクリーンセーバーなのか判別しずらいです。
ウィンドウハンドルかクラス名からファイル名を取得する方法はないでしょうか?

宜しくお願いします。


n  2005-09-05 19:05:41  No: 58804

パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
アプリケーションへの通知はWM_COPYDATAでやりました。


AICO  2005-09-06 19:59:55  No: 58805

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)で起動したものは、スクリーンセーバーによっては、通知しないものもあります。

宜しくお願いします。


  2005-09-06 20:03:08  No: 58806

> If Right$(buf, 3)="scr" Then SendMessage(hwnd, WM_APP+1, 0, 0)
VB?


AICO  2005-09-06 21:02:07  No: 58807

>VB?

ハイ。

参考に成ら無いでしょうか?


  2005-09-06 21:23:15  No: 58808

> 参考に成ら無いでしょうか?
いや、VCで開発しているのかどうかといっているのです。
VBならばいた違い。


n  2005-09-06 22:10:02  No: 58809

> VBならばいた違い。

まあここまで乗ったんだからいいでしょ。

> WM_COPYDATAの通知ができません。
> WM_APP+xxならできるのですが、なぜでしょうか?

何故でしょう...??
ところで「GetModuleFileName(0,buf,len)」はC/C++前提の書き方のつもり
ですけど、VBでもこれでOKなんですかね? 私はVBを全然知らないんです。

> PostMessage(hMainWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0)で起動したものは、スクリーンセーバーによっては、通知しないものもあります。

うーん、そうなんでしょうか?
私がやってみたもの(ブランク、3Dテキスト、ベジエ、等のXP付属のやつ)では特に違いはないような...


Blue  2005-09-06 22:27:39  No: 58810

> ところで「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で同様のことができるかとおもうのですが。


AICO  2005-09-07 19:25:10  No: 58811

皆様、ありがとう御座います。

> 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にしていたのですがマズかったですか?

宜しくお願いします。


Blue  2005-09-07 19:41:36  No: 58812

> 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しないとだめです。


Blue  2005-09-07 20:09:18  No: 58813

よくよんでみたら、

監視しているやつからGetModuleFileNameとっても、スクリーンセーバでないので、
拡張子が"src"になるんでしょうか?
> パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
これは呼び出しているモジュールのフルパスを取るものです。
(App.Pathと同じ)

それと、やっぱり板違いなので、VBの掲示板で聞いたほうがいいです。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi


AICO  2005-09-07 20:36:03  No: 58814

Blue様、ありがとう御座います。

>>Dim buf[MAX_PATH] As Byteにしていたのですがマズかったですか?
Dim buf(MAX_PATH) As Byteの間違いでした。

>Byteでとるならば、GetModuleFileNameの戻り値からReDimして、
>String変数として扱うならば、StrConvしないとだめです。

教えて頂いたサンプルのStringでやってみます。


n  2005-09-07 20:45:08  No: 58815

> 監視しているやつからGetModuleFileNameとっても、スクリーンセーバでないので、
> 拡張子が"src"になるんでしょうか?
> > パスの取得はDLL内からGetModuleFileName(0,buf,len)で、
> これは呼び出しているモジュールのフルパスを取るものです。

CBTフックプロシージャの入ったDLLはプロセスごとに別々の実体としてロードされるので、
DLL内で GetModuleFileName(0,...) として呼び出せばプロセスごとのパスが取得されます。


Blue  2005-09-07 20:49:25  No: 58816

> CBTフックプロシージャの入ったDLLはプロセスごとに別々の実体としてロードされるので
間違えていましたね。DLLから呼び出しているのでしたね。

# VBでDLLつくるのメンドソ。。。


AICO  2005-09-07 21:14:45  No: 58817

皆様、ありがとう御座いました。

途中から「板違い」の質問だと解っても最後まで丁寧に答えて頂きまして、ありがとう御座いました。

調べ足り無いのかも知れませんが、どの過去ログを見てもあんまり参考に成りませんでしたが、皆様の回答は大変参考に成りました。

特にn様、ありがとう御座いました!!(参考に成りました)
Blue様も、最後まで ありがとう御座いました!!

また、ご迷惑かも知れませんが質問させて頂きたいと思います。

その時は、宜しくお願いします。


PATIO  2005-09-07 23:32:15  No: 58818

VBネタと確信していて書き込むのはやめるべきだと思いますけどね。
今度書き込んでもレスは期待しない方が良いと思いますよ。
今回は初回だったからみんな付き合ってくれたのだと思いますし。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加