0

TMemo で base64 キーを表示する必要があります。残念ながら、この base64 文字列を適切に表示することは不可能です。キャリッジ リターンによってすべての '/' で、または体系的に新しい行を開始する '+' で切断されます。この文字列を 1 つの長いフレーズ (キャリッジ リターンなし) にするために、私の知識のすべてを試しましたが、うまくいきませんでした。可能であれば、フォームと TMemo のサイズが変更されたときに自動的にサイズ変更できる場合、base64 (改行なし) でフラット文字列を取得するにはどうすればよいですか? どうもありがとう。

4

1 に答える 1

0

興味のある方は、以下のコードをご覧ください: TMemo (メモ) を含む TForm。このソリューションは、フラットな Base64 文字列に対して機能します。ついに弦が / または + ごとに切れることがなくなりました。以下のソリューションを調整する必要があるかもしれませんが、それで十分です。もちろん、アプリケーションで b64 文字列を処理する前に、CR-LF を除去するためにフィルタリングする必要がありますが、それは問題ありません。イベントを使用します: TMemo の OnKeyDown、OnResize、OnPainting。行を適切に整列させる特定の関数 formatMemo(..) を作成しました。コードは真の B64 文字のみを受け入れ、誤った文字があればフィルターします。

#define IS_B64(c) (isalnum(c) || (c == '/') || (c == '+') || (c == '='))

//Adjustments work for Courier New, standard size:
const float FW=7.2;//Font width
const diff=25;//Room for vert. scroll bar

//Gives the number of characters in one line of the TMemo:
//  width : width in pixels where to put the line of chars
//  font_sz : the average width of a character
//  returns the number of characters by line of the TMemo
inline int nchars(int width, float font_sz)
{
    return int(float(width-diff)/font_sz);
}//nchars
//---------------------------------------------------------------------------

//Formats the memo to a certain length of characters:
//  *p : the memo to format
//  nc : the number of characters for each line.
void formatMemo(TMemo *p, int nc)
{
    if(p==0) return;
    AnsiString src, dest;//UnicodeString is less fast...
    //Filter everything as B64 only:
    for(int i=1; i<=p->Text.Length(); ++i) {//Indexing is "1-based" like on Delphi (except on mobiles)
        if(IS_B64(p->Text[i])) dest += p->Text[i];
    }
    p->Lines->Clear();//Erases everyting
    int length=dest.Length(), units=length/nc, remain=length%nc;
    for( int k=0 ; k<units ; ++k) {
        p->Lines->Append( dest.SubString(1+k*nc, nc) );
    }
    if(remain) {
        p->Lines->Append( dest.SubString(1+units*nc, remain) );
    }
}//formatMemo
//---------------------------------------------------------------------------

void __fastcall TForm1::memoKeyDown(TObject *Sender, WORD &Key, System::WideChar  &KeyChar,
          TShiftState Shift)
{
    //This event is triggered before the character is sent in Text.
    //Saves caret position:
    TCaretPosition p={memo->CaretPosition.Line, memo->CaretPosition.Pos};
    memo->Tag=0;//Don't do a format.

    if(Key==0 && !IS_B64(KeyChar))//Printable KeyChar
    {
        //Changes the entry into '0':
        KeyChar='0';
        KeyDown(Key,KeyChar,Shift);

        //Put a backspace to erase:
        Key=vkBack; KeyChar=0;
        KeyDown(Key,KeyChar,Shift);
    }
    else memo->Tag=1;//Programs a format in the OnPainting
    memo->SetFocus();
    memo->CaretPosition=p;//Repositions the caret
}
//---------------------------------------------------------------------------

//In case of resize, reformat the TMemo
void __fastcall TForm1::memoResize(TObject *Sender)
{
    formatMemo(memo, nchars(memo->Width,FW));
}
//---------------------------------------------------------------------------

void __fastcall TForm1::memoPainting(TObject *Sender, TCanvas *Canvas, const TRectF &ARect)
{
    //We will use the Tag of the memo as a parameter, to plan a reformat.
    if(memo->Tag){//A format is asked by OnKeyDown.
        TCaretPosition p={memo->CaretPosition.Line, memo->CaretPosition.Pos};
        formatMemo(memo, nchars(memo->Width,FW));
        memo->SetFocus();
        memo->CaretPosition=p;
        memo->Tag=0;//Done
    }
}
//---------------------------------------------------------------------------
于 2016-02-04T23:00:24.357 に答える