!!!デュアルディスプレイ環境でのスクリーンセーバー作り with HSP !!はじめに:HSPとスクリーンセーバー HSPでの売りの一つに、「スクリーンセーバーが非常に簡単に作れる」というのがあります。 実は、スクリーンセーバーは動かすまでにいろいろ面倒な手続きが必要だったりする{{fn 確か…}}のですが、 HSPではその多くを肩代わりしてくれます。 HSPでスクリーンセーバーを作るときに守るべきルールは少しだけ。 *(基本的に)bgscr命令を使い、全画面サイズのウィンドウを作る。(で、そこに描画する) *ループする場合(repeat-loopに限らず、途中で停止しない場合)には、必ずwait/awaitを入れる。 **このとき、早い段階で約20回以上のwait/await命令が発行されるようにすること。HSP製スクリーンセーバーは、一定回数以上wait/awaitが発行されないと、終了処理を行いません。 このうち、「bgscrで全画面ウィンドウ作成」が、意外と罠なので以下で解説しています。 !!1:ディスプレイと仮想画面 デュアルディスプレイ環境の場合、2個以上の画面を組み合わせて一つの大きな画面として使用することが出来ます。 このとき、仮想画面の大きさや位置は実際のディスプレイの配置{{fn 正確には、その配置にあわせて設定されたWindows上での画面配置設定}}によって変化するわけですが、 スクリーンセーバーとして画面を覆いつくそうと思ったら、当然その仮想画面を全て覆わなくてはなりません。 {{ref_image ddw.png}} この画像で言う、赤い枠が仮想画面です。 ところが、通常画面表示の大きさを取得するための関数であるginfoでは、メインで使用している画面の大きさしか取得できません。 !!2:仮想画面の大きさを取得する そこで、WinAPIを使って仮想画面の大きさを取得します。使うAPIはGetSystemMetrics()です。 {{code HSP,8,1 #uselib "user32.dll" #func GetSystemMetrics "GetSystemMetrics" sptr }} この引数にいろんなものを渡すといろんなデータが取得できますが、指定できる定数には限りがあります。 ここでは、仮想画面の幅や高さを取得する値を用意します。 {{code HSP,8,5 #define SM_CXVIRTUALSCREEN $0000004E #define SM_CYVIRTUALSCREEN $0000004F }} こんな風にして使うわけです。 {{code HSP,8,11 GetSystemMetrics SM_CXVIRTUALSCREEN:XX=stat GetSystemMetrics SM_CYVIRTUALSCREEN:YY=stat }} !!3:仮想画面の位置を取得する さて、さっきまでで画面の大きさが取得できたわけですが、そのままbgscrを使ってウィンドウを作っても、 うまく画面全体を覆うことは出来ません。 {{ref_image ddw2.png}} こんな感じになっちゃいます。 灰色の部分が作ったウィンドウ。画面2の一部が露出したままであることが分かります。 これは、(画像にも書いてますが)座標0,0が、「仮想画面の左上座標」'''ではなく'''、「メインディスプレイの左上の座標」であることが要因です。 解決方法はさっきと同じで、GetSystemMetrics()を使ってメインディスプレイの左上座標を基準とした、仮想画面の 左上の座標(2枚目の画像の[●]の位置のこと)を取得すればOKです。 {{code HSP,8,3 #define SM_XVIRTUALSCREEN $0000004C #define SM_YVIRTUALSCREEN $0000004D }} こんな風に定義しておいて、 {{code HSP,8,9 GetSystemMetrics SM_XVIRTUALSCREEN:DEFXX=stat GetSystemMetrics SM_YVIRTUALSCREEN:DEFYY=stat }} こうすれば取得できます。 で、仕上げにbgscrを実行すれば晴れて画面全体を覆うことが出来ます。晴れてるのに覆うってのもあれですが。 {{code HSP,8,13 bgscr 2,XX,YY,0,DEFXX,DEFYY }} !!余談 サンプルで文字を表示する位置の指定に {{code HSP,8,14 pos DEFXX*-1,DEFYY*-1 }} としています。これは、bgscrで作成したウィンドウの左上の座標が(例のような配置であれば)メインディスプレイの外側に 位置することになるため、それを補正する目的で入れています。