这是怎么回事呢?咋解决呢?如何让它不跑回去呢?
原来开始按钮恢复到原来位置的原因是因为每当我们改变任务栏窗口大小或刷新屏幕是,系统都会向开始按钮发送WM_MOVE和WM_WINDOWPOSCHANGING这两个消息,而消息的参数指定了开始按钮的位置为(0,0),于是它又恢复回去了。如果不明白,你可以通过SPY++这个工具来捕获。而实际上,我也是用它来捕获到的。
这时也许你已经想到了,我们可以在开始按钮的窗口函数中拦截这两个消息,使它的位置不为(0,0),而改变成我们定义的位置。要拦截这两个消息,那么就得用我们自定义的窗口函数将原来开始按钮的窗口函数替换掉。这是你也许已经想到了,使用SetWindowLong改变原窗口函数地址,使它指向我们定义的窗口函数。但是遗憾的是,并不想我们想的这样简单,WINDOWS不允许一个进程访问另一个进程的进程空间,别说更改目标窗口函数地址,连访问一个变量都不行。
这时我们唯一的方法就是将我们的代码注入到开始按钮的进程空间中,即Explorer,进程注入的方法我就不说了,我们使用最简单也最不费事的HOOK方式注入。代码如下:
HWND hStartButtonWnd = NULL;
HWND hTaskWnd = NULL;
hTaskWnd = FindWindow("Shell_TrayWnd", NULL);
if (hTaskWnd != NULL)
{
hStartButtonWnd = FindWindowEx(hTaskWnd, NULL, "Button", NULL);
if (hStartButtonWnd != NULL)
{
DWORD hThreadId = GetWindowThreadProcessId(hStartButtonWnd, NULL);
if (hThreadId != 0)
{
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hInst, hThreadId);
}
}
}
HOOKPROC中的主要代码如下:
hTaskWnd = FindWindow("Shell_TrayWnd", NULL);
if (hTaskWnd != NULL)
{
hStartButtonWnd = FindWindowEx(hTaskWnd, NULL, "Button", NULL);
g_hBtnOldProc = (WNDPROC)GetWindowLong(hStartButtonWnd, GWL_WNDPROC);
SetWindowLong(hStartButtonWnd, GWL_WNDPROC, (LONG)ButtonWndProc);
}以上代码说明如下:
首先获得开始按钮的窗口句柄,然后再通过窗口句柄得到线程ID,并根据线程ID安装消息钩子函数;一旦消息到达,即执行消息钩子函数。在消息钩子函数中获取开始按钮窗口句柄,然后调用GetWindowLong取得原窗口函数地址以便保存,再调用SetWindowLong更改其窗口函数地址为我们定义的窗口函数ButtonWndProc。
至此我们已经成功将代码注入并更改了开始按钮的窗口函数,接下来要做的就是在窗口函数中拦截WM_MOVE和WM_WINDOWPOSCHANGING这两个消息了。代码如下:
LRESULT CALLBACK ButtonWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_MOVE:
{
MoveWindow(hwnd, 76, 0, 50, 25, TRUE);
break;
}
case WM_WINDOWPOSCHANGING:
{
MoveWindow(hwnd, 76, 0, 50, 25, TRUE);
break;
}
}至此开始按钮可怎么也恢复不回去了,呵呵,动手试试看吧。不过最后记得归还原窗口函数地址哦,不然你的Explorer是必死无疑的了。该在哪里恢复窗口函数地址呢?在什么地方调用UnhookWindowsHookEx呢?自己思考吧,放错了地方Explorer依然会死的哦。
到此就已经成功让WINDOWS的开始按钮靠边站了。不过如果只这样让它挪挪地方,那空出来的地方空空的总让人觉得不爽啦,所以还得放点什么在上边吧,比如女朋友的相片啊或什么的,甚至还可以做个和WINDOWS的开始菜单一样的东西来。这些功能就由你自己去自由发挥了,呵呵。不过在交互时你也许会遇到一些麻烦,比如你在开始按钮原来的位置上放了一个自己的按钮,那么这个按钮的事件你的应用程序如何才能得知或其它什么更复杂的操作,不过都应该不是什么大问题,相信你能够自己解决的。
就写这么多了,很久没写技术类的文章了,有没有写清楚自己都不知道,错了的莫怪哈。有什么不懂的大家提出来相互讨论就是了。这段时间一直在加班,累死掉了。