安装VSCode

下载地址:https://code.visualstudio.com/

直接download即可,下载好之后打开exe一路使用默认设置下一步即可安装成功

VScode 安装汉化包很简单,打开 VScode,点击安装扩展,在搜索框输入 Chinese,然后点 Install 就可以:

安装Python

下载地址:https://www.python.org/

直接download最新的版本即可

下载好后开始安装,安装的时候务必勾选 Add Python x.x to PATH

安装好之后打开VSCode,点击侧边栏的Manage extensions图标,搜索Python,选择第一个点击install即可。

如果你在使用安装程序安装Python的时候没有勾选 Add Python x.x to PATH ,请

右键此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量将Python的路径添加到Path栏即可。

全部安装好之后,新建一个.py文件,尝试写一个print(‘helloworld’)并运行看看是不是把Python环境配置好了~

安装Anaconda

下载地址:https://www.anaconda.com/

直接点击Download即可。

直接一路Next完成安装即可。

安装完成之后,将Anacoda所安装路径以及路径下的一些文件夹添加到环境变量中的系统变量的Path栏中。

比如我添加的路径如下:

C:\Users\dxf\anaconda3
C:\Users\dxf\anaconda3\Scripts
C:\Users\dxf\anaconda3\Library\mingw-w64\bin
C:\Users\dxf\anaconda3\Library\usr\bin
C:\Users\dxf\anaconda3\Library\bin

配置好环境变量之后,打开控制台cmd,输入conda –version,如图就是conda环境配置好了~

如果显示conda不是内部或外部命令,那么一般就是添加环境变量这一步出了问题。

若conda安装成功,我们可以直接在Win10的搜索框搜索Anaconda,打开如下图所示的软件

经过漫长的自动配置之后,出现了下图所示界面

因为我们已经提前安装好了VSCode了,所以在此可以直接点击Launch打开VSCode,在VSCode中按Ctrl+Shift+P,输入Python Select,选择Python的解释器为Anaconde所在目录的Python解释器,然后就可以开始写代码惹~

最近ai火热,对于出门的需求越来越大,使用公共机场容易被ai提供方识别ip一网打尽。只能付出相当高的费用买更高等级的魔法。而我这里提供我自己正在使用的一种方案,自行购买云服务器,对你使用ai带来便利,而且价格相当良心,19.95欧元买到1核心2g运存,30g存储空间,带宽1gbps,每个月流量2t,经过实际测试裸连速度7-9mb/s,虽然没宣传那么夸张,但是毕竟这是国外的服务器。在经过各种操作后稳定下来的速度在3mb/s之内,速度不快,但是刷个视频啥的妥妥够用。缺点是要有折腾的能力,具备一些基本的计算机知识,但为了一个真正意义上独享的ip这是值得的。

(1)首先你需要访问云服务器提供商v.ps的网站https://vps.hosting/cart/nano-kvm-vps/

目前只有19.95欧元的了,9.9已经卖断货了。
系统这里选择centos7就可以了

在选择好后点击order如果没注册会要求你注册,注册之后会提示你订单没有付款,你就选择支付宝付款就好了,这一步可能有点繁琐,因为你的邮箱会有大量的注册邮件,你需要找到其中一个验证邮件激活你的账号,但总之细心一点就能做完。

(2)下载ssh工具连接到我们的服务器,我推荐Xhell,中文界面,对新手友好。在下载的空闲时间你可以打开cmd,输入ping+空格+你购买服务器的ip地址

ipaddress是你服务器的IP地址

在cmd工具中测试你的ip通畅后就可以进入下一步了,打开ssh工具新建连接,密码在主机详情页的password,点击show就可以查看。

(3)安装宝塔面板,宝塔面板部署后易用性会大大增强,我们配置防火墙和编辑配置文件都会轻松很多,具体安装方法进入宝塔面板官网查看,有一键安装的命令,在xshell中粘贴命令为shift+insert。

4)成功进行到这一步之后就完成了一半,剩下的步骤无法在这里说明,请参考https://www.4spaces.org/780.html    或者https://www.wxiou.cn/index.php/archives/54/

另外这两部文章介绍的方法会要求你有个域名,其实不用域名也可以,但注册一个域名会更保险,防止你的服务器ip被墙。此文章主要是介绍购买服务器。因为这家厂商的云服务器一个月之前全都有,现在只剩法兰克福了,所以时间仓促我赶紧写文希望有需要的朋友购买。后续具体的教程我会更新在博客中。

@45°夹角的考研力

1.只出现一次的数字

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int result = nums[0];
        for(int i = 1; i < nums.size() ;i++){
            result = result ^ nums[i];
        }
        return result;
    }
};

2.多数元素

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        //出现次数超过一半的数字一定是出现最多的数字
        map<int , int>mp;
        int max = 0;//出现次数
        int result = 0;//出现次数最多的数字
        for(int i = 0; i < nums.size() ; i++){
            if(mp.find(nums[i]) != mp.end()){//map中找得到该数字
                mp[nums[i]] = ++mp[nums[i]];
                if(mp[nums[i]] > max){
                    max = mp[nums[i]];
                    result = nums[i];
                }
            }
            else{//map中找不到该数字
                mp[nums[i]] = 1;
                if(1 > max){
                    max = 1;
                    result = nums[i];
                }
            }
        }
        return result;
    }
};

3.搜索二维矩阵 II

class Solution {
public:
    bool findTarget(vector<vector<int>>& matrix , int i , int j , int target){
        if(matrix[i][j] == INT_MIN){//递归可能会超时,需要将递归经过的地方设置为INT_MIN,之后递归再次遇到该值直接跳过;
            return false;
        }
        else if(matrix[i][j] == target){
            return true;
        }
        else if(matrix[i][j] > target){
            return false;
        }
        else{
            matrix[i][j] = INT_MIN;
        }

        if(i == matrix.size()-1 && j == matrix[i].size()-1){//最后一行最后一列
            return false;
        }
        else if(i == matrix.size()-1){//最后一行
            return findTarget(matrix , i , j+1 , target);
        }
        else if(j == matrix[i].size()-1){//最后一列
            return findTarget(matrix , i+1 , j , target);
        }
        if(matrix[i][j] < target && matrix[i+1][j] > target && matrix[i][j+1] > target){
            return false;
        }
        return findTarget(matrix , i+1 , j , target) || findTarget(matrix , i , j+1 , target);
    }

    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        return findTarget(matrix , 0 , 0 , target);    
    }
};

4.合并两个有序数组

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        vector<int> nums3;
        int p1 = 0;
        int p2 = 0;
        while(p1 < m && p2 < n){
            if(nums1[p1] <= nums2[p2]){
                nums3.push_back(nums1[p1]);
                p1++;
            }
            else{
                nums3.push_back(nums2[p2]);
                p2++;
            }
        }
        if(p1 == m){
            for(int i = p2 ; i < n ; i++){
                nums3.push_back(nums2[i]);
            }
        }
        else if(p2 == n){
            for(int i = p1 ; i < m ; i++){
                nums3.push_back(nums1[i]);
            }
        }
        nums1.resize(0);
        for(int i = 0; i < m+n ;i++){
            nums1.push_back(nums3[i]);
        }
    }
};

5.验证回文串

class Solution {
public:
    bool isPalindrome(string s) {
        //大写转换为小写
        for(int i = 0; i < s.length() ;i++){
            if(s[i] >= 'A' && s[i] <= 'Z'){
                s[i] = s[i] + 32;
            }
        }
        int i = 0;
        int j = s.length() - 1;
        while(i < j){
            //筛选掉非数字和字母的部分
            while(!((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= '0' && s[i] <= '9'))){
                i++;
                if(i >= j){
                    return true;
                }
            }
            while(!((s[j] >= 'a' && s[j] <= 'z') || (s[j] >= '0' && s[j] <= '9'))){
                j--;
                if(i >= j){
                    return true;
                }
            }
            if(s[i] != s[j]){
                return false;
            }
            else{
                i++;
                j--;
            }
        }
        return true;
    }
};

6.有效的字母异位词

class Solution {
public:
    bool isAnagram(string s, string t) {
        int flag[26];
        memset(flag , 0 , 26*sizeof(int));
        for(int i = 0; i < s.length() ; i++){
            flag[s[i]-'a']++;
        }
        for(int i = 0; i < t.length(); i++){
            flag[t[i]-'a']--;
        }
        for(int i = 0; i < 26 ;i++){
            if(flag[i] != 0){
                return false;
            }
        }
        return true;
    }
};

7.字符串中的第一个唯一字符

class Solution {
public:
    int firstUniqChar(string s) {
        int flag[26];
        memset(flag , 0 , 26*sizeof(int));
        for(int i = 0; i < s.length() ; i++){
            flag[s[i]-'a']++;
        }
        for(int i = 0; i < s.length() ; i++){
            if(flag[s[i]-'a'] == 1){
                return i;
            }
        }
        return -1;
    }
};

8.反转字符串

class Solution {
public:
    void swap(char &s1 , char &s2){
        char tmp = s1;
        s1 = s2;
        s2 = tmp;
    }

    void reverseString(vector<char>& s) {
        int i = 0;
        int j = s.size() - 1;
        while(i < j){
            swap(s[i] , s[j]);
            i++;
            j--;
        }
    }
};

学理工科的,受现代科技高度分化与深入细节的特性所困,往往满脑子被公式,理论,模型,算法,代码……等塞满,推崇理性,但往往并不感到多少幸福,因为理性并不必然带来幸福,更有可能带来中性的“冷静”,或者偏副面的“冷酷”。

人其实还是偏感性的生物,幸福更是一种主观感受而非客观事物,更多来自于关系和社会,科技带不来这些。

但理工科的许多人,大部分时间都被科技所占用,社交圈子不大,生活方式比较单调,真没多少时间去“感悟”和“体会”人生与社会万象。

无法行万里路,见百般人,但可以读万卷书。

我觉得吧,应该多看书,种类要多,还可以看一些优秀的影视文学作品,尤其是那些反映现实而不是构建幻境的优秀作品,还可以多听多看一些智者及过来人的观点和感悟。

在这信息丰富的时代,找到这些其实并不困难。

想办法拥有一个通透的心境,其实比许多外在的东西,比如名利之类,价值更高,更容易让人感到平和与幸福。

每个人的生活,其实就是在讲一个故事。

再理性再智慧的人,也是没有办法完全获知所有真相的,人们是在用自己的方式模拟现实。现实中的一切,本身是没有意义的。魔方是同个颜色都在同一面,还是混乱的颜色,对魔方本身来说有什么区别吗?是人赋予他们意义。最后,现实往往是松散的,事与事之间,关联性很弱。是人把他们串在了一起。形成了我们头脑中的意义,一个连续的故事。

有的故事有趣,有的故事无聊。比如,有人说,人生的意义就在于繁衍后代,延续基因和宗族。那么,这个故事就是千方百计的生育,然后苟活下去。这个就比较无聊了。有的故事就像是打怪探险,遇到一个问题解决一个问题,打怪升级,积累经验,百折不挠,一步步通关。这个故事有趣一些。

有些故事讲着讲着讲崩了。这个时候就得跳出来。不要试图挽回,崩了的故事可能是个漩涡,永远圆不回来。不如存档退出再来。退出的办法有很多,最普遍的就是找个朋友倒苦水。只要他不是什么学了半吊子心理学的,只要是个普通人,给出的建议往往都会中肯有用。

我坐在书桌前,盯着那片白墙看了很久。
其实不算是白墙,墙上贴了浅色纹理的壁纸,只不过在昏暗的灯光下和白墙没什么差别。
在那之前,楼上装修的噪音又惹起了好久不犯偏头痛,我把自己整个蜷缩在沙发上,浑身乏力,头晕目眩,生不如死。
“庆历四年春,滕子京谪守巴陵郡。越明年,政通人和,百废俱兴,乃重修岳阳楼,增其旧制。”
记忆卡在这里,像是戛然而止的磁带,发出细微的嗞啦声,而后归于死寂。
看那面墙看久了,我突然好想推开椅子从窗户那里跳下去。
我希望我死了之后,没有人悲伤,没有人想念我,最好没有一个人记得我。我什么东西都没有拥有过,也不会拥有任何东西。
坐在车上,我只能想到车祸。看见高楼,我只能想到有个人在最高处坠落的样子。看见湖水,我只能想到自己失足掉下去的场景。
但我没有死,我还活着。卑微地、苟且地、懦弱地活着,双目失神地坐在这里,像平常的每一天一样。
并且我知道自己应该活下去。
这个念头让我反胃,于是我只好拼了命地将种种恶心与难受忍回去。好憋屈啊,好难受啊。
我的脑子里很空,什么都没有。它们都流失掉了,或许有一天我会忘记自己叫什么,为什么坐在这里。那时候我只能一遍又一遍地重复着《岳阳楼记》开头的那几句话,或许甚至不知道它们的文字排列有什么意义。
我不知道这样的我能等来什么。终于下定决心的死亡?佝偻苟且掉的一生?还是精神病房的消毒水味?或者是我最无法想象到的一点点救赎。
不可能。写到这里我笑了。
我盯着那面墙,觉得可笑。它像我一样,用力地雕琢了那么久,在昏暗的吊灯和惨白的台灯照射下,还是像一张白纸一样,一无所有。
我这一生,尽是可耻之事。
如果哪天我死了,就把这篇文章打下来,放在我身边吧。

你生活最艰难的时候,
不是物质上的身无分文,
也不是身体上遭受的痛苦折磨,
而是精神上的孤立无援。

无论这种孤立无援是如何产生的,
可能是一件件小事导致的情绪叠加,
亦或是突遭飞天横祸的无能为力。
你崩溃了。
那种感受犹如山洪的爆发,
你拼命的誓死抵抗,
但那种压抑的情绪浩浩荡荡,
螳臂当车,
你做的一切努力都被无情的碾过。
顿时,
你的胸口犹如钢枪穿过,
你的大脑好似暴风卷过。
震颤,压抑,悲愤,无力,失落。
无法冷静,无法克制,无法辩驳。
就连说话的力气都会颤抖到微弱。

你不甘心就此没落,
你被那种情绪一直侵袭着,
一天,两天,一个月,一年……
你始终没有走出来过。

你在同学,同事,朋友,家人面前依然洒脱,
只有你自己明白心里情绪的震烁。
你带着面具,
人前你笑着从未哭过,
只有你自己知道无数个深夜怎么度过。

你尝试着买醉过,
你尝试着得过且过,
你尝试了那么多,
终究还是难以抵挡内心的难过。
熬着熬着你习惯了,
混着混着你明白了,
没有人能拯救你自己,
你感觉迷茫,感觉这辈子就这样了。
可你始终没有想过,
无数个早晨你醒来照的镜子里那个人,
就是你唯一的依靠和解脱。

终于明白,
这个世界陪伴自己最久的终归是自己。
无论再坚固的朋友,
无论再亲密的爱情,
无论再和谐的家庭,
只有自己才是自己最好的寄托。
你要学会和自己好好相处,
你要学会倾听自己内心的声音,
有可能是真,有可能是假,
无论真假,你都要记得好好对待自己。
没有任何人比自己更重要。
这一点不自私。

最后你会发现,
原来那么多的过不去,
其实都是在和自己过不去。
你终于学会了如何和自己相处,
终于放过了自己,
也终于得到了解脱。

我如何知道这么多?
因为我正在经历着,
但还没有经历过。

From 2021.02.21

从前,有一只小鹿,一只小熊,和一只小兔子。
他们度过了很多春夏秋冬。
他们生活在一个生长着七彩树的森林里。
他们看过了不同的阳光穿透不同颜色的叶子。
他们在很多不同地方睡觉。
他们有时候逃亡,有时候安定。
他们互相分享共同成长。
后来小鹿爱上了另一只小鹿,
他走了。
接着小熊又爱上了另一只小熊,
他也走了。
小兔子没有爱上其他的兔子,
但他搬家了。
搬到没有七彩树,没有璀璨阳光的山谷里。
时间缓慢流淌,
像曾经他们屋前的小溪。
小鹿有一次路过,
看到了破败的屋子。
小熊有一次在周围找蜜顺便来看看,
看到了一片青苔满布的废墟。
小兔子一生也没回来过,
那房子还是那样,
再后来,
一只听说了他们故事的鸟儿,
要来这里看看,
他站在溪边望去
他不知道该往哪里看,到处都是花,到处都是树,到处都是蘑菇,到处都是小草。
故事,
是发生在这里吗?
小鸟在这里失声痛哭。

From 2020.12.14

虽然我今年在股票上赚取了十几万元,对于一些人来说,不多,但是对于我,是一种激励与证明,回想起之前失败的亏损时光,那是一段宝贵的经验。
没有人的股票投资生涯是一帆风顺的,你总是要付出一些学费,在跌倒的路上自己默默的爬起来,然后重新整理出发。
这一路真的很寂寞,学习宏观/微观经济学,会被人嘲笑,你学了有什么用?然后尝试学习行为经济学、商业模式、财报、各种投资书籍;还是被人嘲笑,学了用不上,有什么用?但是我不管别人质疑的眼光,坚定的持续学习。
经历过亏损甚至一度吃不上饭还不起债的人有一个好,那就是生死看淡,心态平稳。股价短期的涨跌,只是股民们的情绪波动,与企业价值无关;好的美玉,掉入垃圾桶,它还是美玉;一块普通的石头,哪怕吹的价值上天,它总归是一块石头而已;反而更应该关注那些有价值投资的公司。
市场上,真正能够长期成长的股票,真的不多。因此,可以说,大部分股票都是博弈的游戏,不值得长期持有。
但是,历史数据也告诉我们,能利用市场情绪在股市里长期赚到钱的人,也极其罕见。
相反,因为贪小便宜,想利用市场波动短线走位,结果却错失了大机会的投资者,却十分常见。所以,炒股要挣钱,别贪小便宜。
我们的身边,都可以看见这样一些投资者:这类投资者每次市场下跌,就在市场扫货,目标只是赚一波快钱。在赚取了蝇头小利或者市场陷入横盘后,便迅速卖出。
这类投资者,看似聪明,收益其实未必就好。
一只股票出现调整,如果能在低位买到,两三天之间就能赚个10%。这种跌出来的黄金坑,每只股票一年都会有好几次。
每次10%,当然非常好。可是,在跌市里,相信这些投资者也不会仓位太重,一般只会少量持仓。这样,总的回报就要打折,一年能有超10%的回报,可能就已经是非常罕见了。
如果与长期持有一只好股票,这样的收益就显得有些寒碜了。比如投资贵州茅台这样的公司,只要拿着,放弃短期差价,这样的投资者早已是赚的盆满钵满。
与长期持股相比,热衷短线的投资者不知道需要多少次大跌和黄金坑,多少次的精彩走位,才能炒出这样的回报?!
最后,股票投资,第一心态很重要;第二需要不断的学习金融、经济、投资、历史相关的东西;第三注意身体健康,不然赚钱了,钱都给医院或者没有命花啦。

这个话题并不是一个新的话题,网上有前辈做过详细的描述(Mixing Objective-C, C++ and Objective-C++: an Updated Summary)。之所以做为一篇文章,是因为在实际项目中用到了这种混合,加以记录。

首先需要澄清的是,Objective-C是strict superset of C。C++是基于C语言的面向对象的扩充,但不是strict superset of C。Objective-C++是Objective-C的扩展,使得Objective-C可以链接C++代码。通常情况下,要使用Objective-C++,需要将.m源文件改成.mm源文件。

其次需要澄清的是,Objective-C代码跟C++代码是不能混合使用的,也就是说,Objective-C的头文件中是看不到C++的头文件的。当然,C++的头文件是看不到Objective-C的头文件的。只有Objective-C++文件(也就是.mm文件)可以看到Objective-C的头文件和C++的头文件。

正因为Objective-C和C++互相不能见到对方的头文件,那么就意味着,现有的C++的代码库,想要在Objective-C中使用,是需要封装的,通常,这种封装是借助于Objective-C++写成的Wrapper.

另一方面,Wrapper本身也有技巧,那就是使用Objective-C的class extension特性(或者使用Pointer to implementation设计模式),避免将C++头文件暴露给Objective-C(否则无法编译通过)。具体细节可以参考文章开头的链接。

背景

在使用Qt给MacOS上的截图工具实现自动选中窗口区域需求的时候,原理无非就是获得桌面上可见的所有窗口的坐标以及尺寸,再将这些数据用一个结构体封装起来,按照在桌面的Z序进行排序,最后对鼠标的移动事件进行判断,按照Z序去对鼠标是否在某个窗口的矩形范围内进行判断,直到找到在范围内的矩形,这就是我们要自动选中的矩形了,如果将所有窗口都遍历完了还没发现鼠标正在某个矩形内的话,就不进行自动选中操作。

在Windows下我们可以很方便的使用EnumWindows这个Win32 API去获得桌面上所有窗口的坐标和尺寸,Win32 API可以由C++很方便的调用,而在MacOS上,单纯的使用C++仿佛无法获得我需要的这些数据,于是只好使用Apple的Objective-C提供的接口去获得这些数据。

通过在苹果开发者文档找到了MacOS上很多获得窗口信息的接口,使用CGWindowListCopyWindowInfo就能得到每个窗口的具体数据,接下来我们就要开始Qt与Objective-C混合编程了。

Objective-C是一种在C的基础上加入面向对象特性扩充而成的编程语言,通常称为jObC和较少用的 Objective C或ObjC。在一定程度上,可以把 Objective-C看成是ANSI版本C语言的一个超集,它支持相同的C语言基本语法,同时它还扩展了标准的 ANSI C语言的语法,包括定义类、方法和属性。当然还有其他一些结构的完善和拓展,如类别(Category)的出现。

所以Objective-c是可以直接调用C语言的,那么能否直接调用C++呢?答案是肯定的。

Objective-C源文件介绍

首先我要说一下Objective-C的源文件,后缀是.m或.mm,在.mm文件里,可以直接使用C++代码。所以,我们要混合Qt代码与Objective-C代码,就需要在Qt项目里加入mm文件。

而要混合Objective-C代码,需要更改一下pro文件,添加mm文件,如果有用到MacOS的API的话,则可能还需要添加MacOS的Framework。

添加源文件,需要在.pro中使用OBJECTIVE_SOURCES这个变量,如下所示:

OBJECTIVE_SOURCE += \
Getallvisiblewndpos.mm

添加头文件,需要在.pro中使用OBJECTIVE_HEADERS这个变量,如下所示:

OBJECTIVE_HEADERS += \
getallvisiblewndpos.h

添加Framework,需要在.pro中使用LIBS这个变量,如下所示:

LIBS += -framework CoreGraphics
LIBS += -framework CoreFoundation

混合代码

要使用MacOS提供的框架,需要在.mm文件内包含相关的头文件,又有几部分工作要做。一个是在.pro文件里加入Framework路径,使用LIBS变量即可,不多说了。另外一点是在mm文件内包含Objective-C的头文件,与C++头文件一个理儿,不过使用Objective-C的头文件要使用#import,而使用C++的头文件要使用#include,且所有的#include要写在#import的上面。

需要注意的是,凡是出现了Objective-C源代码和头文件的文件都需要将拓展名改成.mm,只有这样编译器在编译的时候才会既认识Objective-C代码,又认识C++代码。

注意事项

当遇到链接失败的问题时,如下图所示:

通常都是因为只引入了头文件而没有引入对应的Framework,通过在苹果开发者文档或者在Xcode中查找对应的Framework并添加到.pro文件中加以解决。

附赠Qt下Objective-C获得MacOS下所有窗口坐标、尺寸、Z序的方式:

//getAllVisibleWndPos.h
#ifndef GETALLVISIBLEWNDPOS_H
#define GETALLVISIBLEWNDPOS_H

#include <QRect>
#include <QList>
#include <vector>

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <CoreGraphics/CGWindow.h>
#import <CoreFoundation/CFArray.h>

struct WND_INFO{
	int layer;//Z序
	int index;//序号
	QRect pos;
};

bool CompareWNDINFO(const WND_INFO& A , const WND_INFO& B);
QList<WND_INFO> GetAllVisibleWndPos();

#endif // GETALLVISIBLEWNDPOS_H
//getAllVisibleWndPos.mm
#import <getallvisiblewndpos.h>

bool CompareWNDINFO(const WND_INFO& A , const WND_INFO& B)
{
	if(A.layer == B.layer)
	{
		return A.index < B.index;
	}
	if(A.layer > B.layer && B.layer > 0)
	{
		return true;
	}
	if(A.layer < B.layer && A.layer > 0)
	{
		return false;
	}
	return A.layer == 0;
}

QList<WND_INFO> GetAllVisibleWndPos()
{
	std::vector<WND_INFO> vec;
	CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements , kCGNullWindowID);
	CFIndex cnt = CFArrayGetCount(windowList);
	for (CFIndex i = 0; i < cnt ; i++)
	{
		NSDictionary *dict = (NSDictionary* )CFArrayGetValueAtIndex(windowList , i);
		int layer = 0;
		CFNumberRef numberRef = (__bridge CFNumberRef) dict[@"kCGWindowLayer"];
		CFNumberGetValue(numberRef , kCFNumberSInt32Type , &layer);
		if(layer < 0)
			continue;
		CGRect windowRect;
		CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)(dict[@"kCGWindowBounds"]) , &windowRect);
		
		QRectF pos;
		pos.setRect(windowRect.origin.x , windowRect.origin.y , windowRect.size.width , windowRect.size,height);
		
		WND_INFO info;
		info.layer = layer;
		info.pos.setRect(pos.x() , pos.y() , pos.width() , pos.height());
		info.index = i;
		
		vec.push_back(info);
	}
	
	std::sort(vec.begin() , vec.end() , CompareWNDINFO);
	QList<WND_INFO> list;
	for(int i = 0 ; i < vec.size() ; i++)
	{
		list.push_back(vec[i]);
	}
	return list;
}