2014-10-23 7 views
3

전 세계 다중 값 클립 보드를 만들려고합니다. 스택을 사용하여 값을 저장했습니다. WinProc()을 사용하여 스택의 값을 밀어 넣는 전역 복사 작업을 캡처합니다. 마찬가지로 Ctrl-V (붙여 넣기) 작업을 캡처하기 위해 Windows 키보드 후크를 사용하고 있습니다. 두 함수의 코드는 다음과 같습니다. 코드를 복사하여 this에서 수정했습니다.클립 보드 업데이트 이벤트가 여러 번 발생했습니다.

 private int KbHookProc(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     if (nCode >= 0) 
     { 
      var hookStruct = (KbLLHookStruct)Marshal.PtrToStructure(lParam, typeof(KbLLHookStruct)); 

      // Quick and dirty check. You may need to check if this is correct. See GetKeyState for more info. 
      bool ctrlDown = GetKeyState(VK_LCONTROL) != 0 || GetKeyState(VK_RCONTROL) != 0; 

      if (ctrlDown && hookStruct.vkCode == 0x56) // Ctrl+V 
      { 
       if (clipBoardStack.Count > 0) 
       { 
        lock (this) 
        { 
         localChange = true; 
         RemoveClipboardFormatListener(this.Handle);  // Remove our window from the clipboard's format listener list. 
         System.Threading.Thread.Sleep(200); 
         Clipboard.SetText(clipBoardStack.Pop()); 
         AddClipboardFormatListener(this.Handle); 
         System.Threading.Thread.Sleep(200); 
        } 

       } 

      } 
     } 

     // Pass to other keyboard handlers. Makes the Ctrl+V pass through. 
     return CallNextHookEx(_hookHandle, nCode, wParam, lParam); 
    } 

내 WinProc 재정의는 다음과 같습니다. 나는 그것을뿐만 아니라에서 복사했지만 링크를 기억하지 않습니다.

 protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 

     if (m.Msg == WM_CLIPBOARDUPDATE) 
     { 
      if (!localChange)//Only store the data in stack when it comes from outside. Just to prevent the side effect of Paste Operation 
      { 
       IDataObject iData = Clipboard.GetDataObject();  // Clipboard's data. 

       if (iData.GetDataPresent(DataFormats.Text)) 
       { 
        lock (this) 
        { 
         string text = (string)iData.GetData(DataFormats.Text); 
         clipBoardStack.Push(text);        
        } 
       } 
      } 
      else 
      { 
       localChange = false; 
      } 
     } 

복사 작업이 원활하게 작동합니다. 스택을 채 웁니다. 그러나 붙여 넣기 작업을 사용하면 WM_CLIPBOARDUPDATE 이벤트가 트리거됩니다. 그러면 가장 최근 값으로 스택이 다시 채워집니다.

붙여 넣기 절에서 클립 보드 값을 변경하면 WM_CLIPBOARDUPDATE 이벤트가 트리거됩니다. 목록 수신기 등록을 시도했지만 플래그 변수 'localChange'를 사용하려고 시도했지만 블록을 사용하려고했습니다 (),하지만 아무것도 작동하지 않습니다.

해결 방법은 무엇입니까?

답변

3

클립 보드 업데이트를 수신 할 수는 있지만 클립 보드 업데이트가 생성되면 무시해야합니다. 즉 자신의 에코에 반응하지 마십시오.

클립 보드 소유권을 사용할 수도 있고 개인 클립 보드 형식을 삽입하여 자신의 것으로 "표시"할 수도 있습니다. 다음은 클립 보드 뷰어에게 데이터를 캡처하지 않도록 알리는 것을 목적으로하는 방법을 설명하는 기사입니다 (저에게 오래 전부터). http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/ignoring-clipboard-updates-with-the-cf_clipboard_viewer_ignore-clipboard-format

그 기사의 기본적인 아이디어는, 당신은 실제 데이터를 넣어 그 CF_CLIPBOARD_VIEWER_IGNORE라는 개인 클립 보드 형식을 생성하고 (같은 개방/업데이트/가까운 순서대로) 동시에 클립 보드에 추가하는 것입니다 . 웹 브라우저, 워드 프로세서, 메모장 등과 같은 프로그램은 신경 쓰지 않습니다. 그러나 클립 보드 뷰어 (예 : 내 클립 메이트 또는 내 ClipMate)는 클립 보드에 CF_CLIPBOARD_VIEWER_IGNORE 형식을 표시 한 다음 데이터를 무시합니다. 이것은 또한 암호 관리자와 같은 응용 프로그램이 민감한 데이터가있는 클립 보드 관리자를 어지럽히는 것을 방지하는 방법입니다.

1

시스템에서 HotKey (Ctrl-V)를 등록하면 시스템에서 응용 프로그램의 HotKey 처리기로 제어를 보낼 수 있습니다. 여기서 클립 보드를 업데이트 할 수 있습니다.

HotKey를 등록하면 시스템에서 응용 프로그램에만 알릴 수 있으므로 ClipBoard로 수행하는 작업을 제어 할 수 있습니다. 나중에 Ctrl-V 조합을 대상 (의도 된) 응용 프로그램에 보내야합니다. 이것은 대상 응용 프로그램에 대해 사용자가 붙여 넣기 명령을 실행 한 것처럼 시뮬레이트합니다.

이 단점은 나중에 키 조합을 보내려는 애플리케이션이 무엇인지 파악해야한다는 것입니다.

관련 문제