今天有个客户在我的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. 有没有高人能够解释一下?
那么我们就把不可能变成可能, 无非就是熟悉一下微软的游戏规则而已.
下面给出的代码,在整个程序开始时, 调用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
114cleanup:
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
181cleanup:
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 #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
114cleanup:
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
181cleanup:
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
本文转自Walzer博客园博客,原文链接:http://www.cnblogs.com/walzer/archive/2008/07/18/1246251.html,如需转载请自行联系原作者