zoukankan      html  css  js  c++  java
  • [VC++]在应用程序中监视剪贴板的变化和内容

    剪贴板是Windows中系统级的堆空间,系统中任何一个应用程序对剪贴板都有访问权,可以通过剪贴板消息和使用剪贴板API来读写

    剪贴板内容。
                
    正在装载数据……
          
    因此使用剪贴板不仅可以在同一个应用程序内交互数据,也可以在不通应用程序之间交互数据。尤其是在不通应用程序之间交互时


    ,应用程序往往需要对剪贴板内容的变化做到实时感知,即应用程序要能监视剪贴板内容的变化。
          
          
    Windows应用是消息驱动的,同理当剪贴板内容发生变化时,Windows提供了剪贴板变化消息,因此要实时感知剪贴板内容的变化,


    关键是应用程序要能响应和处理Windows触发的剪贴板变化消息。
          
          第一步,要将窗口注册为Clipboard
    Viewer
          需要首先解释两个概念:Clipboard Viewer和Clipboard
    Viewer Chain。
          Clipboard
    Viewer是一个需要取得并显示剪贴板内容的窗口,通过Clipboard
          
    Viewer这个机制,应用程序可以在不影响剪贴板内容的情况下获取剪贴板的变化消息。Clipboard
          
    Viewer可以显示系统定义的标准格式的剪贴板内容,也可以显示应用自定义的私有数据格式的内容。通过调用函数


    SetClipboardViewer将窗口注册为Clipboard
          Viewer。
          
    Clipboard Viewer Chain是保存Clipboard
          
    Viewer窗口以及他们之间的前后向关系的一个Windows系统链表,当一个窗口注册为Clipboard
          Viewer后,他会被加入Clipboard Viewer
          
    Chain,并得到链表中下一个Viewer窗口的句柄,该句柄必须保存以在响应消息时使用,该句柄的作用在下文说明。Windows正是通


    过Clipboard
          
    Viewer Chain保证了所有Clipboard
    Viewer能接收和响应剪贴板变化消息。
          
          
    第二步,响应剪贴板变化消息,判断和取出剪贴板内容
          
    在消息响应里必须正确处理两个消息:WM_DRAWCLIPBOARD和WM_CHANGECBCHAIN。
          
          
    当剪贴板内容发生变化时,Windows将触发WM_DRAWCLIPBOARD消息,并将该消息送给Clipboard Viewer
          Chain的第一个窗口。每一个Clipboard
          
    Viewer窗口,包括第一个窗口在响应和处理该消息后,必须根据其保存的链表中的下一个窗口的句柄将该消息发送给下一个


    Clipboard
          
    Viewer窗口。窗口可以在该消息中取出剪贴板内容,并判断是否是该窗口增在监视的内容,如果是就进行相应的处理。
          
          当某个Clipboard
    Viewer窗口注销时,系统将触发WM_CHANGECBCHAIN,并将该消息送给Clipboard Viewer
          
    Chain的第一个窗口。每一个窗口必须处理该消息。
          
          第三步,将窗口从Clipboard Viewer
    Chain中注销
          
    当窗口不再需要监视剪贴板变化消息,或窗口要关闭时,必须调用ChangeClipboardChain函数将窗口从Clipboard Viewer
          
    Chain中注销。注销后系统会触发WM_CHANGECBCHAIN消息,同WM_DRAWCLIPBOARD消息一样,该消息会给发送给Clipboard
          Viewer
    Chain的第一个窗口处理。下面代码示例当窗口被关闭时进行注销。
          
          
    下面的代码片断给出了监视剪贴板中是否拷贝了URL地址的例子,如果剪贴板中的内容是URL地址,则将其显示在窗口界面上。为使


    示例代码具有一般性,下面给出了一般Windows程序代码和基于MFC的代代码。其他语言要实现该功能可以参考Windows程序代码。两个

    DEMO的完成代码请见附件。
          
          
    Windows程序示例代码
          LRESULT CALLBACK WndProc(HWND
    hWnd, UINT message, WPARAM wParam, LPARAM
          
    lParam)
          
    {
              int wmId,
    wmEvent;
              PAINTSTRUCT
    ps;
              HDC
    hdc;
              unsigned int
    anFormats[] =
    {CF_TEXT};
              unsigned
    int nFormat;
          
              switch (message)
              
    {
                  
    //----------------------------------------------------------------
          
                  
    case WM_CREATE:
                      
    //将本窗口注册到Clipboard Viewer
    Chain,
                      
    //并保存Clipboard Viewer
    Chain中下一个窗口的句柄
                      
    hwndNextViewer = SetClipboardViewer(hWnd);
                      
    break;
                  
    case WM_CHANGECBCHAIN:  //Clipboard
    Viewer注销
                      
    //如果注销的Clipboard
    Viewer窗口是本窗口的下一个窗口,
                      
    //则修改本窗口保存的下一个窗口句柄,
                      
    //否则将该消息传递到Clipboard Viewer
    Chain的下一个窗口
                      
    if ((HWND) wParam == hwndNextViewer)
                          
    hwndNextViewer = (HWND) lParam;
                      
    else if (hwndNextViewer != NULL)
                          
    SendMessage(hwndNextViewer, message, wParam, lParam);
                      
    break;
                  
    case WM_DRAWCLIPBOARD:  
    //剪贴板内容变化
                      
    //触发ON_PAINT显示URL内容
                      
    InvalidateRect(hWnd, NULL, TRUE);
                      
    UpdateWindow(hWnd);
                      
    //否则将该消息传递到Clipboard Viewer
    Chain的下一个窗口
                      
    SendMessage(hwndNextViewer, message, wParam, lParam);
                      
    break;
                  
    case
    WM_DESTROY:
                      
    //从Clipboard Viewer
    Chain注销本窗口
                      
    ChangeClipboardChain(hWnd, hwndNextViewer);
                      
    PostQuitMessage(0);
                      
    break;
                  
    //----------------------------------------------------------------
                  
    case
    WM_COMMAND:
                      
    wmId    = LOWORD(wParam);
                      
    wmEvent = HIWORD(wParam);
                      
    // Parse the menu
    selections:
                      
    switch
    (wmId)
                      
    {
                          
    case
    IDM_ABOUT:
                            
    DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX,
          hWnd,
    (DLGPROC)About);
                            
    break;
                          
    case
    IDM_EXIT:
                            
    DestroyWindow(hWnd);
                            
    break;
                          
    default:
                            
    return DefWindowProc(hWnd, message, wParam,
    lParam);
                      
    }
                      
    break;
                  
    case
    WM_PAINT:
                      
    hdc = BeginPaint(hWnd,
    &ps);
                      
    //判断剪贴板中的内容是否为URL地址,如是则显示
                      
    nFormat =
          
    GetPriorityClipboardFormat(anFormats,sizeof(anFormats));          
                      
    if(nFormat ==
    CF_TEXT)
                      
    {
                          
    OpenClipboard(hWnd);
                          
    HGLOBAL hMem = GetClipboardData(nFormat);
                          
    LPTSTR lpstr = (LPTSTR)GlobalLock(hMem);
          
                          
    if(strstr(lpstr,"http://") != NULL
    ||
                            
    strstr(lpstr,"ftp://")  != NULL
    ||
                            
    strstr(lpstr,"file://") !=
    NULL)
                          
    {
                              
    RECT
    rt;
                              
    GetClientRect(hWnd,
    &rt);
                              
    DrawText(hdc, lpstr, -1, &rt,
    DT_LEFT);
                          
    }
                          
    GlobalUnlock(hMem);
                          
    CloseClipboard();
                      
    }
                      
    EndPaint(hWnd,
    &ps);
                      
    break;
                  
    default:
                      
    return DefWindowProc(hWnd, message, wParam,
    lParam);
            
    }
             return
    0;
          }
          
          MFC程序示例代码
          
    首先要映射以下消息和继承以下函数
          afx_msg void
    OnChangeCbChain(HWND hWndRemove, HWND
    hWndAfter);
          afx_msg void
    OnDrawClipboard();
          afx_msg void
    OnDestroy();
          virtual void
    OnInitialUpdate();
          
          
          void
    CMonitorUrlView::OnInitialUpdate()
          
    {
              
    CListView::OnInitialUpdate();
          
              m_pListCtrl =
    &GetListCtrl();;
              
    m_pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT
    |
                                            
    LVS_EX_GRIDLINES
    |
                                            
    LVS_EX_TRACKSELECT
    |
                                            
    LVS_EX_TWOCLICKACTIVATE
    |
                                            
    LVS_EX_UNDERLINECOLD);
              
    m_pListCtrl->ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
              
    m_pListCtrl->InsertColumn(0, "URL",LVCFMT_LEFT,600,1);  
          
              //将本窗口注册到Clipboard
    Viewer Chain,
              
    //并保存Clipboard Viewer
    Chain中下一个窗口的句柄
              
    m_hwndNextViewer = SetClipboardViewer();
          
    }
          
          
    void CMonitorUrlView::OnDestroy()
          
    {
              
    CListView::OnDestroy();
            
              //从Clipboard Viewer
    Chain注销本窗口
              
    ChangeClipboardChain(m_hwndNextViewer);
          
    }
          
          
    //Clipboard Viewer注销
          void
    CMonitorUrlView::OnChangeCbChain(HWND hWndRemove, HWND hWndAfter)
          
    {
              //如果注销的Clipboard
    Viewer窗口是本窗口的下一个窗口,
              
    //则修改本窗口保存的下一个窗口句柄,
              
    CView::OnChangeCbChain(hWndRemove,hWndAfter);
          
              if(hWndRemove ==
    m_hwndNextViewer)
                  
    m_hwndNextViewer = hWndAfter;
          
    }
          
          
    //剪贴板内容变化,判断剪贴板中的内容是否为URL地址,如是则显示
          void
    CMonitorUrlView::OnDrawClipboard()
          
    {
              
    CView::OnDrawClipboard();
                
              unsigned int
    anFormats[] =
    {CF_TEXT};
              unsigned
    int nFormat =
          
    GetPriorityClipboardFormat(anFormats,sizeof(anFormats));
              if(nFormat ==
    CF_TEXT)
              
    {
                  
    HGLOBAL
    hMem;
                  
    OpenClipboard();
                
                  
    if(hMem =
    ::GetClipboardData(CF_TEXT))
                  
    {
                      
    LPTSTR lpszText = (LPTSTR)
    GlobalLock(hMem);
                      
    CString strURL =
    lpszText;
                      
    strURL =
    strURL.SpanExcluding("\r\n");
                    
                      
    if(strURL.Left(7).CompareNoCase("http://") == 0
    ||
                        
    strURL.Left(6).CompareNoCase("ftp://")  == 0
    ||
                        
    strURL.Left(7).CompareNoCase("file://") ==
    0)
                      
    {              
                          
    m_pListCtrl->InsertItem(0,lpszText);
                      
    }
                      
    GlobalUnlock(hMem);
                  
    }
                  
    CloseClipboard();
              
    }  
          }

  • 相关阅读:
    MVC是什么?
    Slice Header中的field_pic_flag的含义?
    Slice header 中的frame_num的含义?
    上下文管理器 contextlib
    mixin模式特点
    Flask中路由原理
    使用Docker搭建Django,Nginx,R,Python部署环境
    使用Docker+Jenkins自动构建部署
    Jenkins 关闭和重启
    使用pipenv管理python项目
  • 原文地址:https://www.cnblogs.com/boneking/p/1337809.html
Copyright © 2011-2022 走看看