実現したいこと
「スクリーンセーバーがかかっている」かつ「フラグがON」のとき,「スクリーンセーバーを解除したい」です.
困っていること
現状,スクリーンセーバーの状態取得は「SystemParametersInfo」で,スクリーンセーバーの解除方法を下記二つで試しましたが,解除されなくて困っています.
1. SetCursoPos(x, y)でカーソルを任意の位置に移動
2. keybd_evnetでキーボードを押す/離す
修正後のソースコードでもスクリーンセーバーが解除しません.現状,スクリーンセーバーになることは確認しました.また,hdesk = OpenDesktop(L"Screen-saver", 0, FALSE, GENERIC_ALL);にbreakを貼って一行上の「hdesk = OpenDesktop(L"Screen-saver", 0, FALSE, GENERIC_ALL);の「hdesk」の状態をIDEのインスペクトで見てみると「????」となっていました.「OpenDesktop」について調べた結果,「Window Stationとデスクトップ - kkAyatakaのメモ帳。」に「OpenDesktop」は「WPFではうまくいかない.」とありました.WPFのことをあまり分かっていないのですが,C++Builderで作成したアプリケーションは「VCLアプリケーション」であり,WPFであるから大丈夫なのではないでしょうか?ご教授お願いいたします.
別に試したことは,C++BuilderのVCLアプリケーションが原因の可能性があるとおもったので,「screensaver.cpp」を作成後.C++Builderのコンパイラ(bcc32.exe)でコンパイルして実行した結果,下記のようになりました.
1. whileの中で「screenSaver」のみをコールした時はスクリーンセーバー抑止を確認.
2. whileの中で「SystemParametesInfo」の第三引数の状態が「true」なら「screenSaver」をコールした時はスクリーンセーバーはかかるが,スクリーンセーバーが解除されないことを確認.
「SystemParametersInfo」の使い方が間違っているのでしょうか?
修正後の「screensaver.cpp」ではbcc32.exeでコンパイルするときに「-tWM」オプションを付ければ,任意の動作(スクリーンセーバーがかかったあと,5秒後に解除される)になることを確認しました.
なので,その処理をC++Builder上で実現するために「Unit1.cpp」と「Unit1.h」を修正後,「Unit2.cpp」と「Unit2.h」を追加してC++Builder10.2のIDEでコンパイルしましたが次のエラーが出て困っています.
0. E2034 'void(void )'型は'void ()(void )'型に変換できない
0. E2342 パラメータ'__start’はvoid ()(void *)型として定義されているのでvoid(__fastcall *)(void *)は渡せない
確認したこと(試したこと)
1. 「keybd_event( VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0 );」にbreakを貼ってスクリーンセーバー後,5秒待っても解除されない(その後,マウスを動かしてスクリーンセーバーを解除.breakを貼った個所に処理が到達していることを確認.)
2. 1ではbreak時にまだ「keybd_event」処理を実行していないからその下の「ShowMessage("スクリーンセーバー解除したよ");」にbreakに貼ってスクリーンセーバー後,5秒待っても解除されない.
3. ボタンイベント実行時に「SetCursorPos」でマウスカーソル位置が指定位置に移動している.
###原因または解決方法
【原因】
「SetCursorPos」や「keybd_event」はWindows32APIだから64bitOSでは動作しないのではないか?でも,そうするとスクリーンセーバーがかかっていないときにボタンイベントで「SetCursorPos」でマウスカーソル位置が指定位置に移動していることが不思議でなりません.WIN32APIだから,スクリーンセーバーがかかていないときに使えても,スクリーンセーバーかかているときは使えないって言われれば,納得するのですが.
【解決方法】
リアルタイムでマウス座標を取得して,「スクリーンセーバーがかかっている」かつ「5秒後」のときに「マウスカーソルを移動する」でスクリーンセーバーを解除できると思っています.
リアルタイムでマウス座標を取得方法は分かりました(TPoint型のMouse->CursorPos).また,任意のマウス位置を設定する方法(SetLocation(x, y)メソッド)も分かりました.その後,マウスカーソルを移動する方法が分かりません.ご教授お願いいたします.
下記ソースの開発環境
OS:Windows10 64bit
IDE:Embarcadero® C++Builder 10.2
言語:C++
実際に実現するPCの開発環境(参考情報)
OS:Windows10 64bit
IDE:Embarcadero® C++Builder 10.3
言語:C++
開発環境のバージョンのみ異なります.
修正後のソースコード
「注意点」
「スクリーンセーバーがかかっている」かつ「フラグがON」のとき,「スクリーンセーバーを解除したい」と書きましたが,このソースコードではスクリーンセーバーがかかっているときに「フラグON」にすることができないので,「スクリーンセーバーがかかっている」かつ「5秒後」の条件でコーディングしています.
<Unit1.cpp>
C++
1//--------------------------------------------------------------------------- 2 3#include <vcl.h> 4#pragma hdrstop 5// コンパイルオプションの追加 6#pragma checkoption -tWM 7 8#include "unit1.h" 9#include "Unit2.h" 10#include <windows.h> 11#include <process.h> 12//--------------------------------------------------------------------------- 13#pragma package(smart_init) 14#pragma resource "*.dfm" 15TForm1 *Form1; 16//--------------------------------------------------------------------------- 17__fastcall TForm1::TForm1(TComponent* Owner) 18 : TForm(Owner) 19{ 20 cnt = 0; 21 screensaver = false; 22 Form1->Left = (Screen->Monitors[0]->Width / 2) - (Form1->Width / 2); 23 Form1->Top = (Screen->Monitors[0]->Height / 2) - (Form1->Height / 2); 24 memset( &hdesk, 0, sizeof(HDESK) ); 25 memset( &hdesk_old, 0, sizeof(HDESK) ); 26} 27//--------------------------------------------------------------------------- 28void __fastcall TForm1::Timer1Timer(TObject *Sender) 29{ 30 int x = 0; 31 int y = 0; 32 33 x = Form1->Width / 2; 34 y = Form1->Height / 2; 35 pt = Mouse->CursorPos; 36 37 Label1->Caption = "X座標:" + IntToStr((int)pt.X) + ", Y座標:" + IntToStr((int)pt.Y); 38 39 SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, (void *)&screensaver, 0); 40 if( screensaver == true) 41 { 42 // 5秒後(周期は500ms) 43 if( cnt >= 10 ) 44 { 45 // ウィンドウを作成するとSetThreadDesktopできないのでスレッドを起動 46 _beginthread(screenSaver, 0, NULL); 47 48 cnt = 0; 49 } 50 cnt++; 51 } 52} 53//--------------------------------------------------------------------------- 54void __fastcall TForm1::Button1Click(TObject *Sender) 55{ 56 int x = 0; 57 int y = 0; 58 59 x = Form1->Width / 2; 60 y = Form1->Height / 2; 61 SetCursorPos(x, y); 62} 63//--------------------------------------------------------------------------- 64
<Unit1.h>
C++
1//--------------------------------------------------------------------------- 2 3#ifndef Unit1H 4#define Unit1H 5//--------------------------------------------------------------------------- 6#include <System.Classes.hpp> 7#include <Vcl.Controls.hpp> 8#include <Vcl.StdCtrls.hpp> 9#include <Vcl.Forms.hpp> 10#include <Vcl.ExtCtrls.hpp> 11//--------------------------------------------------------------------------- 12class TForm1 : public TForm 13{ 14__published: // IDE で管理されるコンポーネント 15 TTimer *Timer1; 16 TLabel *Label1; 17 TButton *Button1; 18 void __fastcall Timer1Timer(TObject *Sender); 19 void __fastcall Button1Click(TObject *Sender); 20private: // ユーザー宣言 21public: // ユーザー宣言 22 __fastcall TForm1(TComponent* Owner); 23 24 TPoint pt; 25 bool screensaver; 26 int cnt; 27 HDESK hdesk; 28 HDESK hdesk_old; 29}; 30//--------------------------------------------------------------------------- 31extern PACKAGE TForm1 *Form1; 32//--------------------------------------------------------------------------- 33#endif
<Unit2.cpp>
c++
1//--------------------------------------------------------------------------- 2 3#pragma hdrstop 4 5#include "unit1.h" 6#include "Unit2.h" 7#include <windows.h> 8#include <process.h> 9//--------------------------------------------------------------------------- 10#pragma package(smart_init 11 12//--------------------------------------------------------------------------- 13//void __fastcall screenSaver(void *) 14void __fastcall screenSaver(void *a) 15{ 16 // 元のデスクトップハンドルを退避 17 hdesk_old = GetThreadDesktop(GetCurrentThreadId()); 18 19 // スクリーンセーバーのデスクトップを開く 20 hdesk = OpenDesktop(L"Screen-saver", 0, FALSE, GENERIC_ALL); 21 if( hdesk != NULL ) 22 { 23 // 現在のスレッドのデスクトップを変更 24 SetThreadDesktop(hdesk); 25 } 26 27 // スクリーンセーバー解除処理(キーボードの押す/離す) 28 keybd_event( VK_ESCAPE, 0, 0, 0 ); 29 keybd_event( VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0 ); 30 31 // 元のデスクトップに戻す 32 SetThreadDesktop(hdesk_old); 33 if( hdesk != NULL ) 34 { 35 CloseDesktop(hdesk); 36 } 37} 38//---------------------------------------------------------------------------
<Unit2.h>
c++
1//--------------------------------------------------------------------------- 2 3#ifndef Unit2H 4#define Unit2H 5//--------------------------------------------------------------------------- 6 7// スクリーンセーバー解除 8void __fastcall screenSaver(void *); 9 10//--------------------------------------------------------------------------- 11#endif
<screensaver.cpp>
c++
1// 標準ヘッダー宣言 2#include <Windows.h> 3#include <process.h> 4 5// プロトタイプ宣言 6LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 7char szClassName[] = "ウィンドウクラス・ネーム"; 8void screenSaver(void *a); 9 10int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, 11 LPSTR lpszCmdLine, int nCmdShow) 12{ 13 HWND hWnd; 14 MSG msg; 15 WNDCLASS myProg; 16 bool screensaver; 17 HDC hdc; 18 PAINTSTRUCT ps; 19 20 // ウィンドウ・クラスの登録 21 if( !hPreInst ) 22 { 23 myProg.style = CS_HREDRAW | CS_VREDRAW; 24 myProg.lpfnWndProc = WndProc; // プロシージャ名 25 myProg.cbClsExtra = 0; 26 myProg.cbWndExtra = 0; 27 myProg.hInstance = hInstance; // インスタンス 28 myProg.hIcon = NULL; 29 myProg.hCursor = LoadCursor(NULL, IDC_ARROW); 30 myProg.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 31 myProg.lpszMenuName = NULL; 32 myProg.lpszClassName = szClassName; 33 if( !RegisterClass(&myProg) ) 34 { 35 return (false); 36 } 37 } 38 39 // ウィンドウの生成 40 hWnd = CreateWindow(szClassName, 41 "猫でも分かるプログラミング", // タイトルバーにこの名前が表示される 42 WS_OVERLAPPEDWINDOW, // ウィンドウの種類 43 CW_USEDEFAULT, // X座標 44 CW_USEDEFAULT, // Y座標 45 CW_USEDEFAULT, // 幅 46 CW_USEDEFAULT, // 高さ 47 NULL, // 親ウィンドウのハンドル,親を作るときはNULL 48 NULL, // メニューハンドル,クラスメニューを使うときはNULL 49 hInstance, // インスタンスハンドル 50 NULL); 51 ShowWindow(hWnd, nCmdShow); 52 UpdateWindow(hWnd); 53 while( GetMessage(&msg, NULL, 0, 0) ) 54 { 55 TranslateMessage(&msg); 56 DispatchMessage(&msg); 57 // 下記モジュールのみをコールするだけだとスクリーンセーバーがかからないので, 58 // スクリーンセーバーの抑止(キーボードの押す/離す)していることを確認 59// screenSaver(hWnd); // スクリーンセーバーの解除 60 61 // スクリーンセーバー状態の取得 62 SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, (void *)&screensaver, 0); 63 // スクリーンセーバーが有効の場合 64 if( screensaver == true ) 65 { 66 // 5秒後 67 Sleep(5000); 68 69 // ウィンドウを作成するとSetThreadDesktopできないのでスレッドを起動する. 70 _beginthread(screenSaver, 0, NULL); 71 } 72 } 73 return (int)msg.wParam; 74} 75 76// ウィンドウプロシージャ 77LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 78{ 79 switch(msg) 80 { 81 case WM_DESTROY: 82 PostQuitMessage(0); 83 break; 84 default: 85 return (DefWindowProc(hWnd, msg, wParam, lParam)); 86 } 87 88 return (0L); 89} 90 91void screenSaver(void *a) 92{ 93 // 元のデスクトップハンドルを退避 94 HDESK hdesk_old = GetThreadDesktop(GetCurrentThreadId()); 95 // スクリーンセーバーのデスクトップを開く 96 HDESK hdesk = OpenDesktop("Screen-saver", 0, FALSE, GENERIC_ALL); 97 if( hdesk != NULL ) 98 { 99 // 現在のスレッドのデスクトップを変更 100 SetThreadDesktop(hdesk); 101 } 102 // スクリーンセーバー解除処理 103 keybd_event(VK_ESCAPE, 0, 0, 0); 104 keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); 105 106 // 元のデスクトップに戻す 107 SetThreadDesktop(hdesk_old); 108 if( hdesk != NULL ) 109 { 110 CloseDesktop(hdesk); 111 } 112 113} 114
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/05/11 06:29 編集
2019/05/11 06:52 編集
2019/05/11 07:35 編集
2019/05/11 07:32
2019/05/11 08:27 編集
2019/05/11 16:30
2019/05/11 17:53
2019/05/12 10:49
2019/05/12 10:58
2019/05/12 11:32
2019/05/12 11:58