首先感谢加百力和Yonsm对我前一个帖子的解答,没有他俩我现在大概还没思绪呢。

以及感谢今天下午MobileSide开发群里的山夕兄的帮助。

(如果可以,给我帖子加个精华吧@@ *^_^*)

解决的关键如下图所示,这是微软搞的一个小陷阱,偷懒一点不抓完控件都不知道你该找那个窗口的Handle……
http://att.pdafans.com/month_0904/09040516226abef7da6889068f.jpg

分别对应关系:
1.拨号
http://att.pdafans.com/month_0904/09040516238fd3fe44620118f6.jpg

2.通话中(本文主角)
http://att.pdafans.com/month_0904/09040516222573459aeaeba404.jpg

3.通话结束
http://att.pdafans.com/month_0904/0904051622906ba99457cce6fa.jpg

这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;
}