我可以更改观察列表中字符串的显示格式吗? [英] Can I change the display format for strings in the watch list?

查看:114
本文介绍了我可以更改观察列表中字符串的显示格式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆