Clipboard viewer doesn't get paste notificatio

2019-08-20 20:46发布

问题:

I need to block pasting from the clipboard in the window of the certain program. I set a clipboard viewer in my program like this:

HWND hwndNextViewer = 0;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message) {
       case WM_CREATE: {
          hwndNextViewer = SetClipboardViewer(hWnd);
          break;
       }

        default:
            return DefWindowProcW(hWnd, message, wParam, lParam);
  }
  case WM_DRAWCLIPBOARD: {
        if(GetForegroundWindow() == hWndTarget){
            OpenClipboard(hWndTarget);
            EmptyClipboard();
            CloseClipboard();
        }
        SendMessage(hwndNextViewer, message, wParam, lParam);
        break;
   }
    case WM_CHANGECBCHAIN:{

        if ((HWND)wParam == hwndNextViewer)

             hwndNextViewer = (HWND)lParam;

        else if (hwndNextViewer != NULL) {
             SendMessage(hwndNextViewer, message, wParam, lParam);
        }

        break;
    }

 }

}

What I'm doing is I'm checking if the current foreground window is the target program window, and if it is, I empty the clipboard. But this code doesn't detect pasting. for example when I paste inside the target window using the mouse.

How can I detect pasting?

回答1:

A clipboard viewer, and a clipboard format listener (which is what you should be using in Vista+ instead of a viewer), are intended ONLY for detecting changes to the data stored on the clipboard. Nothing else. The WM_DRAWCLIPBOARD and WM_CLIPBOARDUPDATE messages are sent to viewers/listeners when new data is put on the clipboard. There is no message sent when data is being pasted from the clipboard.

You simply CANNOT detect pastes with a clipboard viewer/listener. That task is not what those APIs are designed for.

You are going to have to use some global hooks to do what you want. A keyboard hook via SetWindowsHookEx() or RegisterRawInputDevices() can monitor for Ctrl+V keystrokes. A message hook via SetWindowsHookEx() can monitor for window messages related to pasting, like WM_PASTE, EM_PASTESPECIAL, WM_COMMAND, etc. But even so, this is no guarantee of detecting every possible paste operation. Applications are free to implement pastes however they want.

You will likely have to resort to injecting code into the target process to directly hook the various Win32 API functions that query the clipboard for data. Then you can fake the results when the target process tries to retrieve data during any kind of paste operation (like making the app think there is no data available to paste):

  • CountClipboardFormats()
  • EnumClipboardFormats()
  • IsClipboardFormatAvailable()
  • GetPriorityClipboardFormat()
  • GetUpdatedClipboardFormats()
  • GetClipboardData() and OleGetClipboard()