首先感谢加百力和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;
}
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!