首页 > 代码库 > 简单易懂的小应用StayOnTop

简单易懂的小应用StayOnTop


应用场景:
        当你需要边聊天边看网页的时候, 你就不能把浏览器最大化, 或者需要看一下网页再去任务栏把聊天窗口点出来, 超麻烦不是?很多网页两边都是空白的, 如果能让聊天窗口置顶的话, 这个空间就得以利用了.但其实这又是个伪需求, 腾讯哪能没想到?  每个窗口的右上角都有一个小按钮, 随时可以让窗口置顶.

   

      但其他软件就没得玩了,  一边看网上的Step-by-step教程, 一边来回切换窗口真是麻烦死了, 当时就萌生了花一个晚上来写它的想法.(其实这样的工具应该一大把...另Linux下的话自带置顶功能)
所以目标确定了, 我要做一个能让任意窗口置顶的小工具.

知识点:
      
窗口: Windows是以窗口作为主要交互界面的系统, 我们把那个能拖来拖去, 一般带有最大化最小化关闭按钮的大方框叫做窗口, 但是其实窗口的定义可以更广泛一点, 一个按钮是窗口, 一个文本框也是窗口.
      父窗口: 如果一个按钮(Button)被放在一个Panel(面板)上,   那按钮的父窗口就是Panel, 同样Panel的父窗口是Form, Form就是我们平时说的窗口了;
      顶级窗口: Form的父窗口是什么?  有人说是桌面(Desktop), 也有人说没有父窗口, 但是通过实验得知, 它没有父窗口, 没有父窗口的窗口我们叫做顶级窗口, 我们平时说的窗口, 都是指的顶级窗口;
      句柄: Handle, 这个"句柄"绝对是IT界的神翻译, 谁知道句柄是个什么意思?! 句柄是一种特殊的指针, 指向的是内存里的对象,  通俗得讲它就是一个窗口(事实上远不止窗口)的把手, 你有了这个句柄就能开窗关窗, 改变窗口的状态, 这样的形容虽然不贴切, 但足够生动了吧?
改变窗口的状态?  对了, 只要我们获得顶级窗口句柄 ,改变它的状态, 把"不置顶"改为"置顶", 就达成目的了.



梳理逻辑:

     自己做的工具不需要考虑太多, 而且要尽量简单易用, 实现上述的功能只需要几个API(Application Programmng Interface自行百度), 甚至连窗口都不需要, 所以决定用C语言.
流程如下: 1.获得顶级窗口的句柄 , 2.改变它的状态.
哪个窗口呢? 你需要指定一个窗口,    怎么指定?
能想到最好的方案是用鼠标指定, 你鼠标放在哪一个窗口, 就是哪一个窗口;
有函数GetCursorPos(), 能够取得鼠标所在的点;
又有函数WindowsFromPoint(),
取得在某点的窗口的句柄;
注意, 取得的是窗口的句柄, 要怎么的得到顶级窗口的句柄呢? 不停地找这个窗口的父窗口, 直到某个窗口的父窗口的句柄为0(不存在), 那就找到了,
有函数GetParent(), 能取得窗口的父窗口.
取得顶级窗口的句柄后, 有函数SetWindowPos, 指定参数HWND, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_DRAWFRAME | SWP_NOSIZE 就能置顶一个窗口.
废话了那么多, 其实核心代码只有6句,加了些修饰如下:

HWND GetHwnd()

{

    POINT p;

    HWND hwd;

    GetCursorPos(&p);

    hwd = WindowFromPoint(p);

    while (GetParent(hwd))

        hwd = GetParent(hwd);

    return hwd;

}
SetWindowPos(GetHwnd(),HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_DRAWFRAME | SWP_NOSIZE);


另, 以上函数都包含在Windows.h中,
创建没有窗体的C语言工程, 可以新建Win32工程然后删去所有代码, 使用普通的Main函数即可.




完整代码:

#include <windows.h>

#include <string.h>

HWND GetHwnd()

{

    POINT p;

    HWND hwd;

    GetCursorPos(&p);

    hwd = WindowFromPoint(p);

    while (GetParent(hwd))

        hwd = GetParent(hwd);

    return hwd;

}

int main(int argc, char* args[])

{

    if (argc < 2)

    {

        SetWindowPos(GetHwnd(),HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_DRAWFRAME | SWP_NOSIZE);

        return 0;

    }

    else

    {

        if (!strcmp("/?", args[1]))

        {

            MessageBox(0,

                "Availableparameters:\n/?\n/no param: stay on top.\nother param: cancel\n\n         2014.2.21 LastAvenger",

                "Help",

                MB_OK

                );

        }

        else

            SetWindowPos(GetHwnd(),HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_DRAWFRAME | SWP_NOSIZE);

    }

}