Hatena::Groupnadesiko

雪乃☆雫のなでしこ日和

2016/11/20 (日)

プレビューは難しいよ!

| 22:44 | プレビューは難しいよ! - 雪乃☆雫のなでしこ日和 を含むブックマーク はてなブックマーク - プレビューは難しいよ! - 雪乃☆雫のなでしこ日和 プレビューは難しいよ! - 雪乃☆雫のなでしこ日和 のブックマークコメント

 引き続き、スクリーンセーバーです。

 コンフィグで設定するほどのことは別に何も無いのだけど、設定ボタンを押しても何も動かないとゆうのはちょっとあれなんで、いつものバージョン情報でも表示させておくことにするw

#-----------------------------------------------------------
*コンフィグ
  ダイアログタイトルは「スクリーンセーバーサンプル」
  「{二重カッコ}スクリーンセーバー{改行}    ~実験中~{二重カッコ閉じ}{改行}   Version 0.00{改行}{改行}   by 雪乃☆雫」と言う。
  終わる。
#-----------------------------------------------------------

 忘れず最後は「終わる」で終わらせないと、単にOKを押してダイアログが消えても、プログラムは終わってないんで、スクリーンセーバーの設定ウィンドウの、ボタンの有効がオフになったような状態で止まってしまう。

 ふつーのアプリと違って、設定画面で何か設定したとしても、の後プログラム自体を終了させて、スクリーンセーバーは「/s」で再起動ってことになってるから、設定の内容はの都度iniか何かに保存しておかないとダメらしい。



 次に、プレビューのミニ画面なんですが、これがまあ、とんでもない曲者でした。

 HSPじゃ、何も考えずに出来たよーに思うんだけど・・・

 あれは、HSPのなかで、なんか勝手にどうにかしてくれることになっているんだろうね???

 取りあえず、いろいろ調べて分かったのは、起動オプション「/p」で起動する時は、「コマンドライン¥2」に、あのミニ画面のハンドルがはいるとゆうこと。

 なるほど、あのナゾの数字は、ーゆうことだったのね。

 のハンドルの、「窓ハンドル内サイズ取得」と「窓ハンドル画面座標計算」で、いちおうミニ画面のサイズと位置は取得できるんだけど・・・

 の前にっ! 絶対やらなきゃいけないことがありました。

 こいつ、「スクリーンセーバーの設定」画面が開く時に起動するだけじゃ無いんです。

 設定ボタンを押した時、プレビューボタンを押した時、それから、コンボボックスで別のスクリーンセーバーを選んだ時、いちいち終わらせるようにしないことには、次に復帰する時に、また「/p」オプションでスクリーンセーバーを再起動しやがるのです!

 「終わる」だけを入れてた時は良かったんだけど・・・あっというに沢山のスクリーンセーバーが密かに起動してて、「システムリソースがありません」かなんか怒られてしまった><

 こは、取りあえずこんな感じに。

#-----------------------------------------------------------
  #二重起動の防止。
  プレビュータイトルとは文字列=「スクリーンセーバーサンプルのぷれびゅー画面」 #他とは容易にかぶらなそうなタイトルを指定のこと。
  窓列挙。一時=それ。
  一時の2で0からプレビュータイトルを表検索。
  もしそれ=-1でなければ、終わる。
  母艦のタイトルはプレビュータイトル
#-----------------------------------------------------------

 起動してるヤツを終わらせると言うより、新しく起動した時に、自分と同じタイトルの窓が既にあったら、もう起動してると判断して起動ないことにする的な感じ。

 でも、なんかそれだけじゃダメな気がする・・・けど、一応エラーは出なくなった。


 さて・・・

#-----------------------------------------------------------
  #「スクリーン セーバーの設定」画面内のプレビューウィンドウ(ミニ画面)の情報を取得。
  PS=PWHの窓ハンドル内サイズ取得。
  Pxy=PWHの0,0を窓ハンドル画面座標計算。

  #母艦にプレビューウィンドウの位置サイズを設定
  母艦のスタイルは「枠なし」
  母艦のクライアント幅はPS¥0,2。
  母艦のクライアント高さはPS¥0,3。
  母艦の位置は「{Pxy¥0,0},{Pxy¥0,1}」

  #プレビューウィンドウに実際に表示するもの
  母艦デスクトップ色画面クリア。
  「プレビュー」を表示。
  母艦の可視はオン
#-----------------------------------------------------------

 こんなふうに、サイズと位置をミニ画面に合わせてつくってみたんだけど・・・

 ばっちり希望の場所に、小さい画面が表示されることはされるんだけど、よく考えたらこれでは全くダメで、スクリーンセーバーの設定画面が動いたり、他のウィンドウの下に隠れたりしたら、このちっちゃい母艦のままの場所に残ってしうまうのですよ~(´д`;

 親部品に設定出来るのは、なでしこで作ったヤツだけだしなー・・・と思っていたら、

http://www26.atwiki.jp/isoroku_be/pages/66.html

 ここに、なでしこで作ったヤツじゃ無いウィンドウを親部品にしたり、子部品にしたりする術がありました!

 素晴らしい!!!


 ところが・・・

 どーゆうわけか、位置の設定が上手くいかないんです。

 色々位置を言わせてみるとどうやら、Xの位置だけを設定した時はいいんですが、Yの位置を設定すると、反映されるのはYの位置だけで、Xの位置があらぬところにずれてしまう。

 これは一体!?!?

 むむむむぅ・・・

うぇいくうぇいく2016/11/21 20:37なでしこの部品の場合、内部でいろいろ情報持っていたり補正したりしているので、単純に親を設定してもうまくゆかない可能性が高いです。部品とAPIと併用するのは結構高難易度になります。
なでしこ内部・・・というより、その実行言語であるDelphiのライブラリのソースを読んで原因を探るぐらいじゃないと厳しいかと思います(なぜか、Delphiは製品にライブラリのソースが付属している。)
ライブラリも一応の考慮はされているので、うまくゆく時もあるので、その時は、それに乗ってしまうのも手ですが、うまくゆかないときは厳しいです。

スクリーンセーバー作成のpluginがあってもよさそうですが、なでしこの場合、フォルダに置いてあると必ず読み込まれちゃうんですよね・・・

雪乃☆雫雪乃☆雫2016/11/22 02:51うぇいくさま、ありがとうございます!
やはり、なかなか難しいことなのですね。
なにしろ、APIも借り物で、Delphiなんてとてもとても~>< ・・・という頭脳なので;;;
しかし、とりあえず、位置の指定ではなく全画面にすることで、なんとなくうまくいきそうな気配です☆

スクリーンセーバー作成のpluginがあったら嬉しかったですが、今となっては、スクリーンセーバー自体がもう、今さらな感じですもねー。
このミニ画面は、スクリーンセーバー的には一番どーでもよい機能なのですが、出来そう感が出てきたので、もう少し捨てずに粘ってみます・・

うぇいくうぇいく2016/11/22 23:39非常に長くて、大変申し訳ないのですが、以下のような感じで試してました。
よくわからないのですが、書かれている構成に似せて2ファイル構成です。

プレビュー時は、もらったハンドルが無効になるか非表示になったら終われば良い模様(それまでは本来の動作のようにアニメーションを繰り返しておく)

・・・あれ?プロセスを跨ぐとハンドル類は無効になったような気がするので、ドライバ側の実装は間違えているかも?(別プロセスに渡す場合は、相手プロセス用のハンドルを生成しないといけなかったような )

スクリーンセーバーテストドライバ.nako
--------------
'スクリーンセーバーテストドライバ

#窓ハンドル親設定の実験
プレビューエリアとはパネル。

母艦のタイトル=「親ウィンドウ」。
母艦の幅は300。母艦の高さは300。
プレビューエリアの幅は200。プレビューエリアの高さは200。
プレビューエリアのXは10。プレビューエリアのYは10。
母艦の可視はオン。プレビューエリアの可視はオフ。


プレビューボタンオンとはボタン
プレビューボタンオンの親部品は母艦
プレビューボタンオンのXは10
プレビューボタンオンのYは220
プレビューボタンオンのWは120
プレビューボタンオンのテキストは「プレビュー表示」
プレビューボタンオンのクリックした時は~
 プレビューエリアの可視はオン。
 「vnako.exe スクリーンセーバー.nako /p {プレビューエリアのハンドル}」を起動

プレビューボタンオフとはボタン
プレビューボタンオフの親部品は母艦
プレビューボタンオフのXは150
プレビューボタンオフのYは220
プレビューボタンオフのWは120
プレビューボタンオフのテキストは「プレビュー非表示」
プレビューボタンオフのクリックした時は~
 プレビューエリアの可視はオフ。
---------------------

スクリーンセーバー.nako
---------------------
'スクリーンセーバー
!変数宣言は必要
!変数初期化は必要

#-----------------------------------------------------------
●母艦設計
 母艦のタイトル=「親ウィンドウ」。
 母艦の可視はオフ

一時描画エリアとはイメージ
一時描画エリアの可視はオフ

プレビューハンドルとは整数
プレビューハンドルはコマンドライン¥2

HDCとは整数
HDCはGetDC(プレビューハンドル)

Sとは文字列
プレビュー幅とは整数
プレビュー高さとは整数
Sに16を確保
// 結果はSにLEFT,TOP,RIGHT,BOTTOMの構造体(全部long型)の内容が入る
GetWindowRect(プレビューハンドル, POINTER(S))
プレビュー幅は(Sの9を`LONG`でバイナリ取得)-(Sの1を`LONG`でバイナリ取得)
プレビュー高さは(Sの13を`LONG`でバイナリ取得)-(Sの5を`LONG`でバイナリ取得)

一時描画エリアの幅はプレビュー幅
一時描画エリアの高さはプレビュー高さ

(IsWindowVisible(プレビューハンドル)!=0)の間、
 // 一時描画エリアに描画する
 スクリーン描画(一時描画エリア)
 // 一時描画エリアの内容をプレビューのエリアに転写する
 // SRCCOPY=$00CC0020 元から先へ上書きコピー
 BitBlt(HDC,0,0,プレビュー幅,プレビュー高さ,一時描画エリアのハンドル,0,0,$00CC0020)
 0.05秒待つ

ReleaseDC(プレビューハンドル,HDC)

終わり

●スクリーン描画({グループ}描画対象)
 描画対象を赤色で画面クリア

●ReleaseDC(hWnd,hDC)=DLL("user32.dll",
"int ReleaseDC(
HWND hWnd, // ウィンドウのハンドル
HDC hDC // デバイスコンテキストのハンドル
)")

●IsWindowVisible(hWnd)=DLL("user32.dll",
"BOOL IsWindowVisible(
HWND hWnd // ウィンドウのハンドル
)")

●GetWindowRect(hWnd,lpRect)=DLL("user32.dll",
"BOOL GetWindowRect(
HWND hWnd,
LPRECT lpRect
)")

●BitBlt(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop)=DLL("gdi32.dll",
"BOOL BitBlt(
HDC hdcDest, // コピー先デバイスコンテキストのハンドル
int nXDest, // コピー先長方形の左上隅の x 座標
int nYDest, // コピー先長方形の左上隅の y 座標
int nWidth, // コピー先長方形の幅
int nHeight, // コピー先長方形の高さ
HDC hdcSrc, // コピー元デバイスコンテキストのハンドル
int nXSrc, // コピー元長方形の左上隅の x 座標
int nYSrc, // コピー元長方形の左上隅の y 座標
DWORD dwRop // ラスタオペレーションコード
)")

●GetDC(hWnd)=DLL("user32.dll",
"HDC GetDC(
HWND hWnd // ウィンドウのハンドル
)")
----------------

雪乃☆雫雪乃☆雫2016/11/23 03:02はわわわわわ・・・
一人で勝手に騒いでいるだけでしたのに、こんなにまでして頂いて、本当にありがとうございます!!!
しかし~、今のところ中身が全く分からない~(泣)
MSDNながめて、目が回る~~~(@_@)
でも、今日苦労してなんだかんだした件や、どうしたら良いのか全く分からんと放置した一件が、IsWindowVisibleを使ったら、あっさり解決しそうということだけは閃きました;
こんなにAPIを使いまくらないとならないとは、プレビュー画面恐るべし・・・
ちょっとまた考え直してみます~。

トラックバック - http://nadesiko.g.hatena.ne.jp/snowdrops89/20161120