今天有个客户在我的MOBILE手机上做开发,遇到个需要检测POWER键RESUME的问题. 他们直接说在应用层检测这个是不可能的.
那么我们就把不可能变成可能, 无非就是熟悉一下微软的游戏规则而已.
下面给出的代码,在整个程序开始时, 调用InitPowerNotify一下, 建立起MSG QUEUE和NOTIFY, 然后开个线程读MSG QUEUE等待RESUME触发. 如果等到RESUME事件, 则在PowerThread的TBD处加入处理代码, 如果程序结束, 那么调用一下EndPowerNotify, 把线程结束掉把HANDLE清理掉.
以下代码在WM6.1上验证过可用。里面我写了很多DBGMSG, 这个是我自己做的一个把LOG写到文件里的函数, 用户可以删掉. 由于程序去检测POWER RESUME, 之前一定会有一次POWER SLEEP, 那么USB线连着VS2005调试就断掉了,所以只能把LOG写到文件里来看,而无法单步调试或把LOG输出到VS2005的OUTPUT窗口.
最后我有个疑问, 在反初始化时, 我调用StopPowerNotifications结果返回值是FALSE, 代表该函数失败,但是立刻GetLastError得到的ERR号却也是0. 有没有高人能够解释一下?
1
#include <windows.h>
2
#include <pm.h>
3
#include <Msgqueue.h>
4
5
#define QUEUE_ENTRIES 3
6
#define MAX_NAMELEN 200
7
#define QUEUE_SIZE (QUEUE_ENTRIES * sizeof(POWER_BROADCAST) + MAX_NAMELEN)
8
#define MSGQ_NAME TEXT("PowerNotify")
9
#define EXIT_THREAD_MSG 0x12345678
10
11
static BOOL g_bPowerEnd = FALSE;
12
static HANDLE g_hNoti = NULL;
13
static HANDLE g_hMsgQ = NULL;
14
static HANDLE g_hPowerThread = NULL;
15
16
17
DWORD WINAPI PowerThread(PVOID pParam)
18
{
19
BYTE buf[QUEUE_SIZE];
20
DWORD dwRead, dwFlag;
21
22
DBGMSG(ZONE_LOG, (TEXT("++PowerThread\n")));
23
24
do
25
{
26
if( ReadMsgQueue(g_hMsgQ, &buf, QUEUE_SIZE, &dwRead, 10, &dwFlag) )
27
{
28
POWER_BROADCAST* pBroad = (POWER_BROADCAST*)&buf;
29
30
if(pBroad->Message == PBT_RESUME)
31
{
32
DBGMSG(ZONE_LOG, (TEXT("PowerThread detected RESUME\n")));
33
34
//检测到POWER键按下,系统RESUME
35
//TBD: 把RESUME时的处理写这儿
36
}
37
else if(pBroad->Message == EXIT_THREAD_MSG)
38
{
39
DBGMSG(ZONE_LOG, (TEXT("PowerThread deteced EXIT\n")));
40
g_bPowerEnd = TRUE;
41
break;
42
}
43
else
44
{
45
DBGMSG(ZONE_LOG, (TEXT("PowerNotify detected nothing\n")));
46
}
47
}
48
49
}
50
while(!g_bPowerEnd);
51
52
DBGMSG(ZONE_LOG, (TEXT("--PowerThread\n")));
53
54
return 1;
55
}
56
57
BOOL InitPowerNotify()
58
{
59
BOOL result = FALSE;
60
MSGQUEUEOPTIONS options;
61
62
DBGMSG(ZONE_LOG, (TEXT("++InitPowerNofity\n")));
63
64
memset(&options, 0, sizeof(options));
65
66
if(g_hPowerThread) //等待线程已经存在了,该模块已启动
67
{
68
result = TRUE;
69
goto cleanup;
70
}
71
72
options.dwSize = sizeof(MSGQUEUEOPTIONS);
73
options.dwFlags = MSGQUEUE_ALLOW_BROKEN;
74
options.dwMaxMessages = QUEUE_ENTRIES;
75
options.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
76
options.bReadAccess = TRUE;
77
78
g_hMsgQ = CreateMsgQueue(MSGQ_NAME, &options);
79
80
if(!g_hMsgQ)
81
{
82
ASSERT(0);
83
DBGMSG(ZONE_LOG, (TEXT("CreateMsgQueue for power notify failed\n")));
84
goto cleanup;
85
}
86
else
87
{
88
DBGMSG(ZONE_LOG, (TEXT("CreateMsgQueue for power notify success\n")));
89
}
90
91
g_hNoti = RequestPowerNotifications(g_hMsgQ, PBT_RESUME);
92
93
if(!g_hNoti)
94
{
95
ASSERT(0);
96
DBGMSG(ZONE_LOG, (TEXT("RequestPowerNotifications failed\n")));
97
goto cleanup;
98
}
99
else
100
{
101
DBGMSG(ZONE_LOG, (TEXT("RequestPowerNotifications success\n")));
102
}
103
104
g_bPowerEnd = FALSE;
105
g_hPowerThread = CreateThread(NULL, 0, PowerThread, NULL, 0, NULL);
106
107
if(!g_hPowerThread)
108
{
109
ASSERT(0);
110
DBGMSG(ZONE_LOG, (TEXT("CreateThread for PowerNotify failed\n")));
111
goto cleanup;
112
}
113
114
cleanup:
115
DBGMSG(ZONE_LOG, (TEXT("--InitPowerNofity\n")));
116
return result;
117
}
118
119
BOOL EndPowerNotify()
120
{
121
BOOL bRet = FALSE;
122
HANDLE hWriteMsgQ = NULL;
123
MSGQUEUEOPTIONS options;
124
125
DBGMSG(ZONE_LOG, (TEXT("++EndPowerNotify\n")));
126
127
if(!g_hPowerThread)
128
{
129
DBGMSG(ZONE_LOG, (TEXT("PowerThread has been exit\n")));
130
goto cleanup;
131
}
132
133
memset(&options, 0, sizeof(options));
134
135
options.dwSize = sizeof(MSGQUEUEOPTIONS);
136
options.dwFlags = MSGQUEUE_ALLOW_BROKEN;
137
options.dwMaxMessages = QUEUE_ENTRIES;
138
options.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
139
options.bReadAccess = FALSE;
140
141
hWriteMsgQ = CreateMsgQueue(MSGQ_NAME, &options);
142
143
if(hWriteMsgQ)
144
{
145
POWER_BROADCAST writebuf;
146
writebuf.Message = EXIT_THREAD_MSG;
147
if(FALSE == WriteMsgQueue(hWriteMsgQ, &writebuf, sizeof(writebuf), 1000, 0) )
148
{
149
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQueue failed\n")));
150
}
151
else
152
{
153
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQueue succeed\n")));
154
}
155
156
if(FALSE == CloseMsgQueue(hWriteMsgQ))
157
{
158
DBGMSG(ZONE_LOG, (TEXT("CloseMsgQueue failed\n")));
159
}
160
}
161
else
162
{
163
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQ create failed\n")));
164
}
165
166
DBGMSG(ZONE_LOG, (TEXT("Wait for PowerThread exit
\n")));
167
168
g_bPowerEnd = TRUE;
169
170
if( WaitForSingleObject(g_hPowerThread, 1000) == WAIT_OBJECT_0 )
171
{
172
DBGMSG(ZONE_LOG, (TEXT("PowerThread exit success\n")));
173
g_hPowerThread = NULL;
174
bRet = TRUE;
175
}
176
else
177
{
178
DBGMSG(ZONE_LOG, (TEXT("PowerThread exit failed timeout\n")));
179
}
180
181
cleanup:
182
183
if(g_hNoti)
184
{
185
if( FALSE == StopPowerNotifications(g_hNoti) )
186
{
187
DBGMSG(ZONE_LOG, (TEXT("StopPowerNotifications failed, err = %d\n"), GetLastError()));
188
}
189
190
g_hNoti = NULL;
191
}
192
193
if(g_hMsgQ)
194
{
195
if(!CloseMsgQueue(g_hMsgQ))
196
{
197
DBGMSG(ZONE_LOG, (TEXT("CloseMsgQueue failed\n")));
198
}
199
200
g_hMsgQ = NULL;
201
}
202
203
DBGMSG(ZONE_LOG, (TEXT("--EndPowerNotify\n")));
204
return bRet;
205
}
206
#include <windows.h>2
#include <pm.h>3
#include <Msgqueue.h>4

5
#define QUEUE_ENTRIES 36
#define MAX_NAMELEN 2007
#define QUEUE_SIZE (QUEUE_ENTRIES * sizeof(POWER_BROADCAST) + MAX_NAMELEN)8
#define MSGQ_NAME TEXT("PowerNotify")9
#define EXIT_THREAD_MSG 0x1234567810

11
static BOOL g_bPowerEnd = FALSE;12
static HANDLE g_hNoti = NULL;13
static HANDLE g_hMsgQ = NULL;14
static HANDLE g_hPowerThread = NULL;15

16

17
DWORD WINAPI PowerThread(PVOID pParam)18
{19
BYTE buf[QUEUE_SIZE];20
DWORD dwRead, dwFlag;21
22
DBGMSG(ZONE_LOG, (TEXT("++PowerThread\n")));23

24
do25
{26
if( ReadMsgQueue(g_hMsgQ, &buf, QUEUE_SIZE, &dwRead, 10, &dwFlag) )27
{28
POWER_BROADCAST* pBroad = (POWER_BROADCAST*)&buf;29

30
if(pBroad->Message == PBT_RESUME)31
{32
DBGMSG(ZONE_LOG, (TEXT("PowerThread detected RESUME\n")));33

34
//检测到POWER键按下,系统RESUME35
//TBD: 把RESUME时的处理写这儿36
}37
else if(pBroad->Message == EXIT_THREAD_MSG)38
{39
DBGMSG(ZONE_LOG, (TEXT("PowerThread deteced EXIT\n")));40
g_bPowerEnd = TRUE;41
break;42
}43
else44
{45
DBGMSG(ZONE_LOG, (TEXT("PowerNotify detected nothing\n")));46
}47
}48
49
}50
while(!g_bPowerEnd);51

52
DBGMSG(ZONE_LOG, (TEXT("--PowerThread\n")));53

54
return 1;55
}56

57
BOOL InitPowerNotify()58
{59
BOOL result = FALSE;60
MSGQUEUEOPTIONS options;61

62
DBGMSG(ZONE_LOG, (TEXT("++InitPowerNofity\n")));63

64
memset(&options, 0, sizeof(options));65

66
if(g_hPowerThread) //等待线程已经存在了,该模块已启动67
{68
result = TRUE;69
goto cleanup;70
}71
72
options.dwSize = sizeof(MSGQUEUEOPTIONS);73
options.dwFlags = MSGQUEUE_ALLOW_BROKEN;74
options.dwMaxMessages = QUEUE_ENTRIES;75
options.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;76
options.bReadAccess = TRUE;77

78
g_hMsgQ = CreateMsgQueue(MSGQ_NAME, &options);79

80
if(!g_hMsgQ)81
{82
ASSERT(0);83
DBGMSG(ZONE_LOG, (TEXT("CreateMsgQueue for power notify failed\n")));84
goto cleanup;85
}86
else87
{88
DBGMSG(ZONE_LOG, (TEXT("CreateMsgQueue for power notify success\n")));89
}90

91
g_hNoti = RequestPowerNotifications(g_hMsgQ, PBT_RESUME);92
93
if(!g_hNoti)94
{95
ASSERT(0);96
DBGMSG(ZONE_LOG, (TEXT("RequestPowerNotifications failed\n")));97
goto cleanup;98
}99
else100
{101
DBGMSG(ZONE_LOG, (TEXT("RequestPowerNotifications success\n")));102
}103

104
g_bPowerEnd = FALSE;105
g_hPowerThread = CreateThread(NULL, 0, PowerThread, NULL, 0, NULL);106
107
if(!g_hPowerThread)108
{109
ASSERT(0);110
DBGMSG(ZONE_LOG, (TEXT("CreateThread for PowerNotify failed\n")));111
goto cleanup;112
}113

114
cleanup:115
DBGMSG(ZONE_LOG, (TEXT("--InitPowerNofity\n")));116
return result;117
}118

119
BOOL EndPowerNotify()120
{121
BOOL bRet = FALSE;122
HANDLE hWriteMsgQ = NULL;123
MSGQUEUEOPTIONS options;124

125
DBGMSG(ZONE_LOG, (TEXT("++EndPowerNotify\n")));126

127
if(!g_hPowerThread)128
{129
DBGMSG(ZONE_LOG, (TEXT("PowerThread has been exit\n")));130
goto cleanup;131
}132
133
memset(&options, 0, sizeof(options));134
135
options.dwSize = sizeof(MSGQUEUEOPTIONS);136
options.dwFlags = MSGQUEUE_ALLOW_BROKEN;137
options.dwMaxMessages = QUEUE_ENTRIES;138
options.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;139
options.bReadAccess = FALSE;140
141
hWriteMsgQ = CreateMsgQueue(MSGQ_NAME, &options);142

143
if(hWriteMsgQ)144
{145
POWER_BROADCAST writebuf;146
writebuf.Message = EXIT_THREAD_MSG;147
if(FALSE == WriteMsgQueue(hWriteMsgQ, &writebuf, sizeof(writebuf), 1000, 0) )148
{149
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQueue failed\n")));150
}151
else152
{153
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQueue succeed\n")));154
}155
156
if(FALSE == CloseMsgQueue(hWriteMsgQ))157
{158
DBGMSG(ZONE_LOG, (TEXT("CloseMsgQueue failed\n")));159
}160
}161
else162
{163
DBGMSG(ZONE_LOG, (TEXT("WriteMsgQ create failed\n")));164
}165
166
DBGMSG(ZONE_LOG, (TEXT("Wait for PowerThread exit
\n")));167
168
g_bPowerEnd = TRUE;169
170
if( WaitForSingleObject(g_hPowerThread, 1000) == WAIT_OBJECT_0 )171
{172
DBGMSG(ZONE_LOG, (TEXT("PowerThread exit success\n")));173
g_hPowerThread = NULL;174
bRet = TRUE;175
}176
else177
{178
DBGMSG(ZONE_LOG, (TEXT("PowerThread exit failed timeout\n")));179
}180

181
cleanup:182

183
if(g_hNoti)184
{ 185
if( FALSE == StopPowerNotifications(g_hNoti) )186
{187
DBGMSG(ZONE_LOG, (TEXT("StopPowerNotifications failed, err = %d\n"), GetLastError()));188
}189
190
g_hNoti = NULL;191
}192

193
if(g_hMsgQ)194
{ 195
if(!CloseMsgQueue(g_hMsgQ))196
{197
DBGMSG(ZONE_LOG, (TEXT("CloseMsgQueue failed\n")));198
}199
200
g_hMsgQ = NULL;201
}202

203
DBGMSG(ZONE_LOG, (TEXT("--EndPowerNotify\n")));204
return bRet;205
}206


浙公网安备 33010602011771号