www.Walzer.cn - Tech & Management Blog

Focus on mobile dev
本博客文章,未在标题中写明转载的, 均为原创.
所谓高手,也就是熟悉别人制定的游戏规则、并且能在规则内跳舞的人。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在WM6应用层代码检测POWER键RESUME动作

Posted on 2008-07-18 17:40  Walzer  阅读(2543)  评论(2编辑  收藏  举报

今天有个客户在我的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
 11static BOOL g_bPowerEnd = FALSE;
 12static HANDLE g_hNoti = NULL;
 13static HANDLE g_hMsgQ = NULL;
 14static HANDLE g_hPowerThread = NULL;
 15
 16
 17DWORD 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
 57BOOL InitPowerNotify()
 58{
 59    BOOL result = FALSE;
 60    MSGQUEUEOPTIONS options;
 61
 62    DBGMSG(ZONE_LOG, (TEXT("++InitPowerNofity\n")));
 63
 64    memset(&options, 0sizeof(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
119BOOL 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, 0sizeof(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), 10000) )
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