前两天换了新老板,新老板对百度很感兴趣,就要求我们开发跟百度手机输入自带的搜索框一样的一个“框”。
开始动工前,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类型的窗口成对出现的。
- 找到桌面的菜单栏menubar,menu_worker类型的窗口。
- 找到与桌面菜单栏menubar对应的MS_SOFTKEY_CE_1.0类型的窗口
- 在找到的MS_SOFTKEY_CE_1.0类型的窗口下,创建一个子窗口。
- 将子窗口移动到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进行比较,如果一致,则是我们所有查找的父窗口了。直接把关键代码放出来。
代码
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 相关的网上的资料相对比较多。呵呵)