2016-01-31 29 views
0

我需要在TMemo中顯示base64密鑰。不幸的是,不可能適當地顯示這個base64字符串:它在每個'/'被一個Carriage return或者在系統地開始一個新行的任何'+'處截斷! 我嘗試了一切以我的知識使這個字符串在一個很長的短語中(沒有回車),但沒有成功。 如何在base64中獲取扁平字符串(無回車符),如果可能的話,當窗體和TMemo被調整大小時可以自動調整大小? 非常感謝。Fmx TMemo無法正確顯示base64字符串

回答

0

對於有興趣的人,下面的代碼:與TMemo(備忘錄)的TForm。這個解決方案適用於我的一個扁平的Base64字符串。最後不再在每個/或+處切斷電源。 也許下面的解決方案需要調整,但它對我來說足夠了。當然,在處理應用程序中的b64字符串之前,需要對它進行過濾以消除CR-LF,但沒關係。 我使用的事件:OnKeyDown,OnResize,OnPainting的TMemo。 我寫了一個特定的函數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 
    } 
} 
//---------------------------------------------------------------------------