在WM5以上系统使用Notification Broker机制实现获取全部电话状态
来源:互联网 发布:韶关网络问政平台 编辑:程序博客网 时间:2024/04/30 11:49
查了很多资料涉及到Notification Broker的都只有触发一种状态的代码,但是为了一个功能改进,我需要一种能获取多种电话状态(呼出、呼入、通话中……)的方法,同时由于程序是需要主动触发的,所以用RegistryNotifyApp做主动Broker,查了MSDN却发现没有对RegistryNotifyApp如何在多种事件中启动做出过多说明,就继续翻其他MSDN,终于看到在NOTIFICATIONCONDITION的解释里有这含义模糊的两行文字:
dwMask
Applies only to DWORD values. This mask is applied to the changed registry value before comparison. By specifying a bit mask, the Notifications Broker notifies the clients only when specific bits in the registry value changes.
This mask is not applied to TargetValue. If dwMask is 0, TargetValue is treated as a string (type REG_SZ), otherwise it is treated as type REG_DWORD.
TargetValue
If the changed value is type REG_SZ, then comparison is done between psz and the changed value. If the changed value is type REG_DWORD, then dwMask is applied to the changed value and then the result is compared to dw. If the changed value is neither REG_SZ nor REG_DWORD, then notification is sent without any comparison. You must set dwMask to -1 to test against the whole doubleword.
可以看出,dwMask=-1好像会有什么好玩的事情发生,立即写代码测试:
#define SN_PHONECALLTALKING_ROOT HKEY_LOCAL_MACHINE#define SN_PHONECALLTALKING_PATH TEXT("System//State//Phone")#define SN_PHONECALLTALKING_VALUE TEXT("Status")#define SN_PHONECALLTALKING_BITMASK 536870912#define SN_PHONECALLCALLING_BITMASK 131072#define SN_PHONEINCOMINGCALL_BITMASK 65536#define MY_NOTIFICATION_NAME TEXT("testnotification")DWORD GetCurrentNotificationStatus(){ DWORD lpPhoneTalking = 0; HRESULT hr; hr = RegistryGetDWORD(SN_PHONECALLTALKING_ROOT, SN_PHONECALLTALKING_PATH, SN_PHONECALLTALKING_VALUE, &lpPhoneTalking); if(SUCCEEDED(hr)) { if(lpPhoneTalking & SN_PHONECALLTALKING_BITMASK){ return SN_PHONECALLTALKING_BITMASK; }else if(lpPhoneTalking & SN_PHONECALLCALLING_BITMASK){ return SN_PHONECALLCALLING_BITMASK; }else if(lpPhoneTalking & SN_PHONEINCOMINGCALL_BITMASK){ return SN_PHONEINCOMINGCALL_BITMASK; }else{ return lpPhoneTalking; } }else{ return 0; }}HRESULT RegisterNotification(){ HRESULT hr = NULL; NOTIFICATIONCONDITION nc; nc.dwMask = -1; nc.ctComparisonType = REG_CT_ANYCHANGE; nc.TargetValue.dw = 0x01; hr = RegistryNotifyApp(SN_PHONECALLTALKING_ROOT, SN_PHONECALLTALKING_PATH, SN_PHONECALLTALKING_VALUE, MY_NOTIFICATION_NAME, szExeFile, NULL, NULL, 0x00, RNAF_NONAMEONCMDLINE, &nc); return hr;}int _tmain(int argc, _TCHAR* argv[]){ GetModuleFileName(NULL,szExeFile,256); HRESULT hr = RegisterNotification(); LPCTSTR currStatus; DWORD dStatus; dStatus=GetCurrentNotificationStatus(); switch(dStatus){ case SN_PHONECALLCALLING_BITMASK: currStatus=L"Calling"; break; case SN_PHONECALLTALKING_BITMASK: currStatus=L"Talking"; break; case SN_PHONEINCOMINGCALL_BITMASK: currStatus=L"Incoming"; break; default: currStatus=(LPCTSTR)dStatus; } MessageBox(GetActiveWindow(),currStatus,TEXT("test"),MB_SETFOREGROUND | MB_ICONINFORMATION | MB_OK); return 0;}
执行程序,查找注册表果然注册了一个新的Broker“testnotification”,然后测试呼叫电话和打出电话和接听,成功获取了三种状态。
因此,如果你想在自己的Notification Broker程序里实现监控某种事件的整个状态,用dwMask = -1配合ctComparisonType = REG_CT_ANYCHANGE使用即可。
以及感谢今天下午MobileSide开发群里的山夕兄的帮助。
解决的关键如下图所示,这是微软搞的一个小陷阱,偷懒一点不抓完控件都不知道你该找那个窗口的Handle……
分别对应关系:
1.拨号
2.通话中(本文主角)
3.通话结束
这3个窗口里的类名控件名全都一样,唯一不同的就是那些按钮的文本名,还有通话状态窗口和通话结束窗口是动态切换的,也就是平时状态下你只能看到通话结束窗口,而通话的时候通话结束窗口是被干掉了一堆MS_PHONE_BUTTON按钮控件的。
“打开扬声器”按钮的标识是IDC_SPEAKER(分析CProg就知道),用GetDlgCtrlID可以获得其ID为23016
#define IDC_SPEAKER 23016
然后我们要获得发往这个窗口和指定按钮的消息,所以要对其Subclass子类化,WINCE没有SetWindowsHook等相关函数,只能用SetWindowLong来实现。
不说废话了,还是贴代码省事,今天忙一天又搞Dll Injection又搞回来又搞回去最后发现还是搞回来就行,累死我了……
代码演示了对“打开扬声器”按钮和“打开扬声器”菜单进行控制,代码里的一些ID来自实际分析,非官方标准声明。
#define IDM_SPEAKER 21426#define IDC_SPEAKER 23016unsigned int timerID;static WNDPROC s_OldWndProc = NULL;static WNDPROC s_OldSpkBtnProc = NULL;HANDLE s_hExit = NULL;HWND lpSpeakerPhoneBtn=NULL;LRESULT CALLBACK NewSpkBtnProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ if(timerID!=0){ KillTimer(NULL,timerID); timerID=0; } switch (uMsg) { case WM_LBUTTONDOWN: { SetSpeakerPhone(); break; } } return CallWindowProc(s_OldSpkBtnProc, hwnd, uMsg, wParam, lParam);}LRESULT CALLBACK NewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ if(timerID!=0){ KillTimer(NULL,timerID); timerID=0; } switch (uMsg) { case WM_COMMAND: { //SetWindowText(lpCallStatWin,TEXT("WM_COMMAND")); if(LOWORD(wParam)==IDM_SPEAKER) SetSpeakerPhone(); break; } case WM_SIZE: { if(wParam==SIZE_MINIMIZED) _debug(L"SIZE_MINIMIZED"); _debug(L"WM_SIZE:wParam:%08x,lParam:%08x",wParam,lParam); break; } case WM_SYSCOMMAND: { _debug(L"SYSCOMMAND"); break; } case WM_ACTIVATE: { _debug(L"WM_ACTIVATE:wParam:%08x,lParam:%08x",wParam,lParam); break; } case WM_KILLFOCUS: { _debug(L"WM_KILLFOCUS:wParam:%08x,lParam:%08x",wParam,lParam); break; } case WM_DESTROY: { if (s_hExit) { //_debug(L"Posting exit msg..."); SetEvent(s_hExit); } break; } } return CallWindowProc(s_OldWndProc, hwnd, uMsg, wParam, lParam);}int SetHook(HWND lpHookHwnd){ s_hExit = CreateEvent(NULL, FALSE, FALSE, NULL); if (lpHookHwnd!=NULL) { lpCallStatWin=lpHookHwnd; s_OldWndProc = (WNDPROC)GetWindowLong(lpHookHwnd, GWL_WNDPROC); SetWindowLong(lpHookHwnd, GWL_WNDPROC, (DWORD)NewWndProc); s_OldSpkBtnProc = (WNDPROC)GetWindowLong(lpSpeakerPhoneBtn, GWL_WNDPROC); SetWindowLong(lpSpeakerPhoneBtn, GWL_WNDPROC, (DWORD)NewSpkBtnProc); WaitForSingleObject(s_hExit, INFINITE); SetWindowLong(lpHookHwnd, GWL_WNDPROC, (DWORD)s_OldWndProc); SetWindowLong(lpSpeakerPhoneBtn, GWL_WNDPROC, (DWORD)s_OldSpkBtnProc); } return 0;}HWND FindPhoneHandle(){ HWND lpNextWindow = NULL; HWND lpForeground = NULL; TCHAR lpClassName[64]; int lpControlID; //LPWSTR lpControlText; //LPSTR test; lpForeground =GetForegroundWindow(); if(lpForeground==NULL) return 0; lpNextWindow = GetWindow(lpForeground, GW_CHILD); lpNextWindow = GetWindow(lpNextWindow, GW_HWNDFIRST); while(lpNextWindow!=0){ GetClassName( lpNextWindow,lpClassName,64); //_debug(L"Main Handle:%d,ClassName:%s",lpForeground,lpClassName); if(!_tcscmp(lpClassName,TEXT("MS_PHONE_BUTTON"))){ //确认是电话界面里的按钮,开始判断IDC_SPEAKER lpControlID=GetDlgCtrlID(lpNextWindow); if(lpControlID==IDC_SPEAKER){ //_debug(L" Speaker found"); lpSpeakerPhoneBtn=lpNextWindow; HWND lpRealHandle=GetParent(lpNextWindow); //_debug(L" ParentHandle:%d,lpForeground:%d",lpRealHandle,lpForeground); if(lpRealHandle!=NULL){ return lpRealHandle; } return lpForeground; } } lpNextWindow = GetWindow(lpNextWindow, GW_HWNDNEXT); } return 0;}void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime) { HWND lpCallStatusWindow; lpCallStatusWindow=FindPhoneHandle(); if(lpCallStatusWindow!=0){ SetHook(lpCallStatusWindow); }}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ //NOTIFICATIONCONDITION condition; timerID = SetTimer(NULL,1,1000,TimeProc); MSG msg; while(GetMessage(&msg,0,0,0)) { //收到wm_timer消息,处理它 //_debug(L"msg.message:%d",msg.message); if(msg.message==WM_TIMER){ DispatchMessage(&msg); } } return 0;}
http://hi.baidu.com/net%5Flk007/blog/item/8874f635a8c7921990ef395d.html
- 在WM5以上系统使用Notification Broker机制实现获取全部电话状态
- windows mobile 状态/通知机制 State and Notification Broker
- Windows mobile State and Notification Broker 状态/通知机制
- 如何在Wm5的模拟器中测试电话功能
- android在应用中监听系统的电话状态
- 使用C#更改Smartphone(WM5)的蓝牙状态
- 使用Notification实现状态通知栏的发送和取消
- 【Android】使用Notification实现状态通知栏的通知
- Notification实现状态通知栏
- 在S5PV210平台上实现二代身份证解码,安卓系统,可以获取全部文字信息以及电子照片
- 用jquery实现全选/全部选功能(jquery-1.9.x 版本以上),使用 prop 属性
- WM5调用系统输入法
- WM5调用系统输入法
- Android实现电话状态监控
- wm5获得电池状态信息
- 获取wince系统内存使用状态
- 使用shell脚本获取系统运行状态
- iOS - 如何在iOS8.0系统以上使用指纹功能
- 页面滚动条 body的滚动条
- MySQL导入导出命令
- c++复习注意要点
- MySQL 服务无法启动 1067 错误 进程意外终止解决方法
- 使用java将word文档转换为swf格式
- 在WM5以上系统使用Notification Broker机制实现获取全部电话状态
- csdn windows live writer 发布日志
- C++字符串
- [C#]识别常见图片
- Flex通过javascript读写cookie
- Android是什么 之三-------手机之硬件形态
- VisualSVN Server的配置和使用方法
- Delphi的单元文件详解
- 八大排序算法