Recent

Author Topic: Not reacting to clipboard change - windows  (Read 13550 times)

balazsszekely

  • Guest
Re: Not reacting to clipboard change - windows
« Reply #15 on: October 19, 2016, 05:53:07 pm »
Quote
@dcminus
Any suggestion for a fix?
Did you try the fix from my last post? It filters the same text from the same windows if it appears twice.

dcminus

  • New Member
  • *
  • Posts: 24
Re: Not reacting to clipboard change - windows
« Reply #16 on: October 21, 2016, 03:17:07 pm »
GetMem,

I did, but my problem is that this would filter out genuine updates too. Anyhow thanks for your time spent on it.  I would like to catch all real update events (even those cases when the same text gets copied to the clipboard), but I am starting to think it is not possible that way.

 However, I have found this post on superuser: http://stackoverflow.com/questions/30892931/how-to-deal-with-the-clipboard-message-wm-drawclipboard-which-is-sent-multiple-t and i am afraid that what i would like to achieve is simply not possible:


Quote
Outlook fires the clipboard multiple times and even fires the clipboard when it gets focus. Solution - I only react on one of the events within 200ms. I also only react on a clipboard event when the control key is pressed. (this is a special case for me as I only want to do this for keyboard copy and not mouse copies)

It is very annoying though that this happens with an app that is made by MS on a OS made by MS...

So my app shows every time the user copies something to the clipboard (99% from subject line / mail body of an outlook email) it check if this is a ticket reference and if it is then pops up the details of the ticket so the user can decide what is the best action (with this mail / ticket).

I think the dev in the post is trying to write a similar app to mine. I was thinking of a similar solution so log all "CTRL+C" keypress and if there was no such event in the past 1 or 2 seconds there will be no pop up. 

The best would be of course find some difference between the two updates or to fix outlook somehow. However the last is the least likely....

Thank you all again, I am still thinking on other ways to sort this but not much comes to mind...


dcminus

  • New Member
  • *
  • Posts: 24
Re: Not reacting to clipboard change - windows
« Reply #17 on: October 22, 2016, 05:22:09 pm »
I have sorted the problem by amending the clipboard check with these units to the Unit1 uses part:
Code: Pascal  [Select][+][-]
  1. sysutils, Clipbrd, LCLIntf, LCLType
 

also added check for CTRL keys state in the ClipboardChange procedure, as a fix for "my Outlook bug" (note: obviously, this way you wont receive notification when mouse used to copy something to the clipboard)

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ClipboardChanged(Sender: TObject);
  2. begin
  3.   if GetKeyState(VK_CONTROL) < 0 then
  4.     Memo1.Lines.Append(timetostr(Now)+' ['+Clipboard.AsText+']');
  5. end;
  6.  

On Vista and later, you should be using AddClipboardFormatListener() instead of SetClipboardViewer(). 
This work example:
Code: Pascal  [Select][+][-]
  1. unit ClipboardListener;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, Messages, Classes;
  9.  
  10. type
  11.   { TClipboardListener }
  12.  
  13.   TClipboardListener = class(TObject)
  14.   strict private
  15.     FOnClipboardChange: TNotifyEvent;
  16.     FWnd: HWND;
  17.     class function GetSupported: Boolean; static;
  18.     procedure WindowProc(var Msg: TMessage);
  19.   public
  20.     constructor Create;
  21.     destructor Destroy; override;
  22.     property OnClipboardChange: TNotifyEvent read FOnClipboardChange write FOnClipboardChange;
  23.     class property Supported: Boolean read GetSupported;
  24.   end;
  25.  
  26. implementation
  27.  
  28. uses SysUtils, LCLIntf;
  29.  
  30. var
  31.   AddClipboardFormatListener: function(Wnd: HWND): BOOL; stdcall;
  32.   RemoveClipboardFormatListener: function(Wnd: HWND): BOOL; stdcall;
  33.  
  34. procedure InitClipboardFormatListener;
  35. var
  36.   HUser32: HMODULE;
  37. begin
  38.   HUser32 := GetModuleHandle(user32);
  39.   Pointer(AddClipboardFormatListener) :=
  40.     GetProcAddress(HUser32, 'AddClipboardFormatListener');
  41.   Pointer(RemoveClipboardFormatListener) :=
  42.     GetProcAddress(HUser32, 'RemoveClipboardFormatListener');
  43. end;
  44.  
  45. { TClipboardListener }
  46.  
  47. constructor TClipboardListener.Create;
  48. begin
  49.   inherited;
  50.   if GetSupported then
  51.   begin
  52.     FWnd := LCLIntf.AllocateHWnd(@WindowProc);
  53.     if not AddClipboardFormatListener(FWnd) then
  54.       RaiseLastOSError;
  55.   end;
  56. end;
  57.  
  58. destructor TClipboardListener.Destroy;
  59. begin
  60.   if FWnd <> 0 then
  61.   begin
  62.     RemoveClipboardFormatListener(FWnd);
  63.     LCLIntf.DeallocateHWnd(FWnd);
  64.   end;
  65.   inherited;
  66. end;
  67.  
  68. class function TClipboardListener.GetSupported: Boolean;
  69. begin
  70.   Result := Assigned(AddClipboardFormatListener) and
  71.     Assigned(RemoveClipboardFormatListener);
  72. end;
  73.  
  74. procedure TClipboardListener.WindowProc(var Msg: TMessage);
  75. begin
  76.   if (Msg.msg = WM_CLIPBOARDUPDATE) and Assigned(FOnClipboardChange) then
  77.   begin
  78.     Msg.Result := 0;
  79.     FOnClipboardChange(Self);
  80.   end;
  81. end;
  82.  
  83. initialization
  84.   InitClipboardFormatListener;
  85. end.
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   ClipboardListener, Classes, Forms, StdCtrls;
  9.  
  10. type
  11.   { TForm1 }
  12.  
  13.   TForm1 = class(TForm)
  14.     Memo1: TMemo;
  15.     procedure FormCreate(Sender: TObject);
  16.     procedure FormDestroy(Sender: TObject);
  17.   private
  18.     FListener: TClipboardListener;
  19.     procedure ClipboardChanged(Sender: TObject);
  20.   end;
  21.  
  22. var
  23.   Form1: TForm1;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.ClipboardChanged(Sender: TObject);
  32. begin
  33.  [color=yellow] if GetKeyState(VK_CONTROL) < 0 then
  34.     Memo1.Lines.Append(timetostr(Now)+' ['+Clipboard.AsText+']')   [/color]
  35. // Memo1.Lines.Append('Clipboard changed');
  36. end;
  37.  
  38. procedure TForm1.FormCreate(Sender: TObject);
  39. begin
  40.   FListener := TClipboardListener.Create;
  41.   FListener.OnClipboardChange := @ClipboardChanged;
  42. end;
  43.  
  44. procedure TForm1.FormDestroy(Sender: TObject);
  45. begin
  46.   FListener.Free;
  47. end;
  48.  
  49. end.

Thank you all for your help.   ;)
« Last Edit: October 22, 2016, 05:26:31 pm by dcminus »

 

TinyPortal © 2005-2018