1unit FmEditor;
2
3interface
4
5uses
6 Forms, StdCtrls, ComCtrls, Classes, Controls, Windows, Messages;
7
8const
9
10
11 WM_CLIPBOARDUPDATE = $031D;
12
13type
14 TEditorForm = class(TForm)
15 btnCut: TButton;
16 btnCopy: TButton;
17 btnPaste: TButton;
18 RichEdit1: TRichEdit;
19 procedure FormCreate(Sender: TObject);
20 procedure FormDestroy(Sender: TObject);
21 procedure RichEdit1SelectionChange(Sender: TObject);
22 procedure btnCutClick(Sender: TObject);
23 procedure btnCopyClick(Sender: TObject);
24 procedure btnPasteClick(Sender: TObject);
25 private
26
27
28 fUseNewAPI: Boolean;
29
30
31 fNextCBViewWnd: HWND;
32
33
34
35 fAddClipboardFormatListener: function(hwnd: HWND): BOOL; stdcall;
36 fRemoveClipboardFormatListener: function(hwnd: HWND): BOOL; stdcall;
37
38
39
40 fSetClipboardViewer: function (hWndNewViewer: HWND): HWND; stdcall;
41 fChangeClipboardChain: function(hWndRemove, hWndNewNext: HWND): BOOL;
42 stdcall;
43
44 procedure WMClipboardUpdate(var Msg: TMessage); message WM_CLIPBOARDUPDATE;
45 procedure WMChangeCBChain(var Msg: TMessage); message WM_CHANGECBCHAIN;
46 procedure WMDrawClipboard(var Msg: TMessage); message WM_DRAWCLIPBOARD;
47 end;
48
49var
50 EditorForm: TEditorForm;
51
52implementation
53
54uses
55 SysUtils, Clipbrd;
56
57{$R *.dfm}
58
59procedure TEditorForm.btnCopyClick(Sender: TObject);
60begin
61 RichEdit1.CopyToClipboard;
62end;
63
64procedure TEditorForm.btnCutClick(Sender: TObject);
65begin
66 RichEdit1.CutToClipboard;
67end;
68
69procedure TEditorForm.btnPasteClick(Sender: TObject);
70begin
71 RichEdit1.PasteFromClipboard;
72end;
73
74procedure TEditorForm.FormCreate(Sender: TObject);
75const
76 cUserKernelLib = 'user32.dll';
77begin
78
79 btnPaste.Enabled := Clipboard.HasFormat(CF_TEXT);
80 btnCut.Enabled := RichEdit1.SelLength > 0;
81 btnCopy.Enabled := btnCut.Enabled;
82
83
84
85
86 fAddClipboardFormatListener := GetProcAddress(
87 GetModuleHandle(cUserKernelLib), 'AddClipboardFormatListener'
88 );
89 fRemoveClipboardFormatListener := GetProcAddress(
90 GetModuleHandle(cUserKernelLib), 'RemoveClipboardFormatListener'
91 );
92 fUseNewAPI := Assigned(fAddClipboardFormatListener)
93 and Assigned(fRemoveClipboardFormatListener);
94 if not fUseNewAPI then
95 begin
96 fSetClipboardViewer := GetProcAddress(
97 GetModuleHandle(cUserKernelLib), 'SetClipboardViewer'
98 );
99 fChangeClipboardChain := GetProcAddress(
100 GetModuleHandle(cUserKernelLib), 'ChangeClipboardChain'
101 );
102 Assert(Assigned(fSetClipboardViewer) and Assigned(fChangeClipboardChain));
103 end;
104 if fUseNewAPI then
105 begin
106
107 if not fAddClipboardFormatListener(Self.Handle) then
108 RaiseLastOSError;
109 end
110 else
111 begin
112
113
114 fNextCBViewWnd := fSetClipboardViewer(Self.Handle);
115 end;
116end;
117
118procedure TEditorForm.FormDestroy(Sender: TObject);
119begin
120
121 if fUseNewAPI then
122 fRemoveClipboardFormatListener(Self.Handle)
123 else
124 fChangeClipboardChain(Self.Handle, fNextCBViewWnd);
125end;
126
127procedure TEditorForm.RichEdit1SelectionChange(Sender: TObject);
128begin
129 btnCut.Enabled := RichEdit1.SelLength > 0;
130 btnCopy.Enabled := btnCut.Enabled;
131end;
132
133procedure TEditorForm.WMChangeCBChain(var Msg: TMessage);
134begin
135 Assert(not fUseNewAPI);
136
137 if HWND(Msg.WParam) = fNextCBViewWnd then
138
139 fNextCBViewWnd := HWND(Msg.LParam)
140 else if fNextCBViewWnd <> 0 then
141
142 SendMessage(fNextCBViewWnd, Msg.Msg, Msg.WParam, Msg.LParam);
143end;
144
145procedure TEditorForm.WMClipboardUpdate(var Msg: TMessage);
146begin
147
148 btnPaste.Enabled := Clipboard.HasFormat(CF_TEXT);
149end;
150
151procedure TEditorForm.WMDrawClipboard(var Msg: TMessage);
152begin
153 Assert(not fUseNewAPI);
154
155
156 btnPaste.Enabled := Clipboard.HasFormat(CF_TEXT);
157
158 if fNextCBViewWnd <> 0 then
159 SendMessage(fNextCBViewWnd, Msg.Msg, Msg.WParam, Msg.LParam);
160end;
161
162end.