首先感谢加百力和Yonsm对我前一个帖子的解答,没有他俩我现在大概还没思绪呢。
以及感谢今天下午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 23016 unsigned 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; }