No.1ベストアンサー
- 回答日時:
>WinXPとVB.NETで休止やスタンバイのイベントを受け取るには?
WndProc (WindowsProcとも言われたりします)
を利用します。
ただ、これはシステムフックをする事になるので、ここでは
1・重い負荷を与える処理
2・ユーザからの入力を待機する処理
はご法度です!!
もしそのような処理を入れた場合、
1・システムが次の処理を走らすことができず、動作が不安定になる
2・システムが次の処理を走らすために、アプリ側で捕まえられた処理をタイムアウトとして扱い、アプリ側の変更を受け付けなくなる
という事がありえます。
これを回避するには処理を分割しましょう。↓にまとめます。
1.休止orサスペンド要求イベントを認識する
2.休止orサスペンド要求イベントの継続を破棄する
3.ユーザに休止orサスペンドがあったことを通知する
4.ユーザに休止orサスペンドを行うかを問い合わせをする
5.ユーザへの問い合わせ結果によって、処理を行う
参考[休止状態/サスペンドの破棄]を応用
http://www.microsoft.com/japan/msdn/vbasic/migra …
参考[休止状態/サスペンドの実行]を応用
http://www.vbvbvb.com/jp/gtips/0301/gSetSystemPo …
そこで問題となるのが、休止orサスペンドのどちらの要求が送られてきているのかがわからないということです。こればかりは仕方がありません。
なので、どのような処理にするかはユーザに任せてしまうか、サスペンド限定するなどの対応が必要になります。
電源イベント通知を即座に行わず、後で通知する方法は、私の場合であれば、タイマを利用する方法しか思いつきませんが、もっとよい方法があるかも知れません。
以下が、サンプルです。
WindowsApplication1.vbproj
├Form1.vb(コントロールは、何も置かないでいいです)
└Class1.vb
※Form1.vb
--------------------------------------------------------------------------------
Public Class Form1
Inherits System.Windows.Forms.Form
Private WithEvents m_obj休止 As New 休止監視()
Private m_objListデバッグ用 As New ListBox()
#Region " Windows フォーム デザイナで生成されたコード "
~~~ここは略します~~~
#End Region
'イベント/フォーム/ロード
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'デバッグ用のリストボックスの初期設定
Me.Controls.Add(m_objListデバッグ用)
m_objListデバッグ用.Size = Me.ClientSize
End Sub
'イベント/休止オブジェクト/発生処理
Private Sub obj休止_発生処理(ByVal モード As 休止監視.処理モード) Handles m_obj休止.発生処理
'発生したイベント内容をデバッグ用リストボックスに追加
Dim l_strワーク As String = IIf(モード = 休止監視.処理モード.再開, "再開", "休止")
m_objListデバッグ用.Items.Add(System.DateTime.Now.ToString & " " & l_strワーク)
m_objListデバッグ用.SelectedIndex = m_objListデバッグ用.Items.Count - 1
End Sub
'イベント/休止オブジェクト/発生通知
Private Sub obj休止_発生通知(ByRef モード As 休止監視.休止モード) Handles m_obj休止.発生通知
'サスペンドor休止状態が起ころうとしたことを通知
'さらに、遂行する処理を返却する
Dim l_msgRet As Microsoft.VisualBasic.MsgBoxResult
Dim l_strMsg As String = ""
l_strMsg &= "は い: サスペンド" & vbCrLf
l_strMsg &= "いいえ: 休止状態" & vbCrLf
l_strMsg &= "CANCEL: 何もしない" & vbCrLf
l_msgRet = MsgBox(l_strMsg, MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question, "休止モード継続お知らせ")
Select Case l_msgRet
Case MsgBoxResult.Yes
モード = 休止監視.休止モード.サスペンド
Case MsgBoxResult.No
モード = 休止監視.休止モード.休止状態
Case MsgBoxResult.Cancel
モード = 休止監視.休止モード.未処理
End Select
End Sub
'イベント/システム/WindowsProc
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If Not m_obj休止.メッセージ処理(m) Then
Return
End If
MyBase.WndProc(m)
End Sub
End Class
※Class1.vb
--------------------------------------------------------------------------------
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Public Class 休止監視
#Region "属性"
Public Event 発生通知(ByRef モード As 休止モード)
Public Event 発生処理(ByVal モード As 処理モード)
#Region "定数"
Private Const WM_POWERBROADCAST As Integer = &H218
Private Const PBT_APMQUERYSUSPEND As Integer = &H0
Private Const BROADCAST_QUERY_DENY As Integer = &H424D5144
#End Region
#Region "型"
Private Structure tagLUID
Dim LowPart As Integer
Dim HighPart As Integer
End Structure
Private Structure LUID_AND_ATTRIBUTES
Dim Luid As tagLUID
Dim Attributes As Integer
End Structure
Private Structure TOKEN_PRIVILEGES
Dim PrivilegeCount As Integer
Dim Privileges As LUID_AND_ATTRIBUTES
End Structure
#End Region
#Region "列挙"
Public Enum 休止モード
未処理
サスペンド
休止状態
End Enum
Public Enum 処理モード
再開
休止
End Enum
#End Region
#Region "API"
<DllImport("advapi32.dll", SetLastError:=True)> _
Private Shared Function OpenProcessToken( _
ByVal ProcessHandle As IntPtr, _
ByVal DesiredAccess As Integer, _
ByRef TokenHandle As IntPtr _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Private Shared Function LookupPrivilegeValue( _
ByVal pSystemName As String, _
ByVal lpName As String, _
ByRef lpLuid As tagLUID _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Private Shared Function AdjustTokenPrivileges( _
ByVal TokenHandle As IntPtr, _
ByVal DisableAllPrivileges As Boolean, _
ByRef NewState As TOKEN_PRIVILEGES, _
ByVal BufferLength As Integer, _
ByVal PreviousState As IntPtr, _
ByVal ReturnLength As IntPtr _
) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function SetSystemPowerState( _
ByVal fSuspend As Boolean, _
ByVal fForce As Boolean _
) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function ExitWindowsEx( _
ByVal flag As Integer, _
ByVal reserved As Integer _
) As Boolean
End Function
#End Region
#End Region
#Region "メソッド"
#Region "メソッド_PUBLIC"
'サスペンドを行う
Public Sub 実行_サスペンド()
Call 実行_休止処理(True)
End Sub
'休止状態を行う
Public Sub 実行_休止状態()
Call 実行_休止処理(False)
End Sub
'WindowsProc処理
Public Function メッセージ処理(ByRef m As Windows.Forms.Message) As Boolean
Dim l_blnRet As Boolean = True
If (m.Msg = WM_POWERBROADCAST) And (m.WParam.ToInt32 = PBT_APMQUERYSUSPEND) Then
l_blnRet = False
'休止イベントの破棄
m.Result = New IntPtr(BROADCAST_QUERY_DENY)
'この中でイベントを発生させず、タイマを生成し、そのタイマイベント内部で処理を行う
Dim l_objタイマ As New tmpタイマ()
AddHandler l_objタイマ.Elapsed, AddressOf objタイマ_Elapsed
End If
Return l_blnRet
End Function
#End Region
#Region "メソッド_PRIVATE"
'休止処理メイン
Private Sub 実行_休止処理(ByVal l_blnサスペンド As Boolean)
Const TOKEN_QUERY As Integer = &H8
Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
Const SE_SHUTDOWN_NAME As String = "SeShutdownPrivilege"
Const SE_PRIVILEGE_ENABLED As Integer = &H2
Dim l_blnRet As Boolean
'// プロセスのハンドルを取得する。
Dim l_PronWnd As IntPtr = Diagnostics.Process.GetCurrentProcess().Handle
'// Token を取得する。
Dim l_TpkenWnd As IntPtr = IntPtr.Zero
l_blnRet = OpenProcessToken(l_PronWnd, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), l_TpkenWnd)
'// LUID を取得する。
Dim l_udtLuid As tagLUID
l_blnRet = LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, l_udtLuid)
'// 特権をセットする。
Dim tp As TOKEN_PRIVILEGES = New TOKEN_PRIVILEGES()
tp.PrivilegeCount = 1
tp.Privileges = New LUID_AND_ATTRIBUTES()
tp.Privileges.Luid = l_udtLuid
tp.Privileges.Attributes = SE_PRIVILEGE_ENABLED
l_blnRet = AdjustTokenPrivileges(l_TpkenWnd, False, tp, 0, IntPtr.Zero, IntPtr.Zero)
'休止処理実行
'第2引数をTRUEにすることで、強制実行
Call SetSystemPowerState(l_blnサスペンド, True)
End Sub
#End Region
#End Region
#Region "イベント"
#Region "イベント_定義"
'イベント/クラス/生成時
Public Sub New()
'システムの電源状態変化イベントを、内部メソッドへ引き込む
AddHandler SystemEvents.PowerModeChanged, AddressOf SystemEvents_PowerModeChanged
End Sub
'イベント/クラス/破棄時
Protected Overrides Sub Finalize()
MyBase.Finalize()
'システムの電源状態変化イベントを、内部メソッドからはずす
RemoveHandler SystemEvents.PowerModeChanged, AddressOf SystemEvents_PowerModeChanged
End Sub
#End Region
#Region "イベント_WindowsProc_PowerModeChanged"
'イベント/電源/状態変化時
Private Sub SystemEvents_PowerModeChanged(ByVal sender As Object, ByVal e As PowerModeChangedEventArgs)
Select Case e.Mode
Case PowerModes.Resume
RaiseEvent 発生処理(処理モード.再開)
Case PowerModes.Suspend
RaiseEvent 発生処理(処理モード.休止)
End Select
End Sub
#End Region
#Region "イベント_内部タイマ"
'イベント/タイマ/タイマ
Private Sub objタイマ_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
Dim l_objタイマ As tmpタイマ = CType(sender, tmpタイマ)
Dim l_休止モード As 休止モード = 休止モード.未処理
'イベントとの関連付けを切り離す
RemoveHandler l_objタイマ.Elapsed, AddressOf objタイマ_Elapsed
l_objタイマ.Dispose()
'問合せ中に、再度休止関連イベントが行われたとき対策
Static s_bln多重問合せ回避フラグ As Boolean = False
If s_bln多重問合せ回避フラグ Then
Return
End If
s_bln多重問合せ回避フラグ = True
'問い合わせを行う
RaiseEvent 発生通知(l_休止モード)
'戻り値によって処理を行う
Select Case l_休止モード
Case 休止モード.サスペンド
Call 実行_サスペンド()
Case 休止モード.休止状態
Call 実行_休止状態()
End Select
s_bln多重問合せ回避フラグ = False
End Sub
#End Region
#End Region
#Region "内部タイマー"
Private Class tmpタイマ
Inherits Timers.Timer
Public Sub New()
Me.Interval = 1
Me.Enabled = True
End Sub
End Class
#End Region
End Class
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
夏が終わったと感じる瞬間って、どんな時?
まだまだ暑い今日この頃。 しかしながら、もう夏は終わっている!……はず。 あなたが思う「夏が終わった!」エピソードを教えてください。
-
【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
2024年は「名探偵コナン30周年」「涼宮ハルヒ20周年」などを迎えますが、 あなたが「もうそんなに!?」と驚いた○○周年を教えてください。
-
ホテルを選ぶとき、これだけは譲れない条件TOP3は?
ホテルを探す時、予約サイトで希望条件の絞り込みができる便利な世の中。 あなたは宿泊先を決めるとき「これだけは譲れない」と思う条件TOP3を教えてください。
-
【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
【お題】 ・買ったばかりの自転車を分解してひと言
-
架空の映画のネタバレレビュー
映画のCMを見ていると、やたら感動している人が興奮で感想を話していますよね。 思わずストーリーが気になってしまう架空の感動レビューを教えて下さい!
-
VB2010でスタンバイや休止モードの復帰検出
Visual Basic(VBA)
-
別のフォームで記述している関数を実行するには?C#
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
メッセージボックスのボタン名変更
-
ACCESS側からEXCELの書式を設定...
-
VBA kernel32 の意味
-
【KeyDown】キーコードについて
-
エクセルVBAでクリップボード内...
-
VBSで応答不要のメッセージボッ...
-
VBA メッセージボックスを自動...
-
<input type="file">タグで「キ...
-
左シングルクリックとダブルク...
-
シャットダウン時のExcel強制終...
-
VCでウエイトをミリ秒でかけ...
-
thunderbirdのメッセージフィル...
-
【MFC】イベントの無効化について
-
Application.ScreenUpdating=Fa...
-
ASP.NETでのメッセージ画面を出...
-
VBA、UserFormを前面に出力して...
-
VB Loopを一時停止し再開あるい...
-
WEB上にボタンが押せない
-
Macターミナルで実行中のプログ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
メッセージボックスのボタン名変更
-
VBA kernel32 の意味
-
VBSで応答不要のメッセージボッ...
-
ACCESS側からEXCELの書式を設定...
-
VBA、UserFormを前面に出力して...
-
エクセルVBAでクリップボード内...
-
Excel VBA で処理中断(DoEvents...
-
ASP.NETでのメッセージ画面を出...
-
VBA メッセージボックスを自動...
-
Application.ScreenUpdating=Fa...
-
シャットダウン時のExcel強制終...
-
【C#】 あるイベントから別イ...
-
エクセルが勝手に立ち上がる
-
マルチスレッドを実現したい
-
MFCのワーカースレッドとUIスレ...
-
PostMessageの連続送信
-
vb.net イベントが完全に終了...
-
起動後直に実行するコードはど...
-
DoEvents
おすすめ情報