HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0831
SADOUSウィンドウを完全に最前面に表示したい(タスクバーなどの上に)8解決


SADOUS

リンク

2014/8/31(Sun) 00:19:05|NO.64544

最近user32.dllというものを積極的に利用しようとして、すぐ挫折しています。
パソコンに詳しくないので、msdnで調べていて「これか!」と思ったものを
使っては失敗して・・・

gsel ,2を定期的にやれば、タスクバーやタスクマネージャは引き下がってくれますが、
ウィンドウズボタンの挙動がとてつもなく怪しい・・・・・
安定して、ちらつくこと無く完全最前面表示する方法があれば教えていただきたいです。



■質問に至るまでの経緯
BringWindowToTopは指定ハンドルをZオーダのトップに持っていく。
「Zオーダはつまりxyzのzだよな?最前面表示かー!!!行ける!!!」

#uselib "user32.dll" #func BringWindowToTop "BringWindowToTop" int repeat gsel 0:_stat=stat BringWindowToTop _stat wait 100 loop
「違うのか・・・」
「関連する関数にSetWindowPosを発見!いける!これはいける!」
「・・・?パラメータにSWP_NOSIZEとかあるけど、直接英文字打ってもダメだよな、
0x0000だっけ?そんな感じのやつじゃなかったっけ?どこに載っているんだ?
そもそもZオーダって何だっけ・・・ググってみたら
ウィンドウ同士の相対的な重なりを制御できるものとある、
BringWindowToTopじゃだめなのか?」

「・・・、そもそもこの処理だけじゃgsel ,2と変わらない。
スタートボタンとタスクバーのクラスからハンドルを・・・いや、自ウィンドウより上のzオーダを
常時監視して、なんか出てきたらトップになって・・・・・・?」
「ダメだ、パンクしそう」
「new3DSが出たみたいだけど、3DSにスラパ付けるだけの物とあんま変わんなくね?」
「3DS持ってる人はスラパ買うだけでよくね?MH4Gは3DS対応なはずだしさ」

と言った具合。



この記事に返信する


ぴょぴょ

リンク

2014/8/31(Sun) 02:52:18|NO.64545

> 安定して、ちらつくこと無く完全最前面表示する方法があれば教えていただきたいです。

・Windowメッセージ(0x0000-0x00FF)
http://blog.goo.ne.jp/masaki_goo_2006/e/65fe9047e5f97bde1830566766b4829e

ここの WM_WINDOWPOSCHANGED メッセージを処理すれば常に最前面表示を実現できると思います。
ただし、他のソフトで同じように WM_WINDOWPOSCHANGED を処理して最前面表示を実現してると
ちらつきますよ。

・WM_WINDOWPOSCHANGED message
http://msdn.microsoft.com/en-us/library/ms632652.aspx
・WINDOWPOS structure
http://msdn.microsoft.com/en-us/library/ms632612.aspx

MSDN資料



cats

リンク

2014/8/31(Sun) 07:32:52|NO.64546

SWP_*は資料が少なかったです。
ここに定義がありました。
http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Standard/NativeMethods.cs
SetWindowPosで最前面化はできるのですが、
そのためには第二パラメータに HWND_TOPMOST (-1) を指定します。
ただ、gsel *, 2 もたぶん内部では同じ動作をしているかと。

あと、最初のコードでBringWindowToTopでstatを指定していますが、
ウィンドウハンドルはhwndで指定してください。
statでは全く意味がありません。



SADOUS

リンク

2014/8/31(Sun) 21:37:31|NO.64572

第七パラメータがよくわからないんでヌルったんですけど、
setwindowpos hwnd,-1,0,0,320,240,0
gsel 0,2
catsさんの言うとおり、gselと全く同じ動作をしました。
windowsメニュー出してみたりするとチラつきますね。

画面ロックのソフトを作るというか、修正しようと思ったんですけど
keyhook.dllがアンチウイルスソフトにブロックされる傾向にあるようなので
別の方法でウィンドウズボタンなどを無効化できないかと思っていたんです。



見た目的にちらつくのが気に喰わないので、
クラス名からウィンドウボタン・メニュー、タスクバーのハンドルを拾って
そいつらが前面に出てこれないよう。
または、自ウィンドウより前面に出てくるものを検知できるならして、
そいつらより前に出る。
デスクトップの表示(windows+D)により消される対策もしたい。
とか
そんなことできそうだなとは思うんですが、なかなか関連する関数を見つけれない。

→要するにいつでもどこでも完全に最前面表示したいんです。



cats

リンク

2014/8/31(Sun) 22:48:53|NO.64575

常に最前面ウィンドウのハンドルを取得し、それをhwndと比較して
一致しなければgselで最前面にする、というのが一番良いでしょう。
http://msdn.microsoft.com/ja-jp/library/cc364732.aspx
あとは、信頼性のある設計が必要になりますが、他ウィンドウを全て
最背面ウィンドウに指定して、終了時に元に戻すという無茶な方法も思いつきました。
やろうと思えば他にもいろいろあるのですが、
関数で一発でできるような方法は無いでしょう。
キーボードフックは自作してみたらどうでしょう。
http://7ujm.net/C++/Hook3.html
コードが公開されているのでコンパイルするだけです。
試してないのでセキュリティ面で検知されるかは分かりませんが。



SADOUS

リンク

2014/9/2(Tue) 14:21:59|NO.64616

>catsさん
フォアグラウンドウィンドウの取得、
僕の技量でも無難に扱えそうなのでそれを使います・・・


デスクトップの表示(windows + D)をやると
完全に引っ込んで処理(gsel ,2)が止まるようですが、
これは最小化によるものなのでしょうか・・・
こいつは厄介だなーとか思うんですが、これは対策できそうですか?
くどいようですがキーフックプラグインは誤検出されやすいのでNGです。



cats

リンク

2014/9/2(Tue) 15:50:31|NO.64618

>これは対策できそうですか
IsIconicという最小化されたかを判定できる関数があります。
と思ったのですが、これはWin+Dでは効かないみたいです。
GetForegroundWindowで調べてアクティブウィンドウが自ウィンドウで無いときに、
最前面化すると共に、自ウィンドウに対して「最小化を元に戻す」メッセージを送りましょう。

#include "user32.as" repeat ; IsIconic hwnd GetForegroundWindow if stat != hwnd : gosub *Alice await 15 loop *Alice gsel 0, 2 sendmsg hwnd, $112, $F120 return
しかし、Windows OSの仕様上、最小化からの復帰時のアニメーションが発生してしまいます。
いくつか試してみましたが、どうも上手くいきませんね。
oncmdでWM_SYSCOMMANDとWM_SIZEを受け取って最小化を判断できたのですが、
肝心のWM_SIZEはreturnで-1を渡してもメッセージを妨害できませんでした。
WM_SIZEでwparamが1のときに最小化ですので、それをウィンドウに渡さないようにすればよいかと。
一応失敗コード。

oncmd gosub *ALICE, 0x0112 oncmd gosub *BOB, 5 stop *ALICE ; WM_SYSCOMMAND if ( wparam & 0xFFF0 ) == 0xF020 : return -1 ; 最小化ボタンはとりあえず成功 return *BOB ; WM_SIZE if wparam == 1 : return -1 ; 上手くいかぬ return



カレー

リンク

2014/9/5(Fri) 13:44:39|NO.64692

全く持って原始的な方法ですが、なにかの展示に使おうと思っているなら
ウィンドウキーを引っこ抜いて物理的に使わせないようにするなんて方法もあるかも…
なんてプログラミングの掲示板らしからぬ事を言ってみる…



woodfields

リンク

2014/9/5(Fri) 18:12:12|NO.64700

解決済み?のようにも思えますが、こんなのでダメでしょうか。

#uselib "user32.dll" #cfunc GetForegroundWindow "GetForegroundWindow" #func GetWindow "GetWindow" sptr,sptr #const GW_OWNER 0x0004 ; 指定したウィンドウのオーナーウィンドウのハンドル #cfunc GetWindowThreadProcessId "GetWindowThreadProcessId" sptr,sptr #func AttachThreadInput "AttachThreadInput" sptr,sptr,sptr #func SetForegroundWindow "SetForegroundWindow" sptr #func GetWindowPlacement "GetWindowPlacement" int,int #const SW_SHOWMINIMIZED 2 ; ウィンドウは最小化表示状態 dim str_WINDOWPLACEMENT,6 ; WINDOWPLACEMENT構造体 str_WINDOWPLACEMENT(0)=4*6 ; UINT length; ;str_WINDOWPLACEMENT(1)= ; UINT flags; ;str_WINDOWPLACEMENT(2)= ; UINT showCmd; ;str_WINDOWPLACEMENT(3)= ; POINT ptMinPosition; ;str_WINDOWPLACEMENT(4)= ; POINT ptMaxPosition; ;str_WINDOWPLACEMENT(5)= ; RECT rcNormalPosition; #func SendMessage "SendMessageA" int,int,int,int #const WM_SYSCOMMAND $00000112 ; ウィンドウにメッセージを送る #const SC_RESTORE $0000F120 ; ウィンドウを通常の位置とサイズに復元 screen 2,300,100 ; どういうわけか screen 0 ではうまくいかない hwnd_hsp=hwnd *mainloop wait 1 hwnd_curwin=GetForegroundWindow() ; 現在アクティブなウィンドウのハンドル if hwnd_curwin { GetWindow hwnd_curwin, GW_OWNER if stat != 0 : hwnd_curwin=stat if hwnd_cur != hwnd_hsp { pid1 = 0 : id1 = GetWindowThreadProcessId(hwnd_curwin,varptr(pid1)) ; 現在アクティブなウィンドウを作成したスレッドID pid2 = 0 : id2 = GetWindowThreadProcessId(hwnd_hsp,varptr(pid2)) ; 目的のウィンドウのスレッドIDを取得 AttachThreadInput id2,id1,1 ; 目的のウィンドウのスレッドの入力処理機構をアクティブなウィンドウを作成したスレッドにアタッチ SetForegroundWindow hwnd_hsp ; 目的のウィンドウを前面に ( 実際には SetActiveWindow → FlashWindowEx を呼び出してユーザーに通知する) AttachThreadInput id2,id1,0 ; デタッチ GetWindowPlacement hwnd_hsp, varptr(str_WINDOWPLACEMENT) if str_WINDOWPLACEMENT(2) == SW_SHOWMINIMIZED { ; ウィンドウは最小化表示状態 SendMessage hwnd_hsp, WM_SYSCOMMAND, SC_RESTORE, 0 } } } goto *mainloop



ONION software Copyright 1997-2023(c) All rights reserved.