我现在使用watch窗口来显示包含sql语句的字符串.
'SELECT NAME FROM SAMPLE_TABLE WHERE FIRST_NAME = ''George'''#$D#$A
当然,如果我想在显示结果的sql工具中执行该语句,则必须重新格式化此语句.这有点恼人.
有没有一个技巧/解决方法?
解决方法
我认为通过在IDE中添加一些东西来尝试和设计出一个方法是有趣的,主要是因为当你发布你的q时,我没有一个线索.事实证明,您可以轻松地使用包含以下单元的自定义OTA包来做到这一点.
Btw,我特别强调Rob Kennedy指出另一个SO问题,IDE有一个Screen对象就像其他的一样.这提供了一个简单的方法来解决这个问题,绕过了我通常不得不使用的OTA接口的迷宫来编写一个IDE加载项.
它工作
>查找手表窗口,
>在其上下文菜单&在它之后添加一个新的菜单项
>使用新项目的OnClick处理程序从Watch Window的关注项目中获取该值,根据需要重新格式化它,然后将其粘贴到剪贴板.
就使用OTA服务而言,它并没有任何幻想,但是对于IDE,我认为KISS原则是适用的.
码:
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,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,可能有助于重新格式化手表值.
更新:根据OP,上述不适用于XE3,因为观察窗口是使用TVirtualStringTree而不是TListView实现的.我使用ListView的原因是我发现从剪贴板拾取Watch值(模拟点击上下文菜单的复制观察值)来处理它不是很可靠.这在XE4中似乎有所改进(我没有XE3测试),所以这里有一个在XE4中可以使用的版本:
更新#2:OP提到以前的代码版本失败WatchWindow<>当Delphi第一次启动时,没有断言.我想象的原因是代码在IDE中创建Watch Window之前被调用.我重新安排了代码,添加了一个OTANotifier,用于获取项目桌面已经加载的通知,广告使用它来调用新的SetUp例程.
unit IdeMenuProcessing; interface uses Windows,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,'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',[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); if S[Length(S)] = '''' then S := Copy(S,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.