2013-08-19 164 views
0

我正在用全局鉤子寫入dll。其中一項任務是在有人執行復制操作時查看剪貼板並從中刪除所有數據。這裏是我對窗口的回調函數:監控剪貼板

string test("my data"); 

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 
    switch(msg) { 
     case WM_CREATE: 
      nextClipboardViewer = SetClipboardViewer(windowHandler); 
      MessageBeep(MB_ICONINFORMATION); 
      break; 
     case WM_CHANGECBCHAIN: 
      if((HWND) wParam == nextClipboardViewer) 
       nextClipboardViewer == (HWND) lParam; 
      else if(nextClipboardViewer != NULL) 
       SendMessage(nextClipboardViewer, msg, wParam, lParam); 
      break; 
     case WM_DRAWCLIPBOARD: 
      if(OpenClipboard(windowHandler)) { 
       EmptyClipboard(); 
       HGLOBAL hClipboardData; 
       hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1); 
       char * pchData; 
       pchData = (char*)GlobalLock(hClipboardData); 
       memcpy(pchData, test.c_str(), test.size() + 1); 
       GlobalUnlock(hClipboardData); 
       SetClipboardData(CF_TEXT, hClipboardData); 
       CloseClipboard(); 
      } 
      SendMessage(nextClipboardViewer, msg, wParam, lParam); 
      break; 
     case WM_DESTROY: 
      ChangeClipboardChain(windowHandler, nextClipboardViewer); 
      PostQuitMessage(0); 
      break; 
     default: 
      return DefWindowProc(hwnd, msg, wParam, lParam); 
      break; 
    } 
    return 0; 
} 

我只是想替換剪貼板中的信息,但是這段代碼不起作用。

更新:現在我正在使用不可見窗口和SetClipboardViewer監視更改。但剪貼板中的數據不會改變。

+1

即使這可以作出的工作,你會是陷阱「WM_COPY」消息用於在剪貼板上放置數據的實例 - 無法保證。創建一個窗口並使用'SetClipboardViewer'或'AddClipboardFormatListener'是一個更好的解決方案。 –

+3

在應用程序複製數據之前,清空剪貼板是毫無意義的。錯誤的鉤子,使用WH_CALLWNDPROCRET。你真的*想要使用SetClipboardViewer。如果你沒有HWND,那麼只需創建一個HWND,它不一定是可見的。確保你的卸載程序是完美無瑕的,它會得到很好的鍛鍊。 –

回答

1

我懷疑它是真正安全的改變剪貼板的內容,同時處理WM_DRAWCLIPBOARD消息 - 至少是我很驚訝你不會觸發無限循環(因爲您的通話EmptyClipboard()SetClipboardData()可以觸發另一消息)。可能系統有保護反對 - 我從來沒有試圖找出 - 但它仍然感覺錯誤:)

試試這個版本,其中a)將剪貼板更新移動到一個單獨的消息,窗口發佈到自己將它移到剪貼板更改通知代碼之外); b)使用全局標誌來忽略它自己做出的更改。

(注:我覺得你的代碼實際的錯誤是,當你處理WM_CREATEwindowHandler尚未分配你可能認爲設置的值CreateWindowEx回報,但是當WM_CREATE正在處理CreateWindowEx不是招」牛逼實際返回呢。這意味着剪貼板查看器是從來沒有真正建立正確。我已經改變了參考使用hwnd來解決這個問題。)

string test("my data"); 

#define MSG_UPDATECLIPBOARD  (WM_APP + 1) 
static bool g_fIgnoreClipboardChange = false; 

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 
    switch(msg) { 
     case WM_CREATE: 
      nextClipboardViewer = SetClipboardViewer(hwnd); 
      MessageBeep(MB_ICONINFORMATION); 
      break; 
     case WM_CHANGECBCHAIN: 
      if((HWND) wParam == nextClipboardViewer) 
       nextClipboardViewer == (HWND) lParam; 
      else if(nextClipboardViewer != NULL) 
       SendMessage(nextClipboardViewer, msg, wParam, lParam); 
      break; 
     case WM_DRAWCLIPBOARD: 
      if (!g_fIgnoreClipboardChange) 
       PostMessage(hwnd, MSG_UPDATECLIPBOARD, 0, 0); 
      if(nextClipboardViewer != NULL) 
       SendMessage(nextClipboardViewer, msg, wParam, lParam); 
      break; 
     case MSG_UPDATECLIPBOARD: 
      g_fIgnoreClipboardChange = true; 
      if(OpenClipboard(hwnd)) { 
       HGLOBAL hClipboardData; 
       hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1); 
       char * pchData; 
       pchData = (char*)GlobalLock(hClipboardData); 
       memcpy(pchData, test.c_str(), test.size() + 1); 
       GlobalUnlock(hClipboardData); 
       SetClipboardData(CF_TEXT, hClipboardData); 
       CloseClipboard(); 
      } 
      g_fIgnoreClipboardChange = false; 
      break;  
     case WM_DESTROY: 
      ChangeClipboardChain(hwnd, nextClipboardViewer); 
      PostQuitMessage(0); 
      break; 
     default: 
      return DefWindowProc(hwnd, msg, wParam, lParam); 
      break; 
    } 
    return 0; 
} 
+0

是的,你是對的。我的頭痛是SetClipboardViewer()函數中錯誤的窗口句柄。現在它完美地工作。 –

+0

我只是在學習C++,並且對你有一個非常簡單的問題:我正嘗試使用此代碼在我的控制檯win32應用程序中創建一個新線程。我收到「nextClipboardViewer」未定義的錯誤。我包含哪些庫來解決這個問題?我GOOGLE了它,但沒有發現這個特定的功能和庫進口;我假設這是我的問題。 – user1017063

+1

該代碼來自OP,只是一個片段,並不是一個完整的程序。如果你添加'HWND nextClipboardViewer = 0; ** **外部函數(使其成爲一個全局函數),它應該讓你通過那個錯誤,但我不知道你會遇到什麼其他錯誤只使用片段別人的代碼。 –