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で質問しましょう!
似たような質問が見つかりました
- 会社・職場 30歳主婦でパートで働いてます。夫の扶養外れてるのでガッツリ働かないと損になるのですが、人間関係が辛 6 2022/08/07 15:00
- 遊園地・テーマパーク 1人ディズニー 3 2023/07/25 19:47
- イベント・祭り ジャンプビクトリーカーニバル、ジャンプ様のイベント当たりました。 仕事休みです。 会場のヲタに話しか 1 2022/07/05 08:40
- 人事・法務・広報 法定休日に出勤し振休をとった場合の休日手当は週40時間を超えたら支給するのかについて。 全社員参加必 1 2023/05/17 00:08
- 事務・総務 2つの事務ならどちらに応募しますか? ①社団法人の事務 175000の給与、ボーナス4.5、昇給あり 4 2023/03/16 12:26
- その他(暮らし・生活・行事) 自治会について 一軒家に引越して不動産屋さんからもゴミ捨ての事などあるから自治会には入った方が良いと 7 2022/04/26 09:24
- イベント・祭り 屋外の大型イベント開催について 1 2022/08/24 13:38
- コスメ・化粧品 最近退院してもらった病院の薬が合わず顔に薬疹が出てしまい、塗り薬を塗ったら顔がギトギトのテカテカに。 1 2022/08/18 12:31
- その他(ビジネス・キャリア) 有給休暇トラブル 3 2023/02/05 15:09
- iPhone(アイフォーン) iphone13 2 2022/07/17 08:32
このQ&Aを見た人はこんなQ&Aも見ています
-
見学に行くとしたら【天国】と【地獄】どっち?
みなさんは、一度だけ見学に行けるとしたら【天国】と【地獄】どちらに行きたいですか? 理由も聞きたいです。
-
3分あったら何をしますか?
カップ麺にお湯を入れて、できるまでの3分間で皆さんは何をしていますか?
-
治せない「クセ」を教えてください
なくて七癖という言葉どおり、人によっていろいろなクセがありますよね。 あなたには治せないクセがありますか?
-
【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
「出身中学と出身高校が混ざったような校舎にいる夢を見る」「まぶたがピクピクしてるので鏡で確認しようとしたらピクピクが止まってしまう」など、 これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
-
我がまちの「給食」自慢を聞かせてっ!
富山県の給食には「ベニズワイガニ」が出る、、、なんて話を聞いたことがあります。 日本全国「え、給食にそれ出るの!?」な驚きメニューがまだまだあるはず!
-
VB2010でスタンバイや休止モードの復帰検出
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】看板の文字を埋めてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・【穴埋めお題】恐竜の新説
- ・我がまちの「給食」自慢を聞かせてっ!
- ・冬の健康法を教えて!
- ・一番好きな「クリスマスソング」は?
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ACCESS側からEXCELの書式を設定...
-
VBSの処理中一旦処理を止めて再...
-
Application.ScreenUpdating=Fa...
-
Excel(VBA)シート上のコマンド...
-
MFCのワーカースレッドとUIスレ...
-
メッセージボックスのボタン名変更
-
【C#】 あるイベントから別イ...
-
Windowsがシャットダウンする前に
-
PostMessageの連続送信
-
VBSで応答不要のメッセージボッ...
-
VBA kernel32 の意味
-
スタティックテキストが表示さ...
-
Photoshop JavaScript で処理中...
-
Excel VBA 自動的に閉じるMsgBox
-
「VBでExcel上PictureBoxダブル...
-
Excel VBA で処理中断(DoEvents...
-
ASP.NETでのメッセージ画面を出...
-
Excel VBA 実行中に一瞬フリー...
-
エクセルが勝手に立ち上がる
-
VBA、UserFormを前面に出力して...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
VBA kernel32 の意味
-
メッセージボックスのボタン名変更
-
ACCESS側からEXCELの書式を設定...
-
VBA、UserFormを前面に出力して...
-
VBA メッセージボックスを自動...
-
エクセルVBAでクリップボード内...
-
VBSで応答不要のメッセージボッ...
-
Excel VBA で処理中断(DoEvents...
-
MFCのワーカースレッドとUIスレ...
-
ASP.NETでのメッセージ画面を出...
-
「キャンセル」ボタン付きの処...
-
Excel VBA 自動的に閉じるMsgBox
-
【C#】 あるイベントから別イ...
-
シャットダウン時のExcel強制終...
-
Application.ScreenUpdating=Fa...
-
ASP VBScriptでスクリプト実行...
-
起動後直に実行するコードはど...
-
フォルダ指定
-
DoEvents
おすすめ情報