今天有个客户在我的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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166


167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206
