在應用程式中監視剪貼簿的變化和內容 (轉)

amyz發表於2007-08-14
在應用程式中監視剪貼簿的變化和內容 (轉)[@more@]

在應用中監視剪貼簿的變化和內容:namespace prefix = o ns = "urn:schemas--com::office" />

to:stove@vip.sina.com">stove@vip.sina.com

 

剪貼簿是中級的堆空間,系統中任何一個應用程式對剪貼簿都有訪問權,可以透過剪貼簿訊息和使用剪貼簿來讀寫剪貼簿內容。因此使用剪貼簿不僅可以在同一個應用程式內互動資料,也可以在不通應用程式之間互動資料。尤其是在不通應用程式之間互動時,應用程式往往需要對剪貼簿內容的變化做到實時感知,即應用程式要能監視剪貼簿內容的變化。

 

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  = LO(wParam);

    wmEvent = HIWORD(wParam);

    // Parse the menu ions:

    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,"://")  != 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(" ");

 

    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();

  } 

}

 

 

 

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-956450/,如需轉載,請註明出處,否則將追究法律責任。

相關文章