• 关于 类似QQ 长截图的方案


    -、屏幕截图:

       长截图时,整个截图界面其实是个异形窗体, 其大体思路是先创建一个半透明的窗体,然后根据截图区域来创建异形窗体。

      异形窗体:

           hRgn :=CreateRectRgn(rt.left,rt.top,rt.right,rt.bottom); //rt为截图区域

           hWndRect:= CreateRgn(0,0,self.width,self.height);

         if CombineRgn(hWndRect,hWndRect,hRgn,Rgn_Xor)<>Error then

          SetWindowRgn(Handle,hWndRect,False);

    二、Hook windows消息

       (1)Hook  WH_MOUSE_LL

            其目的是控制滚动速度,方便截图。同时要将截图区域的滚动条禁用,以免影响连续截图。

         WH_MOUSE_LLProc(icode:integer;w:Wparam;l:Lparam):LRESULT;stdcall

         begin

                   if (icode<0) or (icode<> hc_action) then

                  begin

                          Result:= callNextHookEx(g_mouseWheel_hook,icode,w,l);

                         exit;

                  end; 

                if(w<> WM_MOUSELWHEEL) and( w<>WM_LBUTTONDOWN) and (w<>WM_LBUTTONUP) then

              begin

                       Result:=callNextHookEx(g_mouseWheel_hook,icode,w,l);

                      exit(-1); //返回 <0的值 才能阻止消息进入windows 消息循环。

             end

             mslhook = PMSLLHOOKSTRUCT(l);

            if not assign(mslhook ) then

            begin

                   

                        Result:=callNextHookEx(g_mouseWheel_hook,icode,w,l);

                      exit;

            end

             if( w<>WM_LBUTTOnDOWN) or(W<>WM_LBUttonUp) then exit(-1);

              

            iwheeldelta = short(HiWord(mslhook^.mouseData)); //根据iWheeldelta的值 便可知道 是向上滚动还是向下滚动.

            //控制滚动速度,根据需要,可自行调整

           if i>=3 then

           begin

                                      iTickcount :=GetTickCount;

                                    if iTickount - FtickCount>300 then

                                  begin

                                        //发送消息到主窗体,实现拼图功能

                                       PostMessage(Form.Handle, WM_User+100,iWheelDelta,0);

                                        FTickCount := iTickCount;

                                      i:=0;

                                 end

                                      else

                                     Exit(-1);

          end

         else

         begin

                  inc(i);

                 exit(-1);  

    end

          result :=CallnextHookEx(g_MouseWheel_Hook,icode,w,l);  

        end;

     *(2) 如果想做类似QQ的那种点击截图区域后,可自行滚动截图的功能,还需要Hook , WM_GetMessage.

             在此消息的HookProc  里面自行处理 WM_MouseWheel消息。

    三、拼图

    此部份是最重要的一部份,最简单的做法 是利用 opencv的surf、orb 等算法实现图片拼接。

    参考网址:https://www.cnblogs.com/skyfsm/p/7411961.html

    上述网址只是给出了两张图片的拼接,而且是左右拼接,而我们截图需要的上下拼接,最简单直接的做法就是先将图片旋转90度,拼接完成后再旋转回来

    为了提高效率与准确率,最好使用 “增量拼接'的方式,也就是

     A 与B拼接后 生成Ab,

    当与C拼接时,不要用AB与C拼接,而要使用 b与C拼接生成BC,然后将AB中的B扣掉 合并生成ABC.

    上面的无论surf算法、还是orb算法,都存一个问题。如果 两张图片 有 2个以上的重叠区域时,最后合并生成的图片ABC会有问题。最简单的实验就是去截图带导航栏的门户网站,一试便知。

    仔细分析,我们会发现 具有重叠区域的A、B两张图的拼接,转成数学问题,其本质就是求两个集合的最大交集。

    所以 自写算法如下:

    f b c d g --- list2
    a 0 0 0 0 0
    b 0 1 0 0 0
    c 0 0 2 0 0
    d 0 0 0 3 0
    e 0 0 0 0 0
    f 0 0 0 0 0
    |
    list1

    void max_substring(const std::vector<float> &a1,const std::vector<float> &a2,
    int & max1_index, int & max2_index, int & max_count)
    {
    int len1 = a1.size(); int len2 = a2.size();
    std::vector< std::vector<int16_t> > mat(len1, std::vector<int16_t>(len2));
    max_count = 0; max1_index = 0; max2_index = 0;

    for(int i=0;i<len1;i++)
    for(int j=0;j<len2;j++)
    {
    if(i==0 || j==0) { mat[i][j] = 0; continue; }

    if(fabs(a1[i]-a2[j])<0.5)
    {
    int count = mat[i][j] = mat[i-1][j-1] + 1;
    if(count>max_count) { max_count=count; max1_index=i-count+1; max2_index=j-count+1; }
    }
    else { mat[i][j] = 0; }

    }

    }

    注明:上述算法也有些缺陷,并不满足所有的条件,当图片是 纯 白底、黑字的图片时,也会出现拼图错误,我想这也是QQ长截图有时候也不灵的原因吧。

  • 相关阅读:
    点击表单提交 却打开了另存为对话框
    js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)
    html怎么隐藏input标签
    莫名其妙地改变了数组的值,原来是……
    addEventListener 用法
    JavaScript DOM元素常见操作详解【添加、删除、修改等】
    MySQL用户权限验证与管理方法详解
    mysql如何修改root用户的密码
    python案例
    IDEA启动报 Error:java: JDK isn't specified for module 'xxx' 已解决
  • 原文地址:https://www.cnblogs.com/luisfan/p/14591786.html
Copyright © 2020-2023  润新知