详解百度手机输入法“搜索框”的秘密 - 啊夏

时间:2024-03-06 07:19:37

   前两天换了新老板,新老板对百度很感兴趣,就要求我们开发跟百度手机输入自带的搜索框一样的一个“框”。

开始动工前,google了下(google现在不行了,转用bing吧),找到一篇文章。

“百度输入框的秘密” url: http://blog.csdn.net/pknife/archive/2010/01/06/5141282.aspx

 

先放两张效果图吧 

  

 建议先看上面这篇文章。下面的内容是具体实现的详解。 

     我们要实现的第一个目标:

 在homescreen 的菜单栏*添加一个自定义的按钮。 

     背景资料:

       我们通过 SHFindMenuBar这个函数,将桌面顶层窗口的句柄传递进去后,能拿到桌面菜单栏的句柄。

       这时候,首先想到的就是直接使用api函数给菜单栏添加一个item。但是,当我们在wm的menubar上有3个菜单项的时候,那3个菜单项不会乖乖地以左中右的方式给我们进行排列。而是全部靠左依次排开。这显然不是我们想要的结果。

 

ok,上文提到的那篇blog 里面对“百度的搜索框”用spy已经分析的蛮清楚了。 现在我们把一些核心的信息提取出来。

 

  •  百度图标其实是个窗口,其父窗口是一个MS_SOFTKEY_CE_1.0类型的窗口 
  • SHFindMenuBar得到的只是menu_worker类型的窗口
  • MS_SOFTKEY_CE_1.0类型窗口是与menu_worker类型的窗口成对出现的。
ok,整理下思路。为了在主界面的menubar中间添加那么一个按钮。我们需要干下面的几件事情。       

 

  1. 找到桌面的菜单栏menubar,menu_worker类型的窗口
  2. 找到与桌面菜单栏menubar对应的MS_SOFTKEY_CE_1.0类型的窗口
  3. 在找到的MS_SOFTKEY_CE_1.0类型的窗口下,创建一个子窗口。
  4. 将子窗口移动到menubar的中间位置,并处理相关的按键和绘制消息。
好,对于上面的问题。第一个很好解决。

  HWND hwndMB = ::SHFindMenuBar(GetDesktopWindow());

第3点和第4点也没啥问题。这样难点就在第2点了。这里,我们注意到 MS_SOFTKEY_CE_1.0类型窗口是与menu_worker类型的窗口成对出现的。

那么他们之间有什么关系呢。还是使用我们伟大的spy大神(这里我就不截图了,有兴趣的可以自己去看看)。 我们会发现  menu_worker类型 窗口与他对应的MS_SOFTKEY_CE_1.0类型窗口所在的进程id是一样的。

 

ok,思路有了。 先查找到桌面menubar的句柄,然后得到他所在进程的编号。

遍历系统所有的顶层窗口,查找 MS_SOFTKEY_CE_1.0类型的窗口,然后将窗口的进程id跟 menubar的进程id进行比较,如果一致,则是我们所有查找的父窗口了。直接把关键代码放出来。

  代码

 1 
 2 void CreateMenuButtonOnDesktop()
 3 {
 4     HWND hwndMB = ::SHFindMenuBar(GetDesktopWindow());
 5     ::GetWindowThreadProcessId(hwndMB,&m_pID);//pID就是进程ID 
 6     EnumWindows(EnumWindowsProc,NULL);
 7 }
 8 
 9 BOOL   CALLBACK   EnumWindowsProc(HWND   hwnd,LPARAM   lParam)
10 {
11 
12     DWORD pID=0
13     ::GetWindowThreadProcessId(hwnd,&pID);//pID就是进程ID 
14 
15     if ((DWORD)m_pID == pID)
16     {
17 
18         TCHAR szClassName[128];
19         GetClassName(hwnd,szClassName,128);
20         if (wcscmp(szClassName,_T("MS_SOFTKEY_CE_1.0")) == 0)
21         {
22             
23             child_hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
24                 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, g_hInst, NULL);
25 
26             
27             if (!child_hWnd)
28             {
29                 return FALSE;
30             }
31 
32             int nWidth = 36;
33             int nHeight = 20;
34             RECT rc;
35             GetWindowRect(hwnd,&rc);
36             MoveWindow(child_hWnd, (rc.right- nWidth)/2, (rc.bottom - rc.top - nHeight)/2 , nWidth, nHeight, FALSE);
37 
38             ShowWindow(child_hWnd, WM_SHOWWINDOW);
39             UpdateWindow(child_hWnd);
40             return FALSE;
41         }
42     }
43     return TRUE;
44 }

 

 第4步,这里就不花时间来写了。

 

我们要实现的第2个目标。

  创建一个非模态的对话框 

这个跟本篇文章的核心思路关系不大,在这里也不细说了。相信大家都能轻松搞定。

 

至此,我们完成了一个跟百度一个的桌面menubar中间的按钮。 有空可能会把symbian版本的也写下。(symbian 相关的网上的资料相对比较多。呵呵)