Sample Code 在 google groupe 上: PowerChange Notifications : Resume
很好心的把 code 都貼出來,但是我用起來有一點問題,就是 Notification Thread 沒有辦法terminate 掉,
/ John Baik: Sample code for Power Notification
#include <windows.h>
#include <PM.h>
// from pmimpl.h file.
#ifndef QUEUE_ENTRIES
#define QUEUE_ENTRIES 3
#endif
#ifndef MAX_NAMELEN
#define MAX_NAMELEN 128
#endif
#ifndef QUEUE_SIZE
#define QUEUE_SIZE (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + \\
(MAX_NAMELEN * sizeof(TCHAR))))
#endif
int WINAPI PMNotifyThread(LPVOID pvParam);
void PMNotification(HANDLE hMsgQ);
HANDLE ghPMNotifyQ = NULL;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSGQUEUEOPTIONS msgQpm = {0};
HANDLE hPwrNotify=NULL; // Power manager handle
HANDLE hPMThread=NULL;
// create a message queue for Power Manager notifications
msgQpm.dwSize = sizeof(MSGQUEUEOPTIONS);
msgQpm.dwFlags = 0;
msgQpm.dwMaxMessages = QUEUE_ENTRIES;
msgQpm.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
msgQpm.bReadAccess = TRUE;
ghPMNotifyQ= CreateMsgQueue(NULL, &msgQpm);
if (ghPMNotifyQ == NULL)
{
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT(" PMNotify:CreateMessageQueue ERROR:%d \r\n"), dwErr));
return 1;
}
// request Power notifications
hPwrNotify = RequestPowerNotifications(ghPMNotifyQ, PBT_TRANSITION |
PBT_RESUME);
if (hPwrNotify == NULL)
{
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT(" PMNotify:RequestPowerNotifications ERROR:%d\r\n"), dwErr));
return 2;
}
// Create PMNotifyThread
hPMThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE )PMNotifyThread, NULL, 0, NULL);
if(hPMThread)
{
// wait for PMNotifyThread done
WaitForSingleObject(hPMThread, INFINITE);
CloseHandle(hPMThread);
if(hPwrNotify)
{
StopPowerNotifications(hPwrNotify);
}
}
return 0;
}
// PMNotifyThread: Wait for Message from PM Driver.
//
int WINAPI PMNotifyThread(LPVOID pvParam)
{
DWORD dwStatus;
while (TRUE)
{
dwStatus = WaitForSingleObject(ghPMNotifyQ, INFINITE);
if(dwStatus == WAIT_OBJECT_0)
{
PMNotification(ghPMNotifyQ);
}
else
{
RETAILMSG(1,
(TEXT(" PMNotify: WaitForSingleObject returned %d (error %d)\r\n"),
dwStatus, GetLastError()));
break;
}
}
return 0;
}
void PMNotification(HANDLE hMsgQ)
{
UCHAR pmbuf[QUEUE_SIZE];
int nBytesRead=0;
DWORD dwFlags = 0;
int dwCount = 0;
memset(pmbuf, 0, sizeof(pmbuf));
if ( !ReadMsgQueue(hMsgQ,
pmbuf,
QUEUE_SIZE,
(LPDWORD)&nBytesRead,
INFINITE, // Timeout
&dwFlags))
{
DWORD dwErr = GetLastError();
RETAILMSG(1,
(TEXT(" ProcessPowerNotification: ReadMsgQueue:ERROR:%d\n"), dwErr));
}
else if(nBytesRead >= sizeof(POWER_BROADCAST))
{
// process power notifications
//-----------------------------
PPOWER_BROADCAST pPB = (PPOWER_BROADCAST) pmbuf;
switch (pPB->Message)
{
case PBT_RESUME:
RETAILMSG(1, (TEXT(" PMNotify:PBT_RESUME \r\n")));
break;
case PBT_POWERSTATUSCHANGE:
RETAILMSG(1, (TEXT(" PMNotify:PBT_POWERSTATUSCHANGE: \r\n")));
break;
case PBT_POWERINFOCHANGE:
RETAILMSG(1, (TEXT(" PMNotify:PBT_POWERSTATUSCHANGE: \r\n")));
break;
case PBT_TRANSITION:
{
switch (POWER_STATE(pPB->Flags))
{
case POWER_STATE_ON:
break;
case POWER_STATE_OFF:
break;
case POWER_STATE_CRITICAL:
break;
case POWER_STATE_BOOT:
break;
case POWER_STATE_IDLE:
break;
case POWER_STATE_SUSPEND:
break;
case POWER_STATE_RESET:
break;
default:
break;
}
break;
}
default:
break;
}
}
}
實際上用要稍微修改一下..
- PMThread 要有 Exit 的機制 - 在 WaitForSingleObject 加 Timeout check flag 或是用 WaitForMultipleObject 代替
- WinMain 的 code 其實要分兩部份: InitPowerHandler, ClosePowerHandler. 放在 Dialog Proc 的 WM_INITDIALOG 和 WM_CLOSE
沒有留言:
張貼留言