我可以更改观察列表中字符串的显示格式吗? [英] Can I change the display format for strings in the watch list?
问题描述
现在,我使用watch窗口显示包含sql语句的字符串。
Every now and then I use the watch window to display strings which contain sql statements.
现在我从上下文菜单中选择复制值,并获得
Now I select Copy Value from the context menu and get
'SELECT NAME FROM SAMPLE_TABLE WHERE FIRST_NAME = ''George'''#$D#$A
当然,如果我想在显示结果的sql工具中执行该语句,则必须重新格式化此语句。这是一个有点恼人的。
Of course, this statement has to be reformatted if I want to execute it in a sql tool displaying the results. This is a little bit annoying.
有没有一个技巧/解决方法?
Is there a trick / workaround for that?
推荐答案
我以为通过在IDE中添加一些东西来尝试和设计出一个方法是有趣的,主要是因为当你发布q时,我没有一个线索。事实证明,您可以轻松地使用包含下列单位的自定义OTA包。
I thought it would be amusing to try and work out a way to do this by adding something inside the IDE, mainly because when you posted your q, I didn't have a clue how to. It turns out that you can do it quite easily using a custom OTA package containing a unit like the one below.
Btw,我特别强调Rob Kennedy指向在另一个SO问题中,IDE具有像任何其他的Screen对象。这提供了一个简单的方法来解决这个问题,绕过了我通常不得不使用的OTA接口的迷宫来编写一个IDE加载项。
Btw, I'm particularly obliged to Rob Kennedy for pointing out in another SO question that the IDE has a Screen object just like any other. That provides an easy way into the problem, bypassing the maze of OTA interfaces I've usually had to work with to code an IDE add-in.
它工作在
-
查找
Watch Window
,
在其上下文菜单中查找复制观察值
项目在
Finding the Copy Watch value
item in its context menu & adding a new menu item after it
之后添加一个新的菜单项使用新项目的OnClick处理程序从Watch Window的重点项目中获取该值,将其重新格式化为需要,然后粘贴到剪贴板
。
Using the OnClick handler of the new item to pick up the value from the Watch Window's focused item, re-formatting it as required, then pasting it to the Clipboard
.
所以就像使用OTA服务一样,它并没有任何幻想,但是在IDE中我认为KISS原则是适用的。
So far as using OTA services is concerned, it doesn't do anything fancy, but with the IDE I think the KISS principle applies.
代码:
unit IdeMenuProcessing;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ToolsAPI, Menus, ClipBrd, ComCtrls;
type
TOtaMenuForm = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
OurMenuItem : TMenuItem;
WatchWindow : TForm;
WWListView : TListView;
procedure GetWatchValue(Sender : TObject);
end;
var
OtaMenuForm: TOtaMenuForm;
procedure Register;
implementation
{$R *.dfm}
procedure ShowMenus;
begin
OtaMenuForm := TOtaMenuForm.Create(Nil);
OtaMenuForm.Show;
end;
procedure Register;
begin
ShowMenus;
end;
procedure TOtaMenuForm.FormCreate(Sender: TObject);
var
i : Integer;
S : String;
PM : TPopUpMenu;
Item : TMenuItem;
begin
// First create a menu item to insert in the Watch Window's context menu
OurMenuItem := TMenuItem.Create(Self);
OurMenuItem.OnClick := GetWatchValue;
OurMenuItem.Caption := 'Get processed watch value';
WatchWindow := Nil;
WWListView := Nil;
// Next, iterate the IDE's forms to find the Watch Window
for i := 0 to Screen.FormCount - 1 do begin
S := Screen.Forms[i].Name;
if CompareText(S, 'WatchWindow') = 0 then begin // < Localize if necessary
WatchWindow := Screen.Forms[i];
Break;
end;
end;
Assert(WatchWindow <> Nil);
if WatchWindow <> Nil then begin
// Next, scan the Watch Window's context menu to find the existing "Copy watch value" entry
// and insert our menu iem after it
PM := WatchWindow.PopUpMenu;
for i:= 0 to PM.Items.Count - 1 do begin
Item := PM.Items[i];
if CompareText('Copy Watch &Value', Item.Caption) = 0 then begin // < Localize if necessary
PM.Items.Insert(i + 1, OurMenuItem);
Break;
end;
end;
// Now, find the TListView in the Watch Window
for i := 0 to WatchWindow.ComponentCount - 1 do begin
if WatchWindow.Components[i] is TListView then begin
WWListView := WatchWindow.Components[i] as TListView;
Break;
end;
end;
Assert(WWListView <> Nil);
end;
end;
procedure TOtaMenuForm.GetWatchValue(Sender: TObject);
var
WatchValue : String;
begin
// This is called when the Watch Window menu item we added is clicked
if WWListView.ItemFocused = Nil then begin
Memo1.Lines.Add('no Watch selected');
exit;
end;
WatchValue := WWListView.ItemFocused.SubItems[0];
WatchValue := StringReplace(WatchValue, #$D#$A, ' ', [rfreplaceAll]);
if WatchValue[1] = '''' then
Delete(WatchValue, 1, 1);
if WatchValue[Length(WatchValue)] = '''' then
WatchValue := Copy(WatchValue, 1, Length(WatchValue) - 1);
// [etc]
ClipBoard.AsText := WatchValue;
Memo1.Lines.Add('>' + WatchValue + '<');
end;
initialization
finalization
if Assigned(OTAMenuForm) then begin
OTAMenuForm.Close;
FreeAndNil(OTAMenuForm);
end;
end.
Btw,我在D7写了这个,因为我把它用作SO答案的最低公分母因为很明显,这里的大部分人还在使用它。后来的版本有额外的字符串功能,例如注释中提到的AniDequotedStr,可能有助于重新格式化手表值。
Btw, I wrote this in D7 because I use that as a sort of lowest common denominator for SO answers because its quite obvious that a large number of people here still use it. Later versions have additional string functions, such as the AniDequotedStr mentioned in a comment, which might be helpful in reformatting the watch value.
更新:根据OP,上述不适用于XE3,因为观察窗口使用TVirtualStringTree而不是TListView实现。我使用ListView的原因是我发现从剪贴板拾取Watch值(在模拟了上下文菜单的复制观察值
之后)的处理它wasn'很可靠这在XE4中似乎有所改进(我没有XE3测试),所以这里有一个似乎在XE4中工作的版本:
Update: According to the OP, the above doesn't work with XE3 because the watch window is implemented using a TVirtualStringTree rather than a TListView. The reason I used the ListView was that I found that picking up the Watch value from the Clipboard (after simulating a click on the context menu's Copy Watch Value
) to process it wasn't very reliable. That seems to have improved in XE4 (I don't have XE3 to test), so here's a version that seems to work in XE4:
更新#2: OP提到以前的代码版本失败了 WatchWindow<>当Delphi第一次启动时,Nil
断言。我想象的原因是在IDE中创建了 Watch Window
之前调用代码。我重新安排了代码,添加了一个OTANotifier,用于获取项目桌面已经加载的通知,广告使用它来调用新的 SetUp
例程。 / p>
Update #2: The OP mentioned that the previous version of the code below failed the WatchWindow <> Nil
assertion when Delphi is first started. I imagine the reason is that the code is called before the Watch Window
has been created in the IDE. I've re-arranged the code an added an OTANotifier that's used to get the notification that a project desktop has been loaded, ad uses that to called the new SetUp
routine.
unit IdeMenuProcessing;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ToolsAPI, Menus, ClipBrd, ComCtrls;
type
TIdeNotifier = class(TNotifierObject, IOTANotifier, IOTAIDENotifier)
protected
procedure AfterCompile(Succeeded: Boolean);
procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
procedure FileNotification(NotifyCode: TOTAFileNotification;
const FileName: string; var Cancel: Boolean);
end;
TOtaMenuForm = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
IsSetUp : Boolean;
ExistingMenuItem,
OurMenuItem : TMenuItem;
WatchWindow : TForm;
Services: IOTAServices;
Notifier : TIdeNotifier;
NotifierIndex: Integer;
procedure GetWatchValue(Sender : TObject);
procedure SetUp;
end;
var
OtaMenuForm: TOtaMenuForm;
procedure Register;
implementation
{$R *.dfm}
procedure ShowMenus;
begin
OtaMenuForm := TOtaMenuForm.Create(Nil);
OtaMenuForm.Services := BorlandIDEServices as IOTAServices;
OtaMenuForm.NotifierIndex := OtaMenuForm.Services.AddNotifier(TIdeNotifier.Create);
OtaMenuForm.Show;
end;
procedure Register;
begin
ShowMenus;
end;
procedure TOtaMenuForm.SetUp;
var
i : Integer;
S : String;
PM : TPopUpMenu;
Item : TMenuItem;
begin
if IsSetUp then exit;
// First create a menu item to insert in the Watch Window's context menu
OurMenuItem := TMenuItem.Create(Self);
OurMenuItem.OnClick := GetWatchValue;
OurMenuItem.Caption := 'Get processed watch value';
WatchWindow := Nil;
// Next, iterate the IDE's forms to find the Watch Window
for i := 0 to Screen.FormCount - 1 do begin
S := Screen.Forms[i].Name;
if CompareText(S, 'WatchWindow') = 0 then begin
WatchWindow := Screen.Forms[i];
Break;
end;
end;
Assert(WatchWindow <> Nil);
if WatchWindow <> Nil then begin
// Next, scan the Watch Window's context menu to find the existing "Copy watch value" entry
// and insert our menu item after it
PM := WatchWindow.PopUpMenu;
for i:= 0 to PM.Items.Count - 1 do begin
Item := PM.Items[i];
if CompareText('Copy Watch &Value', Item.Caption) = 0 then begin
ExistingMenuItem := Item;
PM.Items.Insert(i + 1, OurMenuItem);
if ExistingMenuItem.Action <> Nil then
Memo1.Lines.Add('Has action')
else
Memo1.Lines.Add('No action');
Break;
end;
end;
end;
Caption := 'Setup complete';
IsSetUp := True;
end;
procedure TOtaMenuForm.FormCreate(Sender: TObject);
begin
IsSetUp := False;
end;
procedure TOtaMenuForm.GetWatchValue(Sender: TObject);
var
S,
WatchValue : String;
TL : TStringList;
i : Integer;
begin
// This is called when the Watch Window menu item we added is clicked
ExistingMenuItem.Click;
WatchValue := ClipBoard.AsText;
WatchValue := StringReplace(WatchValue, '#$D#$A', #$D#$A, [rfreplaceAll]);
if WatchValue <> '' then begin
TL := TStringList.Create;
try
TL.Text := WatchValue;
WatchValue := '';
for i := 0 to TL.Count - 1 do begin
S := TL[i];
if S[1] = '''' then
Delete(S, 1, 1);
if S[Length(S)] = '''' then
S := Copy(S, 1, Length(S) - 1);
if WatchValue <> '' then
WatchValue := WatchValue + ' ';
WatchValue := WatchValue + S;
end;
finally
TL.Free;
end;
// [etc]
end;
ClipBoard.AsText := WatchValue;
Memo1.Lines.Add('>' + WatchValue + '<');
end;
{ TIdeNotifier }
procedure TIdeNotifier.AfterCompile(Succeeded: Boolean);
begin
end;
procedure TIdeNotifier.BeforeCompile(const Project: IOTAProject;
var Cancel: Boolean);
begin
end;
procedure TIdeNotifier.FileNotification(NotifyCode: TOTAFileNotification;
const FileName: string; var Cancel: Boolean);
begin
if NotifyCode = ofnProjectDesktopLoad then
OTAMenuForm.SetUp
end;
initialization
finalization
if Assigned(OTAMenuForm) then begin
OTAMenuForm.Services.RemoveNotifier(OTAMenuForm.NotifierIndex);
OTAMenuForm.Close;
FreeAndNil(OTAMenuForm);
end;
end.
这篇关于我可以更改观察列表中字符串的显示格式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!