モニタの電源を切る設定をして、モニタの電源が切れた状態のパソコンを、
イベント内で復帰させ、表示が出るようにしたいのですがうまくいきません。
検索するとSendMessageやmouse_eventで解決できるとの情報から
下記のような命令をタイマー内で実行しましたが
モニタは復旧しませんでした。
なおスクリーンセーバの解除は「SetCursorPos」で出来ております。
環境はXP ServicePack3のノートパソコンです。
// モニタのON/OFFをしてみる
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
// マウスを動かしたように見せかける
mouse_event(MOUSEEVENTF_MOVE,100,100,0, GetMessageExtraInfo() );
よろしくお願いします。
Vista,Desktop環境では問題なく動作することを確認しました。
procedure TForm1.Button1Click(Sender: TObject);
begin
//OFF=2, ON=-1, (省エネ=1)
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
sleep(3000);
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
end;
レスありがとうございます。
しかし試したところ、やはり画面は復帰しません。
>procedure TForm1.Button1Click(Sender: TObject);
ボタンイベントで試されたということは
キーを押した事で画面が復帰したのではないでしょうか?
こちらで試したソースです。
モニタの電源を切るを1分後に設定
Intervalを80000に設定したタイマーとボタンをフォームに設置
procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled := True;
end;
procedure TForm1.ScreenServerOff;
begin
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
sleep(3000);
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
ScreenServerOff();
end;
私の環境ではということですが、
実際には二種類チェックしました。
上記ソースで、ボタンを押して何もしない。
Windowsの自動的にモニタの電源を切る(1分)で
1分30秒後にモニタの電源を入れる指令をタイマーで走らせ何もしない。
いずれも、モニタの電源はOFFからONに切り替わりました。
おそらく、関数的には目的の動作を果たしていると思われます。
もちろんモニタOFF中にマウスを動かしたり等はしていません。
モニタの電源OFFと言っても、No signalの事で物理的にモニタの電源が切れるわけではありません。(当然ですが)
ボタンクリックイベントの件、こちらの勘違いだったようで申し訳ないです。
上記サンプルを何度か試したところ
「時々表示が復帰する」
という現象でした。さらに復帰しても1秒後にはモニタOFFに
なってしまいます。
検索すると同じ悩みを持ち、解決に至った人がいましたので
http://d.hatena.ne.jp/NyaRuRu/20080925/p1
同じようにWindowsMessageの停止ができないか処理を考えてみる事にします。
解決までもう少々時間ください。
Windowsメッセージを奪っても今度は再度1分後に自動で電源をOFFするのが
困難なようです。
kernel32.dll内のSetThreadExecutionStateを呼ぶのが最も理想の動作で
あったため、作成してみました。
kernel32.dllが無いと起動すらしなくなるのが嫌なので
動的DLLで呼び出していますが
実際はたった1命令で済ませる事もできそうです。
自己解決してしまいましたが、様々な助言を頂いた事、感謝いたします。
// SetThreadExecutionState APIの引数
const
ES_CONTINUOUS = $80000000;
ES_SYSTEM_REQUIRED = $00000001;
ES_DISPLAY_REQUIRED = $00000002;
type TSetThreadExecutionState = function(esFlags: DWORD): DWORD; stdcall;
type
TScreenSaverCtrl = class(TPersistent)
private
{ Private 宣言 }
FDllHandle : THandle; // 動的ロードしたDLLのハンドル
FExecutionState : TSetThreadExecutionState;
public
{ Public 宣言 }
constructor Create;
destructor Destroy;override;
// 画面の表示が必要な場合の処理
function Require() : Boolean;
end;
implementation
{ TScreenSaverCtrl }
constructor TScreenSaverCtrl.Create;
begin
FDllHandle := LoadLibrary('kernel32.dll'); // DLLを動的ロード
if FDllHandle = 0 then begin // 失敗した場合
// 必要であればエラー処理
raise Exception.Create('kernel32.DLL が見つかりません'); // エラーとして通知
exit;
end;
@FExecutionState := GetProcAddress(FDllHandle,'SetThreadExecutionState');
if @FExecutionState = nil then begin
// 必要であればエラー処理
//raise Exception.Create('SetThreadExecutionState' + ' が見つかりません');
exit;
end;
end;
destructor TScreenSaverCtrl.Destroy;
begin
if FDllHandle <> 0 then begin
FreeLibrary(FDllHandle);
end;
inherited;
end;
function TScreenSaverCtrl.Require: Boolean;
begin
result := False;
if @FExecutionState = nil then exit;
FExecutionState(ES_DISPLAY_REQUIRED);
result := True;
end;
解決チェックし忘れました。
ツイート | ![]() |