10

各行を引用することなく、Delphi で複数行の文字列値を割り当てる方法はありますか?

編集(特定の問題):Delphiの外部でテストしたいSQLクエリがいくつかあります。クエリをコピーするとき、毎回引用符を追加して置き換えるのは少しオーバーヘッドです。

4

10 に答える 10

8

IDE の [ツール] メニューに追加できる、役立つアプリケーションのコードを次に示します。しばらく前に、TeamB メンバーの Peter によって CodeGear ニュースグループの 1 つに投稿されました。

プログラム ClipToStringConst;

// コンソール アプリの場合、下の行からドットを削除します。
// Rob Kennedy のコメントによる。それは問題なく動作します
// コンソール アプリ。
{.$APPTYPE コンソール}
用途
  ウィンドウズ、
  クラス、
  システムユーティリティ、
  APIClipboard;

定数
  cIndent = ' '; // 2 つのスペース
  cSingleQuote = '''';
  EndChar : Char の配列 [ブール値] = ('+',';');

手順 プロセス;
変数
  SL: TStringlist;
  i、最大: 整数。
始める
  もし ClipboardHasFormat( CF_TEXT ) なら
  始める
    SL := TStringlist.Create;
    試す
      SL.Text:= ClipboardAsString;
      最大:= SL.count-1;
      for i:= 0 から max do
        SL[i] := cIndent +
                 AnsiQuotedStr( TrimRight(SL[i])+#32, cSingleQuote ) +
                 EndChar[i = 最大];
      StringToClipboard( SL.Text );
    最後に
      SL.無料;
    終わり; { ついに }
  終わり;
終わり;

始める
  試す
    プロセス;
  を除外する
    E: 例外 do
      ShowException(E、ExceptAddr);
  終わり;
終わり。

テスト後に SQL 管理ツールでテキストを選択し、クリップボードにコピーするだけです。Delphi コード エディタに切り替え、定数テキストを表示する場所に挿入ポイントを配置し、[ツール] メニューから [クリップボードから定数] または任意の名前を選択して、Ctrl+V を押してエディタに貼り付けます。

かなり便利な小さなツールです。また、逆の方法 (ConstantToClipboard) で動作するように変更して、ソースの書式設定を削除し、生の SQL に戻すこともできますが、私はまだそうするつもりはありません。

編集: 単位を逃した (APIClipboard)。明らかに、これは別のユニットである必要があります。繰り返しになりますが、Peter Below に感謝します。

{== Unit APIClipboard =================================================}
{: Clipboard access routines using only API functions
@author Dr. Peter Below
@desc Version 1.0 created 5 Juli 2000<BR>
        Current revision 1.0<BR>
        Last modified 5 Juli 2000<P>

This unit provides simply clipboard access routines that do not rely on
the VCL Clipbrd unit. That unit drags in Dialogs and Forms and a major
part of the VCL as a consequence, not appropriate for simple console
or non-form programs. This unit uses only API routines, the only VCL
units used are Classes (for exceptions and streams) and SysUtils.
}
{=====================================================================}

unit APIClipboard;

interface

uses
  Windows, Classes;

  procedure StringToClipboard( const S: String );
  function ClipboardAsString: String;
  procedure CopyDataToClipboard( fmt: DWORD; const data; datasize: Integer;
                                 emptyClipboardFirst: Boolean = true );
  procedure CopyDataFromClipboard( fmt: DWORD; S: TStream );
  function ClipboardHasFormat( fmt: DWORD ): Boolean;

implementation

uses
  Sysutils;

type
  {: This is an internal exception class used by the <see unit=APIClipboard> }
  EClipboardError = class( Exception )
  public
    constructor Create( const msg: String );
  end;

resourcestring
  eSystemOutOfMemory =
    'could not allocate memory for clipboard data.';
  eLockfailed =
    'could not lock global memory handle.';
  eSetDataFailed =
    'could not copy data block to clipboard.';
  eCannotOpenClipboard =
    'could not open the clipboard.';
  eErrorTemplate =
    'APIClipboard: %s'#13#10+
    'System error code: %d'#13#10+
    'System error message: %s';

{-- EClipboardError.Create --------------------------------------------}
{: Creates a new EclipboardError object
@Param msg is the string to embed into the error message
@Precondition none
@Postcondition none
@desc Composes an error message that contains the passed message and the
  API error code and matching error message. The CreateFmt constructor
  inherited from the basic Exception class is used to do the work.
Created 5.7.2000 by P. Below
}{---------------------------------------------------------------------}

constructor EClipboardError.Create( const msg: String );
begin { Create }
  CreateFmt( eErrorTemplate,
               [msg, GetLastError, SysErrorMessage(GetLastError)] );
end; { EClipboardError.Create }

{-- DataToClipboard ---------------------------------------------------}
{: Copies a block of memory to the clipboard in a given format
@Param fmt is the clipboard format to use
@Param data is an untyped const parameter that addresses the data to copy
@Param datasize is the size of the data, in bytes
@Precondition The clipboard is already open. If not an EClipboardError
  will result. This precondition cannot be asserted, unfortunately.
@Postcondition Any previously exisiting data of this format will have
  been replaced by the new data, unless datasize was 0 or we run into an
  exception. In this case the clipboard will be unchanged.
@desc Uses API methods to allocate and lock a global memory block of
  approproate size, copies the data to it and submits the block to the
  clipboard. Any error on the way will raise an EClipboardError
  exception.<BR>
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

procedure DataToClipboard( fmt: DWORD; Const data; datasize: Integer );
var
  hMem: THandle;
  pMem: Pointer;
begin { DataToClipboard }
  if datasize <= 0 then
    Exit;

  hMem := GlobalAlloc( GMEM_MOVEABLE or GMEM_SHARE or GMEM_ZEROINIT, datasize );
  if hmem = 0 then
    raise EClipboardError.Create( eSystemOutOfMemory );

  pMem := GlobalLock( hMem );
  if pMem = nil then
  begin
    GlobalFree( hMem );
    raise EClipboardError.Create( eLockFailed );
  end;

  Move( data, pMem^, datasize );
  GlobalUnlock( hMem );
  if SetClipboardData( fmt, hMem ) = 0 then
    raise EClipboardError( eSetDataFailed );

  // Note: API docs are unclear as to whether the memory block has
  // to be freed in case of failure. Since failure is unlikely here
  // lets blithly ignore this issue for now.
end; { DataToClipboard }

{-- DataFromClipboard -------------------------------------------------}
{: Copies data from the clipboard into a stream
@Param fmt is the clipboard format to look for
@Param S is the stream to copy to
@precondition S <> nil
@postcondition If data was copied the streams position will have moved
@desc Tries to get a memory block for the requested clipboard format.
Nothing
  further is done if this fails (because the format is not available or
  the clipboard is not open, we treat neither as error here), otherwise
  the memory handle is locked and the data copied into the stream. <P>
  Note that we cannot determine the actual size of the data originally
  copied to the clipboard, only the allocated size of the memory block!
  Since GlobalAlloc works with a granularity of 32 bytes the block may be
  larger than required for the data and thus the stream may contain some
  spurious bytes at the end. There is no guarantee that these bytes will
  be 0. <P>
  If the memory handle obtained from the clipboard cannot be locked we
  raise an <see class=EClipboardError> exception.
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

procedure DataFromClipboard( fmt: DWORD; S: TStream );
var
  hMem: THandle;
  pMem: Pointer;
  datasize: DWORD;
begin { DataFromClipboard }
  Assert( Assigned( S ));
  hMem := GetClipboardData( fmt );
  if hMem <> 0 then
  begin
    datasize := GlobalSize( hMem );
    if datasize > 0 then
    begin
      pMem := GlobalLock( hMem );
      if pMem = nil then
        raise EclipboardError.Create( eLockFailed );
      try
        S.WriteBuffer( pMem^, datasize );
      finally
        GlobalUnlock( hMem );
      end;
    end;
  end;
end; { DatafromClipboard }

{-- CopyDataToClipboard -----------------------------------------------}
{: Copies a block of memory to the clipboard in a given format
@Param fmt is the clipboard format to use
@Param data is an untyped const parameter that addresses the data to copy
@Param datasize is the size of the data, in bytes
@Param emptyClipboardFirst determines if the clipboard should be emptied,
  true by default
@Precondition The clipboard must not be open already
@Postcondition If emptyClipboardFirst is true all prior data will be
  cleared from the clipboard, even if datasize is <= 0. The clipboard
  is closed again.
@desc Tries to open the clipboard, empties it if required and then tries to
  copy the passed data to the clipboard. This operation is a NOP if
  datasize <= 0. If the clipboard cannot be opened a <see
class=EClipboardError>
  is raised.
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

procedure CopyDataToClipboard( fmt: DWORD; const data; datasize: Integer;
                               emptyClipboardFirst: Boolean = true );
begin { CopyDataToClipboard }
  if OpenClipboard( 0 ) then
    try
      if emptyClipboardFirst then
        EmptyClipboard;
      DataToClipboard( fmt, data, datasize );
    finally
      CloseClipboard;
    end
  else
    raise EclipboardError.Create( eCannotOpenClipboard );
end; { CopyDataToClipboard }

{-- StringToClipboard -------------------------------------------------}
{: Copies a string to clipboard in CF_TEXT clipboard format
@Param S is the string to copy, it may be empty.
@Precondition The clipboard must not be open already.
@Postcondition Any prior clipboard content will be cleared, but only
  if S was not empty. The clipboard is closed again.
@desc Hands the brunt of the work off to <See routine=CopyDataToClipboard>,
  but only if S was not empty. Otherwise nothing is done at all.<BR>
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

procedure StringToClipboard( const S: String );
begin
  if Length(S) > 0 Then
    CopyDataToClipboard( CF_TEXT, S[1], Length(S)+1);
end; { StringToClipboard }

{-- CopyDataFromClipboard ---------------------------------------------}
{: Copies data from the clipboard into a stream
@Param fmt is the clipboard format to look for
@Param S is the stream to copy to
@Precondition S <> nil<P>
  The clipboard must not be open already.
@Postcondition If data was copied the streams position will have moved.
  The clipboard is closed again.
@desc Tries to open the clipboard, and then tries to
  copy the data to the passed stream. This operation is a NOP if
  the clipboard does not contain data in the requested format.
  If the clipboard cannot be opened a <see class=EClipboardError>
  is raised.
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

procedure CopyDataFromClipboard( fmt: DWORD; S: TStream );
begin { CopyDataFromClipboard }
  Assert( Assigned( S ));
  if OpenClipboard( 0 ) then
    try
      DataFromClipboard( fmt , S );
    finally
      CloseClipboard;
    end
  else
    raise EclipboardError.Create( eCannotOpenClipboard );
end; { CopyDataFromClipboard }

{-- ClipboardAsString -------------------------------------------------}
{: Returns any text contained on the clipboard
@Returns the clipboards content if it contained something in CF_TEXT
  format, or an empty string.
@Precondition The clipboard must not be already open
@Postcondition The clipboard is closed.
@desc If the clipboard contains data in CF_TEXT format it is copied to a
  temp memory stream, zero-terminated for good measure and copied into
  the result string.
Created 5.7.2000 by P. Below
@Raises EClipboardError
}{---------------------------------------------------------------------}

function ClipboardAsString: String;
const
  nullchar: Char = #0;
var
  ms: TMemoryStream;
begin { ClipboardAsString }
  if not IsClipboardFormatAvailable( CF_TEXT ) then
    Result := EmptyStr
  else
  begin
    ms:= TMemoryStream.Create;
    try
      CopyDataFromClipboard( CF_TEXT , ms );
      ms.Seek( 0, soFromEnd );
      ms.WriteBuffer( nullChar, Sizeof( nullchar ));
      Result := PChar( ms.Memory );
    finally
      ms.Free;
    end;
  end;
end; { ClipboardAsString }

{-- ClipboardHasFormat ------------------------------------------------}
{: Checks if the clipboard contains data in the specified format
@Param fmt is the format to check for
@Returns true if the clipboard contains data in this format, false
  otherwise
@Precondition none
@Postcondition none
@desc This is a simple wrapper around an API function.
Created 5.7.2000 by P. Below
}{---------------------------------------------------------------------}

function ClipboardHasFormat( fmt: DWORD ): Boolean;
begin { ClipboardHasFormat }
  Result := IsClipboardFormatAvailable( fmt );
end; { ClipboardHasFormat }

end.

サンプル使用:

SQL エディター、テキスト エディターなどでテキストを準備します。

選択する
  名前、
  fname、
  ドブ
から
  従業員

すべてのテキストを選択し、Ctrl+C を使用してクリップボードにコピーします。

IDE のコード エディタに切り替えて、ClipboardToStringConst アプリケーションを実行します (追加した [ツール] メニュー項目を使用するか、その他の手段を使用します)。定数テキストを表示する場所にエディターのカーソル (挿入ポイント) を置き、Ctrl+V を押してテキストを貼り付けます。

定数
  MySQLText = | // パイプは挿入ポイントを示します。

結果:

定数
  MySQLText = '選択'+
  ' 名前, '+
  ' fname, '+
  'ドブ'+
  'から'+
  ' 従業員 ';
于 2009-12-09T13:42:14.277 に答える
4

このようなことを意味しますか?

myStr := 'first line'#13#10'secondline'#13#10'thirdline';
于 2009-12-09T08:58:52.510 に答える
3

フォームまたはデータ モジュールの TQuery コンポーネントに SQL を配置することを検討できます。

これにより、コピー/貼り付けの問題は解決されますが、他の問題が発生します (クエリの 2 つのバージョン間の違いが悪化するなど)。

于 2009-12-09T15:24:55.757 に答える
2

簡単な答えはノーです、それはできません。(私はそれがあなたが聞きたいものではないことを知っています。)

しかし、 Andreas Hausladenは、まさにこれが可能な拡張機能を開発しました。グーグルで検索しましたが見つかりませんでした。それは彼のDLangExtensionsパックに含まれていたと思いますが、彼はすでに2007年後半にサポートを終了しました。:(

于 2009-12-09T12:27:49.450 に答える
2

Delphi >= 2007 のバージョンでは、複数行にわたって引用符で囲まれた文字列を入力すると、引用符を自分で閉じないと、次の行に閉じ引用符と + ' が自動的に追加されます。

これは問題の解決策ではありませんが、長い文字列の入力を高速化するのに役立ちます。

于 2009-12-09T09:48:39.467 に答える
2

引用符なしで複数の行に文字列を定義することはできません:

const
  myString = 'this is a long string that extends' +
             'to a second line';

ただし、次のような制御文字から文字列を作成できます。

const 
  myString = #83#84#82#73#78#71;

しかし、それは読み取り可能なコードに起因するものではありません。

于 2009-12-09T09:02:56.403 に答える