Search

'RTF'에 해당되는 글 3건

  1. 2007.07.24 CF_RTF를 사용하기위해...
  2. 2007.07.24 Msftedit.dll과 CF_RTF
  3. 2007.07.23 RTF를 사용하기 위하여

CF_RTF를 사용하기위해...

Projects/CoVNC 2007.07.24 17:51 Posted by soulfree >동네청년<
#include <richedit.h>를 추가해줍니다....
이걸 찾기위해 하루를 보냈습니다...
신고

'Projects > CoVNC' 카테고리의 다른 글

탭스 업로드 3.0  (0) 2007.08.03
html을 클립보드에 복사  (0) 2007.07.25
CF_RTF를 사용하기위해...  (0) 2007.07.24
Msftedit.dll과 CF_RTF  (0) 2007.07.24
다중포멧 클립보드를 위한 글들...  (0) 2007.07.23
RTF를 사용하기 위하여  (0) 2007.07.23

Msftedit.dll과 CF_RTF

Projects/CoVNC 2007.07.24 16:31 Posted by soulfree >동네청년<
MFC를 사용하지 않고 win32 API만으로  rich editor 라이브러리인 Msftedit.dll을 사용하는 방법을 잘 모르겠네요...
영어나 우리말로 잘 되어있는 문서도 없고, 라틴어?? (맞나??)로 된 글을 복사해둡니다. 참고하시길...

 

Page 1

Note sul controllo Rich Edit

[di Matteo Mecucci – v.1.3 del 28 settembre 2006]

Introduzione

Come per tante altre parti delle API Win32, anche il Rich Edit a volte si comporta in modi inattesi o

non documentati, perciò mi piacerebbe appuntare qui alcune note relative al suo uso. La lista

crescerà man mano che avrò tempo di stilarla e man mano che i problemi si presenteranno.

In questi giorni in ufficio stiamo creando un software che usa intensamente un controllo rich–text

full–featured. Per realizzarlo ho scelto di partire dal Rich Edit Control di base delle API Win32,

contenuto in un controllo custom che ne gestisca gli eventi e l'interazione con le altre parti del

software. Questa scelta ha portato ovviamente alcuni vantaggi e alcuni svantaggi ma per i nostri

scopi al momento sembra che possiamo accontentarci e possiamo raggiungere più o meno ogni

obbiettivo previsto.

Licenza

Questo documento è distribuito con Licenza Creative Commons BY-NC-SA 2.0. I

termini della licenza sono disponibili presso il sito:

http://creativecommons.org/licenses/by-nc-sa/2.0/it/

Eventuali marchi e copyright nominati ed utilizzati in questo documento appartengono ai rispettivi

proprietari.

Il materiale fornito è da considerarsi "AS IS" e l'autore declina ogni responsabilità per danni

derivanti dal suo utilizzo.

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 1


Page 2

La versione del controllo da utilizzare

La scelta della versione del controllo da utilizzare non è necessariamente banale. Sebbene

siano "papabili" per il controllo sia la classe RICHEDIT_CLASS (versione 2.0 o 3.0) che la classe

MSFTEDIT_CLASS (versione 4.1 disponibile con XP SP1), quest'ultima ha un supporto

decisamente migliore delle tabelle RTF (non al livello di Word, comunque) e offre un'anteprima

di stampa più fedele, ma renderizza in modo pessimo le tabelle con colonne a larghezza

automatica (assegna a tutte larghezza nulla, mentre la versione precedente gli assegna una larghezza

fissa). Inoltre l'ultima versione del controllo non supporta ‘nativamente’ il set di caratteri ANSI ma

solo quello UTF–16.

Se si sceglie il controllo MSFTEDIT_CLASS, bisogna fare attenzione alle impostazioni del

progetto rispetto all'encoding dei caratteri. Se si utilizza, come accade nella maggior parte dei

progetti legacy, la versione ANSI e non quella Unicode UTF–16 delle API, ci sono alcuni punti su

cui soffermarsi.

Prima di tutto non può essere utilizzato nel CreateWindow il define della classe perché anche

quello è una stringa wide, quindi bisogna usare direttamente il nome della classe

"RichEdit50W" (notate che al contrario delle versioni precedenti non esiste alcuna classe

"RichEdit50A").

m_pRichEditDll = ::LoadLibrary("msftedit.dll");

if(m_pRichEditDll != NULL)

{

// si assicura che i controlli avanzati siano attivi

INITCOMMONCONTROLSEX icc;

icc.dwSize = sizeof(INITCOMMONCONTROLSEX);

icc.dwICC = ICC_WIN95_CLASSES;

InitCommonControlsEx(&icc);

// crea il controllo rich text

m_pRTHwnd = ::CreateWindowEx(exStyle, TEXT("RICHEDIT50W"), TEXT(""),

style, 0, 0, rc.width(), rc.height(), m_pHwnd, NULL, NULL, NULL);

}

Si deve anche tenere presente che tutti i messaggi al controllo possono essere inviati

tranquillamente con le strutture in versione Ansi (ad esempio EM_SETCHARFORMAT può

utilizzare CHARFORMAT = CHARFORMATA) in quanto vengono inviati per default con

SendMessage = SendMessageA, TRANNE i messaggi che LEGGONO il testo dal controllo,

ovvero EM_GETSELTEXT e EM_GETTEXTRANGE, in quanto i buffer vengono comunque

interpretati come wchar_t* e quindi riempiti con testo Unicode, non Ansi; quindi va utilizzato nel

primo caso un buffer wchar_t* e nel secondo la struttura TEXTRANGEW e non TEXTRANGE.

Nessun problema invece per i messaggi che impostano il testo, come EM_REPLACESEL o

EM_SETTEXTEX.

// copia in textw tutto il testo del controllo in formato UTF-16

wchar_t* textw = (wchar_t*)malloc(...);

// dimensione opportuna

TEXTRANGEW tr = { {0, -1}, textw };

int read = ::SendMessage(m_pRTHwnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 2


Page 3

Impostazioni del formato del testo

Tutte le misure del rich text sono espresse in twip: 1 cm = 567 twips; 1 pollice = 1440 twip.

Questi numeri possono essere utili ad esempio nei CHARFORMAT e nei PARAFORMAT.

Per evitare il wordwrap del testo è necessario inviare il messaggio EM_SETTARGETDEVICE

con wParam=0 e lParam=1. Se si vuole il wordwrap (come di default), lParam va messo pari a 0.

Nella stampa questo messaggio va utilizzato in modo più accorto, impostando il device context

della stampante come wParam e la larghezza del foglio come lParam.

// disattiva il wordwrap in base ad un flag

::SendMessage(m_pRTHwnd, EM_SETTARGETDEVICE, NULL, m_fTextOnlyMode ? 1 : 0);

Per poter utilizzare l'allineamento giustificato è necessario prima aver impostato il flag

TO_ADVANCEDTYPOGRAPHY col messaggio EM_SETTYPOGRAPHYOPTIONS.

Per utilizzare il controllo RichEdit come editor di testo non formattato imposto il flag

SES_EMULATESYSEDIT

nel

messaggio

EM_SETEDITSTYLE,

il

flag

TO_SIMPLELINEBREAK nel messaggio EM_SETTYPOGRAPHYOPTIONS. La cosa più

seccante però è la necessità di filtrare il tentativo di incollare testo formattato nel controllo: ne

parliamo in maggiore dettaglio in seguito. Basti dire che il flag TM_PLAINTEXT nel messaggio

EM_SETTEXTMODE, che la documentazione indica come sufficiente allo scopo sembra non avere

alcun effetto sul problema.

// imposta i flag in base al flag text-only

::SendMessage(m_pRTHwnd, EM_SETTYPOGRAPHYOPTIONS,

m_fTextOnlyMode ? TO_SIMPLELINEBREAK : TO_ADVANCEDTYPOGRAPHY,

m_fTextOnlyMode ? TO_SIMPLELINEBREAK : TO_ADVANCEDTYPOGRAPHY);

::SendMessage(m_pRTHwnd, EM_SETEDITSTYLE,

m_fTextOnlyMode ? SES_EMULATESYSEDIT : 0, SES_EMULATESYSEDIT);

Il default per il massimo di caratteri che il controllo accetta è in molte occasioni basso: 2

15

(32767) caratteri. È sufficiente impostarlo con EM_EXLIMITTEXT, mettendo in lParam un

numero più alto (noi usiamo ad esempio 0xffffff = 2

24

-1). Questo messaggio deve essere inviato

quando il controllo è vuoto.

// svuota il controllo ed imposta il numero di caratteri che esso accetta

SETTEXTEX st = {ST_DEFAULT, CP_ACP};

::SendMessage(m_pRTHwnd,EM_SETTEXTEX,(WPARAM)&st,(LPARAM)TEXT(""));

::SendMessage(m_pRTHwnd, EM_EXLIMITTEXT, 0, 0xffffff);

Quando si aggiunge del testo non RTF al controllo esso assume la formattazione corrente ma

alla fine viene reimpostata quella di default. Se tenete alla formattazione esistente nel punto di

inserimento, abbiate cura di chiedere la formattazione con EM_GETCHARFORMAT prima di

inserire il testo e di reimpostarla con EM_SETCHARFORMAT dopo averlo inserito. Fate anche

attenzione che aggiungere del testo programmaticamente non sposta il cursore nel controllo: se

dovete aggiungere testo di seguito ogni volta dovete anche spostare il cursore.

// inserisce del testo UTF-16 non formattato in fondo al controllo

::SendMessage(m_pRTHwnd, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);

CHARFORMAT2 cf;

cf.cbSize = sizeof(cf);

::SendMessage(m_pRTHwnd, EM_GETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );

cf.dwMask = CFM_ALL2;

SETTEXTEX st = {ST_SELECTION, 1200};

::SendMessage(m_pRTHwnd, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)textw);

::SendMessage(m_pRTHwnd, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 3


Page 4

Creare una tabella direttamente attraverso PARAFORMAT non è possibile (i pochi attributi

relativi sono in sola lettura e non possono essere impostati in un EM_SETPARAFORMAT). Il

metodo migliore che abbiamo trovato è stato quello di costruire un testo RTF che descrivesse la

tabella voluta e inserirlo nel controllo già bello e pronto. Documentazione essenziale per lo scopo

la specifica RTF della Microsoft, ovviamente.

La numerazione con PFM_NUMBERING sa contare solo fino a 255. Se si imposta il numero

iniziale ad X con PFM_NUMBERINGSTART, il massimo numero che si può ottenere (senza

reimpostare a mano PFM_NUMBERINGSTART) è X+255.

Per quanto strano, il numero o il pallino della numerazione assumono il CHARFORMAT

dell'accapo della riga dove si trovano: se si vuole il numero in grassetto, ad esempio, è necessario

impostare il CFM_BOLD dell'ultimo carattere della riga dove si trova il numero.

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 4


Page 5

Sovraccaricare la gestione degli eventi di default

Si possono facilmente intercettare eventi di mouse, tastiera e altro genere col messaggio

EM_SETEVENTMASK e gestendo i messaggi sul controllo parent.

Si può ad esempio bloccare un tasto per impedirgli di fare edit e collegarlo ad una funzione sul

testo — è sufficiente restituire un valore non nullo nella WindowProc in risposta all'evento

EN_MSGFILTER relativo; ho usato questo metodo ad esempio per gestire il Tab e lo Shift-Tab

per aumentare e diminuire l'indentazione di una selezione, mentre senza selezione il Tab

aggiunge una tabulazione, come di default. Inoltre gestisco l'evento EN_SELCHANGE per

aggiornare la toolbar rispetto al CHARFORMAT e al PARAFORMAT del testo selezionato e

l'evento EN_CHANGE per impostare un documento come modificato.

// frammento della WindowProc del controllo parent del rich-text

if(uMsg == WM_NOTIFY &&((LPNMHDR)lParam)->code == EN_MSGFILTER)

{

// controlla se il tasto premuto e' tab e se c'e' una selezione attiva.

// in questo caso fa l'indentazione del testo selezionato

// e non la sostituzione col carattere di tabulazione.

MSGFILTER* filter = (MSGFILTER*)lParam;

if(filter->msg==WM_CHAR &&filter->wParam=='\t')

{

CHARRANGE cr;

SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&cr);

if(cr.cpMax != cr.cpMin)

{

if(IsShiftDown())

ctrl->Outdent();

else

ctrl->Indent();

return 1;

}

}

}

Per verificare se il controllo è stato modificato è sufficiente nella maggior parte dei casi usare

il messaggio EM_GETMODIFY. Se però prevedete di poter inserire oggetti OLE all'interno del

testo, dovete occuparvi voi di controllare se qualcuno di essi è modificato. Ho scelto di farlo

enumerando tutti gli oggetti attraverso l'interfaccia OLE del controllo ottenibile col messaggio

EM_GETOLEINTERFACE. Nell'enumerazione (ottenuta con GetObjectCount()/GetObject()),

controllo se l'oggetto corrente ha l'interfaccia IPersistStorage (con QueryInterface) e quindi

controllo le modifiche col metodo IsDirty().

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 5


Page 6

// se il flag di modificato non e' settato, controlla

// prima che il controllo stesso non lo abbia attivo

m_fModified = ::SendMessage(m_pRTHwnd, EM_GETMODIFY, 0, 0)!=0;

if(m_fModified || !m_pOleObj)

return;

// poi controlla se un oggetto contenuto nel controllo e' per caso modificato

// andando a cercare il flag IsDirty sulla sua interfaccia IPersistStorage

HRESULT hr = 0;

int objectCount = m_pOleObj->GetObjectCount();

for (int i = 0; !m_fModified &&i <objectCount; i++)

{

REOBJECT reObj;

ZeroMemory(&reObj, sizeof(REOBJECT));

reObj.cbStruct = sizeof(REOBJECT);

hr = m_pOleObj->GetObject(i, &reObj, REO_GETOBJ_POLEOBJ);

if(SUCCEEDED(hr))

{

IPersistStorage* pstg=NULL;

if(SUCCEEDED(reObj.poleobj->QueryInterface(

IID_PPV_ARG(IPersistStorage, &pstg))))

{

if(pstg &&pstg->IsDirty()==S_OK)

m_fModified=true;

pstg->Release();

}

reObj.poleobj->Release();

}

}

Per intercettare alcuni eventi OLE è possibile impostare un oggetto di callback attraverso il

messaggio EM_SETOLECALLBACK. La classe dell'oggetto deve derivare dall'interfaccia

IRichEditOleCallback e può risultare utile (necessaria) per diverse cose, di cui parleremo in seguito.

La definizione della classe è agevolata dal fatto che tutti i metodi che non vogliamo implementare

possono semplicemente restituire E_NOTIMPL o in alcuni casi S_OK (ad esempio in

QueryInsertObject e in DeleteObject) per ottenere il comportamento di default. Fornendo l'oggetto

di callback è possibile:

inserire oggetti OLE nel controllo fornendo l'implementazione di GetNewStorage,

deputata a creare oggetti di storage.

// implementazione molto banale e poco efficiente di GetNewStorage

HRESULT TRichTextOleCallback::GetNewStorage(LPSTORAGE* ppStg)

{

if (!ppStg)

return E_INVALIDARG;

*ppStg = NULL;

LPLOCKBYTES pLockBytes;

HRESULT hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);

if (FAILED(hr))

return hr;

hr = StgCreateDocfileOnILockBytes(pLockBytes, STGM_SHARE_EXCLUSIVE |

STGM_CREATE | STGM_READWRITE, 0, ppStg);

pLockBytes->Release();

return (hr);

}

gestire l'interazione con la nostra applicazione dei controlli che supportano

l'attivazione in–place, implementando i metodi GetInPlaceContext e ShowContainerUI.

Questa interazione coinvolge a fondo altre parti dell'applicazione (toolbar, menu, palette e

quant'altro?), quindi può essere di difficile attuazione in applicazioni legacy non realizzate

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 6


Page 7

dall'inizio con certi criteri. Tra l'altro non è sempre desiderabile che questa attivazione

inplace abbia luogo: in alcuni casi è molto meglio che con un doppio click si apra

l'applicazione relativa all'oggetto OLE nel suo ambiente esclusivo, senza interagire

direttamente col nostro; è molto comodo il fatto che questo sia esattamente il

comportamento di default.

filtrare gli oggetti OLE che si possono inserire (magari con un paste dalla clipboard, con

un caricamento da file o con un dialogo "Inserisci oggetto?") implementando il metodo

QueryInsertObject.

filtrare dati in ingresso dalla clipboard o dal drag&drop (come vedremo più avanti)

implementando il metodo QueryAcceptData.

fornire un help basato sul contesto implementando il metodo ContextSensitiveHelp.

mostrare un menu contestuale in risposta al tasto destro del mouse (praticamente

obbligatorio), implementando il metodo GetContextMenu.

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 7


Page 8

Salvataggio e caricamento

Serializzare il contenuto del controllo su file RTF o su un buffer in memoria è molto semplice

attraverso il messaggio EM_STREAMOUT. Questo messaggio permette anche di specificare

un'eventuale pagina di codici per la codifica del testo. In particolare mi sembrava molto interessante

la possibilità di usare la codifica UTF–8, usando come wParam «(CP_UTF8 <<16) |

SF_USECODEPAGE | SF_RTF», in base alla documentazione. Ebbene queste impostazioni

generano file perfettamente validi (come si verifica leggendo il file attraverso un relativo

EM_STREAMIN) ma purtroppo non leggibili da Word e da Wordpad. A parte la questione assurda

che il Wordpad nient'altro dovrebbe essere che un contenitore per lo stesso controllo che stiamo

realizzando (usa l'mfstedit), il motivo si legge nella specifica dell'RTF (della Microsoft,

ovviamente): il tag \urtf1, quello utilizzato in questa codifica, è generato dall'applicazione "Pocket

Word" (della Microsoft, ovviamente) e NON viene riconosciuto da Word. Non riesco a spiegarmi

questa cosa. Comunque per i file bisogna di fatto usare SF_RTF e basta. Il problema è relativo

per fortuna, in quanto la specifica RTF prevede comunque precise modalità per la memorizzazione

di caratteri Unicode, quindi non si perde niente…

Anche salvare un pezzo di testo selezionato e non tutto il contenuto come file RTF è

abbastanza semplice. È sufficiente utilizzare il metodo GetClipboardData dell'oggetto

IRichEditOle ottenibile con il messaggio EM_GETOLEINTERFACE. Questo metodo restituisce un

oggetto IDataObject per un certo range di caratteri, che è possibile interrogare con un opportuno

FORMATETC per ottenere i dati relativi nel formato desiderato (CF_RTF o CF_TEXT nel nostro

caso).

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 8


Page 9

Bug e work–around

Come accennato prima, quando si utilizza il controllo richtext in modalità solo testo si ha lo

spiacevole comportamento di default che per quanti flag si impostino il testo formattato continua

a poter entrare nel controllo dalla clipboard o con i drag&drop. Per evitare tutto ciò è

necessario, come accennato, implementare la funzione QueryAcceptData dell'interfaccia

IRichTextOleCallback. Al suo interno va controllato innanzitutto se ci viene richiesto il formato che

preferiamo (quando *pcfFormat==0): in tal caso specifichiamo che vogliamo ovviamente

CF_TEXT. Se al contrario il formato è imposto, si restituisce DATA_E_FORMATETC (per

convenzione, ma va bene un errore qualsiasi) se esso è appunto diverso da CF_TEXT.

Con questo metodo è uscito fuori però un bacherello (almeno pare tale): il richtext elimina

l'eventuale end–of–line dell'ultima riga del testo da incollare: se ad esempio si copia una linea

intera di testo, compreso l'accapo, quando eseguiamo l'incolla l'accapo non viene incollato. Questo

comportamento è ancora più evidente quando si fa il drag&drop del testo: se una linea intera di

testo viene spostata e poi il drop viene annullato o finisce nella posizione originale, l'accapo viene

eliminato. Per evitare tutto ciò possiamo modificare ancora la QueryAcceptData in modo che,

quando il paste stia avvenendo (segnalato da fReally==1), essa esegua direttamente l'operazione,

chiedendo al pDataObj i dati CF_TEXT col metodo GetData ed inserendoli nel controllo con un

EM_SETTEXTEX. A quel punto essa può restituire S_FALSE, ovvero un codice di successo ma

negativo che indica al chiamante che il dato è stato accettato ma che si è già provveduto

all'inserimento. Infatti restituire S_OK farebbe inserire un'altra volta il testo mentre restituire un

codice d'errore eviterebbe ad esempio la cancellazione del testo originale in un drag&drop.

// implementazione del metodo QueryAcceptData per gestire correttamente

// la copia del testo non formattato

HRESULT TrichTextOleCallback::QueryAcceptData(

LPDATAOBJECT pDataObj, CLIPFORMAT* pcfFormat,

DWORD reco, BOOL fReally, HGLOBAL hMetaPict)

{

// se il controllo e' in modalita' solo testo, pretende di ottenere

// il formato CF_TEXT, altrimenti restituisce errore

if(m_pCtrl &&m_pCtrl->IsInTextOnlyMode())

{

// workaround per inserire gli accapo alla fine del testo

if(fReally)

{

FORMATETC ftc; STGMEDIUM stg;

ftc.cfFormat = CF_TEXT;

ftc.dwAspect = DVASPECT_CONTENT;

ftc.lindex = -1; ftc.ptd = NULL;

ftc.tymed = TYMED_HGLOBAL;

if(pDataObj &&SUCCEEDED(pDataObj->GetData(&ftc, &stg)) &&

stg.hGlobal)

{

char* text = (char*)GlobalLock(stg.hGlobal);

if(text)

{

// inserisce il testo al posto della selezione corrente

m_pCtrl->InsertText(text);

GlobalUnlock(stg.hGlobal);

}

if(stg.pUnkForRelease)

stg.pUnkForRelease->Release();

else

GlobalFree(stg.hGlobal);

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 9


Page 10

if(text)

// codice per dire che questa funzione ha accettato

// il testo ma l'ha anche inserito direttamente lei

return S_FALSE;

}

}

if(*pcfFormat == 0)

{

// chiediamo solo testo non formattato

*pcfFormat = CF_TEXT;

return S_OK;

}

if(*pcfFormat != CF_TEXT) // errore: formato non valido

return DATA_E_FORMATETC;

}

return S_OK;

}

In alcuni strani casi in cui nella clipboard c'è tra i formati disponibili "RTF in UTF8", ci è capitato

di ottenere un testo vuoto utilizzando il WM_PASTE standard. Per questo abbiamo preferito

intercettare i comandi di incolla (non col QueryAcceptData ma direttamente da dove viene inviato il

WM_PASTE) e chiedere esplicitamente l'inserimento dei dati CF_RTF con un bel

EM_PASTESPECIAL.

// workaround necessario per strani casi in cui c'e' "RTF in UTF8"

// tra i formati nella clipboard

static int cf_rtf = RegisterClipboardFormat(CF_RTF);

if(!m_fTextOnlyMode &&::SendMessage(m_pRTHwnd, EM_CANPASTE, cf_rtf, 0))

{

::SendMessage(m_pRTHwnd, EM_PASTESPECIAL, cf_rtf, 0);

return;

}

::SendMessage(m_pRTHwnd, WM_PASTE, 0, 0);

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 10


Page 11

Riferimenti

Descrizione del RichEdit Control su MSDN:

http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/RichEdit/RichEditControls.asp

Rich Text Format Specification, version 1.8:

http://go.microsoft.com/?linkid=5467681

Il mio sito:

http://www.digitalwaters.net/

© 2006 Matteo Mecucci, DigitalWaters.net

pag. 11

신고

'Projects > CoVNC' 카테고리의 다른 글

html을 클립보드에 복사  (0) 2007.07.25
CF_RTF를 사용하기위해...  (0) 2007.07.24
Msftedit.dll과 CF_RTF  (0) 2007.07.24
다중포멧 클립보드를 위한 글들...  (0) 2007.07.23
RTF를 사용하기 위하여  (0) 2007.07.23
소스코드 검색 사이트  (0) 2007.06.09

RTF를 사용하기 위하여

Projects/CoVNC 2007.07.23 21:16 Posted by soulfree >동네청년<
출처 : msdn

==============================================================================================

About Rich Edit Controls

The original specification for rich edit controls is Microsoft Rich Edit 1.0; the current specification is Rich Edit 4.1. Each version of rich edit is a superset of the preceding one, except that only Asian builds of Rich Edit 1.0 have a vertical text option. Before creating a rich edit control, you should call the LoadLibrary function to verify which version of Rich Edit is installed. For more information, see What's New in Rich Edit.

The following table shows which DLL corresponds with which version of Rich Edit. Note that the name of the file did not change from version 2.0 to version 3.0. This allows version 2.0 to be upgraded to version 3.0 without breaking existing code.

Rich Edit version DLL
1.0 Riched32.dll
2.0 Riched20.dll
3.0 Riched20.dll
4.1 Msftedit.dll

The following list describes which versions of Rich Edit are included in which releases of Microsoft Windows.

Windows XP SP1 Includes Rich Edit 4.1, Rich Edit 3.0, and a Rich Edit 1.0 emulator.
Windows XP Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
Windows Me Includes Rich Edit 1.0 and 3.0.
Windows 2000 Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
Windows NT 4.0 Includes Rich Edit 1.0 and 2.0.
Windows 98 Includes Rich Edit 1.0 and 2.0.
Windows 95 Includes only Rich Edit 1.0. However, Riched20.dll is compatible with Windows 95 and may be installed by an application that requires it.

On Windows 95/98/Me, Rich Edit 1.0 is localized so that it works with a particular operating system that is similarly localized. For example, on Japanese versions of an operating system, Rich Edit 1.0 can display Japanese, but not Arabic.

The following topics are discussed in this section.

What's New in Rich Edit

The following topics describe the new features introduced in each version of Rich Edit.

Rich Edit Version 1.0

Rich Edit 1.0 includes the following features.

Text entry and selection Mostly standard (system-edit control) selection and entry of text. Selection bar support (the selection bar is an unmarked area to the left of each paragraph that when clicked, selects the line). Word-wrap and auto-word-select options. Single-, double-, and triple-click selection.
ANSI (single-byte character set (SBCS) and multibyte character set (MBCS)) editing However, there is no Unicode editing.
Basic set of character/paragraph formatting properties See CHARFORMAT and PARAFORMAT.
Character formatting properties Font name and size, bold, italic, solid underline, strike-out, protected, link, offset, and text color.
Paragraph formatting properties Start indent, right indent, subsequent line offset, bullet, alignment (left, center, right), and tabs.
Find forward Includes case-insensitive and match-whole-word options.
Message-based interface Almost a superset of the system edit-control message set plus two interfaces, IRichEditOle and IRichEditCallback.
Embedded objects Requires client collaboration based on IRichEditOle and IRichEditCallback interfaces.
Right-button menu support Uses IRichEditCallback interface.
Drag-and-drop editing Drag-and-drop editing is supported.
Notifications WM_COMMAND messages sent to client plus a number of others. This is a superset of common-control notifications.
Single-level undo/redo Behaves similarly to the system edit control. Selecting Undo reverses the last action, and that action then becomes the new Redo action.
Simple vertical text (Asian builds only).
Input Method Editor (IME) support (Asian builds only).
WYSIWYG editing using printer metrics This feature is needed for Microsoft WordPad, in particular.
Cut/Copy/Paste/StreamIn/StreamOut With plain text (CF_TEXT) or Rich Text Format (RTF) with and without objects.
C code base The code is written in C, which provides a solid and versatile foundation.
Different builds for different scripts Rich Edit 1.0 addresses localization issues with different builds.

Rich Edit Version 2.0

Rich Edit 2.0 incorporated several additional features, such as support for Unicode and Asian languages, multilevel Undo, Component Object Model (COM) interfaces, and numerous user interface (UI) enhancements.

Rich Edit 2.0 includes the following features in addition to the features provided by  .

Unicode Unicode eases the effort in handling international text. However effort is needed to maintain compatibility with existing non-Unicode documents—that is, the ability to convert to/from non-Unicode plain and rich text. Also, substantial effort is needed to run correctly on Windows 95/98/Me.
General international support General line breaking algorithm (extension of Kinsoku rules), simple font linking, keyboard font switching.
Asian support Level 2 (dialog box) and 3 (inline) is supported in IMEs.
Find Up/Find Down support Searching forward and backward is supported.
Bidirectional support This is included in Rich Edit 2.1
Multilevel undo An extensible Undo architecture allows client to participate in application-wide Undo model.
Magellan mouse support This is the mouse with a roller for scrolling.
Dual-font support The keyboard can automatically switch fonts when the active font is inappropriate for current keyboard, for example, Kanji characters in Times New Roman.
Smart font apply Font change request does not apply Western fonts to Asian characters.
Improved display An off-screen bitmap is used when multiple fonts occur on the same line. This allows, for example, the last letter of the word cool not to be chopped off.
Transparency support Also in windowless mode.
System selection colors Used for selecting text.
Automatic URL recognition Can check for a number of URL formats (for example, http:)
Microsoft Word edit UI compatibility Selection, cursor-keypad semantics.
Word standard EOP The end-of-paragraph mark (CR) can also handle carriage return/line feed (CR/LF) (carriage return, line-feed).
Plain-text as well as rich-text functionality Single-character format and single-paragraph format.
Single-line and multiline controls Truncate at first end-of-paragraph and no wordwrap.
Accelerator keys Accelerator keys are supported.
Password window style Password edit controls are supplied through EM_GETPASSWORDCHAR and EM_SETPASSWORDCHAR.
Scalable architecture To reduce instance size.
Windowless operation and interfaces This is provided through the ITextHost and ITextServices interfaces.
COM dual interfaces Text Object Model (TOM) interfaces.
CHARFORMAT2 Added font weight, background color, locale identifier, underline type, superscript and subscript (in addition to offset), disabled effect. For RTF roundtripping only, added amount to space between letters, twip size above which to kern character pair, animated-text type, various effects: font shadow/outline, all caps, small caps, hidden, embossed, imprint, and revised.
PARAFORMAT2 Added space before and after and Word line spacing. For RTF roundtripping only, added shading weight/style, numbering start/style/tab, border space/width/sides, tab alignment/leaders, various Word paragraph effects: RTL paragraph, keep, keep-next, page-break-before, no-line-number, no-widow-control, do-not-hyphenate, side-by-side.
More RTF roundtripping All of the Word FormatFont and FormatParagraph properties.
Code stability and stabilization Examples: parameter and object validation, function invariants, reentrancy guards, object stabilization.
Strong testing infrastructure Including extensive regressions tests.
Improved performance Smaller working set, faster load and redisplay times, etc.
C++ code base The code is written in C++, which provides a solid foundation on which to build Rich Edit 3.0.

With a few exceptions, Rich Edit 2.0 uses the same functions, structures, and messages as Rich Edit 1.0. Note, however, the following differences:

  • The name of the Rich Edit 1.0 window class is RichEdit. Rich Edit 2.0 has both ANSI and Unicode window classes—RichEdit20A and RichEdit20W, respectively. To specify the appropriate rich edit window class, use the RICHEDIT_CLASS constant, which the Richedit.h file defines depending on the definition of the UNICODE compile flag.
  • In Rich Edit 2.0, if you create a Unicode rich edit control (one that expects Unicode text messages), you must specify only Unicode data in any window messages sent to the control. Similarly, if you create an ANSI rich edit control, send only ANSI or double-byte character set (DBCS) data. You can use the IsWindowUnicode function to determine whether a rich edit control uses Unicode text messages. Note that the rich edit COM interfaces use Unicode text unless they encounter a code page argument.
  • Rich Edit 1.0 used CR/LF character combinations for paragraph markers. Rich Edit 2.0 used only a carriage return character ('\r'). Rich Edit 3.0 uses only a carriage return character but can emulate Rich Edit 1.0 in this regard.
  • Rich Edit 2.0 introduced the following new messages.
    Message Description
    EM_AUTOURLDETECT Enables or disables automatic URL detection.
    EM_CANREDO Determines whether there are any actions in the redo queue.
    EM_GETIMECOMPMODE Retrieves the current input method editor (IME) mode.
    EM_GETLANGOPTIONS Retrieves options for IME and Asian language support.
    EM_GETREDONAME Retrieves the type name of the next action in the redo queue.
    EM_GETTEXTMODE Retrieves the text mode or undo level.
    EM_GETUNDONAME Retrieves the type name of the next action in the undo queue.
    EM_REDO Redoes the next action in the redo queue.
    EM_SETLANGOPTIONS Sets options for IME and Asian language support.
    EM_SETTEXTMODE Sets the text mode or undo level.
    EM_SETUNDOLIMIT Sets the maximum number of actions in the undo queue.
    EM_STOPGROUPTYPING Stops grouping consecutive typing actions into the current undo action.
  • Rich Edit 2.0 introduced the following new structures.
    Structure Description
    CHARFORMAT2 Contains information about character formatting.
    PARAFORMAT2 Contains information about paragraph formatting.
  • Rich Edit versions 2.0 and 3.0 do not support the following messages that were previously supported in Asian-language versions of Rich Edit 1.0.

    EM_CONVPOSITION

    EM_GETIMECOLOR

    EM_GETIMEOPTIONS

    EM_GETPUNCTUATION

    EM_GETWORDWRAPMODE

    EM_SETIMECOLOR

    EM_SETIMEOPTIONS

    EM_SETPUNCTUATION

    EM_SETWORDWRAPMODE

Rich Edit Version 3.0

Rich Edit 3.0 is a single, scalable, world-wide DLL that offers high performance and compatibility with Word in a small package. New features for Rich Edit 3.0 include richer text, zoom, font binding, more powerful IME support, and rich complex script support (bidirectional, Indic, and Thai).

Rich Edit 3.0 includes the following features in addition to the features provided by Rich Edit Version 2.0.

Zoom The zoom factor is given by a ratio.
Paragraph numbering (single-level) Numeric, upper and lower alphabetic, or Roman numeral.
Simple tables Deleting and inserting rows is possible, but not resizing nor wrapping inside cells. With advanced typography turned on (see EM_GETTYPOGRAPHYOPTIONS), Rich Edit 3.0 can align columns centered or flush right, and include decimals. Cells are simulated by tabs, so text tabs and carriage returns are replaced by blanks.
Normal and heading styles Built-in normal style and heading styles 1 through 9 are supported by the EM_SETPARAFORMAT and Text Object Model (TOM) interfaces.
More underline types Dashed, dash-dot, dash-dot-dot, and dot underlining has been added.
Underline coloring Underlined text can be tagged with one of 15 document choices for underline colors.
Hidden text Marked by CHARFORMAT2 attribute. Handy for roundtripping (writing out to a file what was read in) of information that ordinarily should not be displayed.
More default hot keys These hot keys function the same as those in Word. For example, European accent dead keys (U.S. keyboards only). Number hot key (CTRL+L) cycles through numbering options available, starting with bullet.
HexToUnicode IME Allows a user to convert between hexadecimal and Unicode by using hot keys.
Smart quotes This feature is toggled on and off by CTRL+ALT+' for U.S. keyboards.
Soft hyphens For plain text, use 0xAD. For RTF, use \-.
Italics cursor In addition, the mouse cursor changes to a hand when over URLs.
Advanced typography option Rich Edit 3.0 can use an advanced typography option for line breaking and display (see EM_GETTYPOGRAPHYOPTIONS). This elegant option was added primarily to facilitate handling complex scripts (bidirectional, Indic, and Thai). In addition, a number of improvements occur for simple scripts. Examples are:
  • Center, right, decimal tabs
  • Fully justified text
  • Underline averaging, which provides a uniform underline even when adjacent text runs have different font sizes.
Complex script support Rich Edit 3.0 supports bidirectional (text with Arabic and/or Hebrew mixed with other scripts), Indic (Indian scripts like Devangari), and Thai text. For support of these complex scripts, the advanced typography and Uniscribe components are used.
Font binding Rich Edit 3.0 will automatically choose an appropriate font for characters that clearly do not belong to the current character set stamp. This is done by assigning character sets to text runs and associating fonts with those character sets. For more information, see Font Binding.
Charset-specific plain-text read/write options This allows reading a file using one charset, and writing with a different charset.
UTF-8 RTF This is recommended for cutting, copying, and pasting operations. This file format is more compact than ordinary RTF, faster, and compatible with Unicode.
Microsoft Office 9 IME support (IME98) This more powerful IME capability has been separated into an independent module. Features include:
  • Reconversion

    In the earlier versions, the user needed to delete the final string first and then type in a new string to get to the correct candidate. This new feature enables the user to convert the final string back to composition mode, thereby allowing easy selection of a different candidate string.

  • Document feed

    This feature provides IME98 with the text for the current paragraph, which helps IME98 perform more accurate conversion during typing.

  • Mouse operation

    This feature provides better control over the candidate and UI windows during typing.

  • Caret position

    This feature provides the current caret and line information, which IME98 uses to position UI windows (for example, a candidate list).

Active Input Method Manager (IMM) support Users can invoke the Active IMM object, which enables users to enter Asian characters on U.S. systems.
HexToUnicode support Users can convert between hexadecimal notation and Unicode by using hot keys.
More RTF roundtripping RTF text that is read in from a file will be written back out intact.
Improved 1.0 compatibility mode Rich Edit 3.0 can emulate Rich Edit 1.0 behavior. For example, it is possible to change between MBCS and Unicode character-position (cp) mappings. This feature emulates Rich Edit 1.0 in Windows 2000.
Increased freeze control The display can be frozen over multiple API calls and then unfrozen to display the updates.
Increased undo control Undo can be suspended and resumed (an IME requirement).
Increase/decrease font size Increases or decreases font size to one of six standard values (12, 28, 36, 48, 72, and 80 points).

Rich Edit Version 4.1

New features for Rich Edit 4.1 include hyphenation, page rotation, and Text Services Framework (TSF) support.

Rich Edit 4.1 includes the following features in addition to the features provided by Rich Edit Version 3.0.

Hyphenation Hyphenation is supported through the following APIs: HyphenateProc, EM_SETHYPHENATEINFO, and EM_GETHYPHENATEINFO.
Page rotation Top-to-bottom and bottom-to-top layout is supported through EM_SETPAGEROTATE and EM_GETPAGEROTATE.
Text Services Framework support
Additional IME support
Additional EM_SETEDITSTYLE settings Besides the TSF settings, there are new settings that exclude IMEs, set bidirectional text flow, use draftmode fonts, and more.
Additional EM_SETCHARFORMAT settings New flags allow the client to set the default font and font sizes for a given LCID or charset, to set the default font for the control, to prevent keyboard switching to match the font, and more.
Restricting input to ANSI text Using TM_SINGLECODEPAGE in EM_SETTEXTMODE prevents Unicode input from entering a Rich Edit control.
Unsupported RTF keyword notification EN_LOWFIRTF warns an application when there is an unsupported RTF keyword.
Additional language support Additional languages include Armenian, Divehi, Telugu, and others.
Improved table support Features include: wrapping within cells, improved handling via RTF, and improved navigation.
ES_VERTICAL The ES_VERTICAL windows style is supported.
WM_UNICHAR Notification support To send or post Unicode characters to ANSI windows, use WM_UNICHAR Notification. It is equivalent to WM_CHAR, but it uses (UTF)-32.
Tags What's this?: Add a tag
신고

'Projects > CoVNC' 카테고리의 다른 글

Msftedit.dll과 CF_RTF  (0) 2007.07.24
다중포멧 클립보드를 위한 글들...  (0) 2007.07.23
RTF를 사용하기 위하여  (0) 2007.07.23
소스코드 검색 사이트  (0) 2007.06.09
겨우 찾아낸 제대로 된 XML 파싱  (3) 2007.06.01
BSTR  (0) 2007.05.31