Linux VNC 초기 설정

Projects/CoVNC 2010.02.26 16:53 Posted by soulfree >동네청년<

항상 까먹을때가 되면 필요하다... 메모해둬야지...

 

rpm이나 yum으로 대충설치

/etc/sysconfig/vncservers 편집 -> VNCSERVERS="1:root"

chkconfig vncserver on

 

특히 chkconfig는 맨날 까먹는거 같다// 한동안 리눅스를 안썼떠니 ㅠㅠ;;

신고

[링크] DirectVNC 컴파일 작업관련 링크

Projects/CoVNC 2008.07.25 12:59 Posted by soulfree >동네청년<
http://armadillo.atmark-techno.com/howto/directvnc-build (일본어)

caps 에러 관련글
http://bugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=364264

http://kelp.or.kr/korweblog/stories.php?story=06/06/14/0618715

      diff 사용법
      http://wiki.kldp.org/wiki.php/DiffAndPatch

DirectFB 관련글 및 홈페이지
http://www.directfb.org/index.php?path=Main%2FDownloads&page=4
http://kldp.org/node/50569
http://alvastro.tistory.com/23 : 컴파일 옵션 설명
http://alvastro.tistory.com/27 : 설치기

DirectVNC 홈페이지
http://www.adam-lilienthal.de/directvnc/download.html

gtk
http://alvastro.tistory.com/tag/gtk
http://kldp.org/KoreanDoc/html/GtkTutorial/GtkTutorial-3.html

ARM 보드에 DirectFB 포팅 관련글
http://kldp.org/node/78399

신고

[링크] VNC 모음

Projects/CoVNC 2008.07.14 14:24 Posted by soulfree >동네청년<
http://faq.gotomyvnc.com/cgi-bin/fom?_recurse=1&file=113

또는

http://stromberg.dnsalias.org/~strombrg/vnc.html
신고

협업 VNC stable 버전

Projects/CoVNC 2008.05.23 17:49 Posted by soulfree >동네청년<
최종 버전입니다.
졸업작품으로 진행하였으며
올해 제출할 학회지 논문 및 IFOST 논문 발표를 위해서와
이번학기 저희 교수님 담당의 졸업반 학생들의 졸업작품에 사용될 예정이라 안정화시켜 배포합니다.

협업 VNC의 개발 목적, 개발배경, 사용방법, 결론, 비교등은 첨부하는 논문과 프리젠테이션 파일을 참조해주세요... 또 작성하려니 손아파서;;
협업 VNC의 테스트 환경은 다음과 같습니다.

HOST PC에 VMware를 이용하여 Guest PC가 4대 존재하는 환경을 구성
각  Guest PC는 NAT를 이용한 사설 네트워크로 연결됨
HOST PC 사양 : 인텔 펜티엄 E2140, 램 2GB, 기가비트랜, 윈도우즈XP SP3
Guest PC 사양 : VMware 6.0으로 구성된 Guest PC, 램 256MB, 윈도우즈XP SP3, 페도라코어8

협업 VNC 서버 

협업 VNC JavaViewer 클라이언트
참고 논문

졸업작품 프리젠테이션

졸업작품 심사 요청서




신고

Ultra VNC 1.0.2

Projects/CoVNC 2008.04.17 16:44 Posted by soulfree >동네청년<
신고
TAG UltraVNC, VNC
VNC는 아시는 분들은 잘아시는 원격데스크탑과 같은 원격제어도구입니다.

VNC는 RealVNC, TightVNC, UltraVNC 등 여러 버전으로 배포중이구요... 서버와 클라이언트의 클립보드를 공유하는 기능을 제공하고 있지만 문자열만 공유가 가능합니다.

2006년 2학기 졸업작품을 위해 문자열 뿐만아닌 이미지도 공유가 가능하도록 확장하였습니다.

서버는 플랫폼에 의존적이지만(윈도우즈) 클라이언트는 자바가 동작하는 어느 GUI 시스템이든지 상관없습니다.

사실 리눅스 X-window 시스템은 클립보드 메니저가 존재하지 않아 이러한 시도가 무의미해지는 경우가 많았는데 요즘은 윈도우즈의 단일 클립보드 메니저와 OLE 객체의 통일함의 편리성과 강력함을 따르게 되어 이러한 구현이 가치있게 되었습니다.

다음은 윈도우즈 서버와 리눅스 클라이언트를 제가 확장한 VNC 시스템을 통해 클립보드를 이용한 이미지 공유를 한 예입니다.


사용자 삽입 이미지
사용자 삽입 이미지
신고

error LNK2001: unresolved external symbol __imp__PropertySheetA@4

Projects/CoVNC 2007.09.17 20:26 Posted by soulfree >동네청년<

출처 : http://www.codeguru.com/forum/archive/index.php/t-106735.html
Add comctl32.lib to Project/Settings/Link/Library object modules.

신고

error LNK2001: unresolved external symbol _main

Projects/CoVNC 2007.09.17 20:25 Posted by soulfree >동네청년<

출처 : http://jof4002.net/?%C7%C1%B7%CE%B1%D7%B7%A1%B9%D6%C6%C1/%C4%C4%C6%C4%C0%CF%BF%A1%B7%AFLNK2001

음... 별게 아니라 안쓸려고 했는데... -_-;
error LNK2001: unresolved external symbol _main

질문란에도 잊을만하면 올라오는 질문이더군요. 이 에러가 발생하는 경우는 크게 두가지가 있습니다.


--------------------------------------------------------------------------------

1. API로 프로그래밍을 처음 하시는 분들이 흔히 하는 실수 같습니다.

윈도우에서 프로그램은 크게 두가지로 분류할 수 있습니다. 도스처럼 console 창에 텍스트만을 출력하는 console 프로그램과 흔히 쓰는 GUI를 가진 프로그램이 있죠. (에구 이걸 뭐라고 해야 하나... 그냥 GUI 프로그램이라고 쓸께요)

Visual C++에서 프로젝트를 만들 때 Win32 Application : WinMain 함수에서 시작하게 되는 GUI 프로그램 Win32 Console Application : main 함수에서 시작하는 console 프로그램 이 두가지가 있습니다.

제목에 적은 것 같은 에러가 나는 분들은 대부분 GUI 프로그램을 만드시려고 하고 WinMain은 만드셨는데, 프로젝트를 만들 때 console application을 선택하신겁니다. 반대로 WinMain이 없다고 에러가 나오면 GUI 프로젝트를 선택하고서 main 함수를 작성하신 것이겠죠.

자, 그럼 어떻게 해결하느냐. 설정을 바꿔주면 됩니다. 프로젝트 세팅(Alt + F7)에서 Link탭을 누르면 제일 아래에 에디트 박스가 보이죠? 잘 보면 /subsystem:console 이라고 써있을 겁니다. 이걸 /subsystem:windows로 바꿔주세요. (또는 상황에 따라서 그 반대로 해줄 수도 있겠죠) 이 옵션의 역할은 링커에게 있어서 이 프로그램이 어떤 함수로부터 시작해야 하는지를 알려주는 겁니다. 이 옵션이 console이라면 main을, windows라면 WinMain을 찾아서 그 함수에서부터 프로그램이 시작하게 하는거죠.

아시겠죠? 잘 이해가 안되면 질문 달아주세요. 성실히 답변해드리겠습니다. 그리고 Jeffrey Ritcher 아저씨가 쓴 Programming Applications for Windows 4th. 를 보면 잘 나와 있으니 참고하세요.


--------------------------------------------------------------------------------

2. ATL에서 컨트롤을 만들 때 이 에러가 날 수 있습니다.

디버그에서는 잘 컴파일이 되던게 릴리즈로 빌드하면 저 에러가 날 수 있습니다. ATL에서는 생성되는 코드의 크기를 최소화 하기 위해서 CRT (C RunTime) 함수의 일부를 제한하고 있기 때문이죠(정확히 말하자면 start up 코드를 넣지 않습니다). 그런데 프로젝트에서 특정 C 함수를 사용하면 ATL에서 제한한 CRT의 기능이 필요해지고 따라서 에러가 나는겁니다.

이 해결책도 간단합니다. a. 프로젝트 세팅에서 predefined keyword를 찾아서 _ATL_MIN_CRT를 지워주세요. b. 초기화가 필요한 CRT 함수를 사용하지 마세요. -_-; MSDN에 따르면 strcmp대신 lstrcmp를 사용하는 식으로 피해갈 수 있다고 합니다.

자세한건 MSDN에서 _ATL_MIN_CRT를 찾아보세요. (색인에서 입력하면 나옵니다.)

신고

탭스 업로드 3.0

Projects/CoVNC 2007.08.03 14:05 Posted by soulfree >동네청년<


탭스 업로드 컴포넌트입니다.


무료 컴포넌트 중에 퍼포먼스가 좋은편이라고 알려져있죠.


주요 특징입니다.


64비트(x64) 탭스 업로드 (버전 3.0)

이제 64비트 환경(Windows Server 2003 x64)에서도 탭스 업로드 서버 컴포넌트를 사용할 수 있습니다. 64비트 전용으로 제작되어 64비트 IIS에서 최상의 성능을 제공합니다

윈도우 비스타를 지원하는 TABSFileup 액티브액스 컨트롤 (버전 3.0)

비스타의 IE7은 보호 모드(Protect Mode)로 동작하기 때문에 액티브액스 컨트롤에 상당한 제약을 주므로 상당수의 기존 컨트롤들이 정상 동작하지 않거나 실행조차 되지 않습니다. TABSFileup은 보호 모드의 표준 프로그래밍 규약을 준수해서 동작하도록 개발되어 비스타에서도 원할하게 사용할 수 있습니다.


업로드 바이러스 검출(버전 2.3)

Sophos for TABS Upload 안티바이러스 프로그램을 이용해 파일 업로드시 전송된 파일에 대해 바이러스를 검사할 수 있습니다. 서버에 업로드 되는 파일에 대해 실시간으로 바이러스를 검출할 수 있는 기능이 제공되어 보다 안전한 업로드 서버를 구성할 수 있습니다. Sophos for TABS Upload는 업로드시 검사 기능 외에 기본적으로 윈도우 서버를 바이러스 감염으로 부터 보호할 수 있는 기능이 탑재되어 있으므로 서버 보호용으로 별도의 안티 바이러스를 구입할 필요가 없습니다.

프리웨어

TABS Upload는 프리웨어 입니다. 누구나 자유롭게 사용할 수 있습니다. TABS Upload를 사용하시려면 고객등록을 하신 후 등록키를 발급 받아 TABS Upload에 입력하시면 정상적으로 사용할 수 있습니다. [고객등록]에서 등록을 먼저 하십시오. 고객등록 후 [무료 등록키 받기]를 통해서 키를 받으십시오. 키를 e-mail로 받으신 후 해당 키를 제품에 입력십시오.

Upload 컴포넌트와 TABSFileup 컨트롤은 자유롭게 설치하여 사용할 수 있습니다. 그러나 다음과 같은 경우에는 사용할 수 없습니다.

  1. Upload 컴포넌트와 TABSFileup 컨트롤을 임의의 제품 기능에 포함 또는 변형시켜 판매하거나 유통시킬 수 없습니다. 이 경우 구매를 해야 합니다.(Redistribution License, Site License 구매)
  2. Upload 컴포넌트와 TABSFileup 컨트롤을 탭스랩(주)의 허가 없이 판매 또는 수익모델로 사용할 수 없습니다.

탭스 업로드 3.0

신고

html을 클립보드에 복사

Projects/CoVNC 2007.07.25 03:25 Posted by soulfree >동네청년<

rich text의 경우 richedit.h만 include해주면 MFC가 아닌 Win32 API를 사용하는 프로그램에서도CF_RTF를 사용할 수 있었지만 HTML은 아직 발견하지 못했네요.
다음 예는 msdn에 올라와있는 예제입니다만,,, MFC에서만 사용가능 한 것으로 생각됩니다...
RegisterClipboardFormat("HTML Format"); 함수를 사용했고 이것을 사용해 setClipboardData()함수를 호출 하였지만 클립보드에 html 데이터가 들어가지 못합니다...
그나저나 빨리 CF_HTML 을 사용할 수 있도록 하는 방법을 찾아야 하는데,,, 잠도 못자고 죽겠네여....


How To Add HTML Code to the Clipboard by Using Visual C++


 When you use this function to copy an HTML code fragment to the clipboard, it might look like the following:

    char *html = 
        "<b>This is a test</b><hr>"
        "<li>entry 1"
        "<li>entry 2";
    CopyHTML(html);


Additional Note

Using an approach that sends HTML code to the clipboard might be especially beneficial for Office Automation clients. For example, if you have an Automation client that needs to generate formatted data for cells in Microsoft Excel or paragraphs in Microsoft Word, you could build the data in HTML code, send it to the clipboard, and then paste it into the application. By using this technique, you could reduce the number of out-of-process calls to the Automation client.


REFERENCES

To learn more about the specifics of the HTML Clipboard format, see the topic "HTML Clipboard Format" in the MSDN:

신고

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

error LNK2001: unresolved external symbol _main  (1) 2007.09.17
탭스 업로드 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

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

다중포멧 클립보드를 위한 글들...

Projects/CoVNC 2007.07.23 23:59 Posted by soulfree >동네청년<
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=217&MAEULNo=8&no=21266&ref=21266

http://pds2.egloos.com/pds/1/200609/23/17/MyWord(0).zip

http://blog.empas.com/swguru/10848091
신고

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

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
겨우 찾아낸 제대로 된 XML 파싱  (3) 2007.06.01

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

소스코드 검색 사이트

Projects/CoVNC 2007.06.09 02:44 Posted by soulfree >동네청년<
1. Koders
 - http://www.koders.com/
사용자 삽입 이미지




2. Google Code Search
 - http://www.google.com/codesearch/
사용자 삽입 이미지






3. Krugle
 - http://www.krugle.com/
사용자 삽입 이미지



4. Codase
 - http://www.codase.com/
사용자 삽입 이미지

신고

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

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

겨우 찾아낸 제대로 된 XML 파싱

Projects/CoVNC 2007.06.01 16:19 Posted by soulfree >동네청년<

================================================
안준철님 정말 감사합니다.
================================================
 출처 : 블로그 > Jon's 블로그
 http://blog.naver.com/junechol/140022015860

xml에 있는 데이터를 액셀 파일로 저장하려고 한다.

화면에 액셀이 뜨지는 않고 조용히 xls 파일이 만들어져야 한다.

이를 위해서는 excel automation을 써야 한다.

또한 xml을 읽어들이는 작업은 msxml 컴포넌트를 쓴다.


비주얼 스투디오에서 끌어오기 하는 방식으로 automation을 하기도 한다.

숱한 참조문서에서 그렇게들 한다.

나도 그렇게 했었다.

왜 되는지는 모르고 되니까 좋아했다.


여기서는 #import로 automation하는 방법을 쓴다.

이게 이해하기도 쉽고, 소스파일 갯수와 크기가 줄어든다.

샘플 프로그램은 window console 기반 api 프로그램이다.

(뭐 MFC가 싫지는 않지만, 프로그래머를 바보로 만든다.)


두가지 컴포넌트를 쓴다.

1. excel.exe (액셀을 깔아야 한다. 당연히...)

2. msxml2.dll (msxml 2.6 이상의 버전을 깔면 된다. ms에서 다운가능)


완전한 소스를 올리기는 그러니 요약해서 커멘트하겠다.


------------------------------------------------------


// printf 와 strxxx 함수들을 쓰려면 이것들은 써야한다.

#include <stdio.h>
#include <tchar.h>


// #import 가 뭐하는 거냐하면...

// 아무것도 안하고 #import "msxml2.dll" 만 한다음에 컴파일해 보라.

// msxml.tlh 와 msxml.thi 가 debug 디렉토리에 생긴다.

// 이 파일들이 automation의 마술을 한다.


#import "msxml2.dll"
using namespace MSXML2;
// 뒤에 보면 여전히 MSXML2::xxx 라고 쓰고 있다. ambiguity가 발생하기 때문이다.


// excel은 절대경로로 import 할 수밖에 없을게다.

#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL" \
   rename("RGB", "MsoRGBType")
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\excel.exe"\
   rename("DialogBox", "ExcelDialogBox") \
   rename("RGB", "MsoRGBType") \
   rename("CopyFile", "ExcelCopyFile") \
   no_dual_interfaces
using namespace Excel;


// ---------소스 생략----------

// main 과 doTranslate만 보면 된다.


int main(int argc, char* argv[])
{
  char excelFilename[1024];


// 실행시 파라미터 까보기 생략


// CoInitialize는 automation (COM interface 사용) 에는 필수다.

  HRESULT hr;
  hr = CoInitialize(NULL);


  printf("opening %s using MSXML2\n", argv[1]);



// xxxPtr 은 신비한 타입이다.

// xxxPtr.func() 도 있고 xxxPtr->func() 도 된다. (두가지는 다른 용도로 쓰인다.)

// smart pointer라는 것인데, _COM_SMARTPTR_TYPEDEF() 매크로를 볼 것.

  IXMLDOMDocument2Ptr pXMLDoc;


// IXMLDOMDocument2Ptr::CreateInstance 는 _com_ptr_t 템플릿 클래스의 멤버함수다.

// (comip.h 참조)

// 이건 CoCreateInstance를 불러서 COM object instance를 만든다.


// "Msxml2.DOMDocument" 가 어디서 나온건지 궁금하면...

// regedit.exe를 실행해서 HKEY_CLASSES_ROOT 아래에서 찾아보라.

// 이 스트링으로부터 CLSID 값을 받아낼 수 있다.

// 나중에 나오는 "Excel.Application"도 마찬가지

  hr = pXMLDoc.CreateInstance(L"Msxml2.DOMDocument");


// 여기서 리턴된 값이 S_OK 가 아니면 CoCreateInstance가 실패한 것이다.
  if (hr == S_OK)
  {

// _variant_t 는 VARIANT 타입의 불편함을 덜어주는 클래스다. (comutil.h 참조)

// #import 하면 이런 comxxx.h 헤더들이 다 include 된 것이다.
    _variant_t vFilename;
    vFilename.SetString(argv[1]);


// 이번에는 xxxPtr->func() 을 사용했다.

// 이건 xxx 의 함수다. 즉, 이 경우 IXMLDOMDocument2의 함수다.

// msxml2.tlh 에 사용할 수 있는 함수들이 뭐가 있는지 볼 수 있다.

// 문제는 함수 프로토타입만 있지, 뭐에 쓰는 함수인지는 없다는 건데...

// 이건 해당 컴포넌트의 매뉴얼을 (있다면) 참조하는 수밖에 없다.

// 다행히 msxml 이나 excel 은 그나마 msdn 문서가 좀 있다.


// IXMLDOMDocument2::load 는 xml 파일을 읽는 함수다.

// xml 파일이 조금만 잘못되어 있어도 에러가 난다.

// 아래쪽 else 의  GetparseError()->get_reason() 해서 어지간한 이유는 알 수 있다.

    if (pXMLDoc->load(vFilename))
    {
      doTranslate(pXMLDoc, excelFilename);
    }
    else
    {

// _bstr_t는 BSTR을 쓰기 편하게 만든 클래스임.(comutil.h 참조)
      _bstr_t bsReason;
      pXMLDoc->GetparseError()->get_reason(bsReason.GetAddress());

// printf 의 %S는 wchar 스트링을 찍는다.(%s 아님)
      printf("%S\n", bsReason);
    }

// CreateInstance() 했다면 반드시 Release() 또는 Detach() 해야한다.
    pXMLDoc.Release();
  }
  else
  {
    printf("Cannot create DOMDocument instance.\nDid ");
  }

// CoInitialize()를 부른 프로그램은 끝내기 전에 반드시 CoUninitialize() 해야 한다.

  CoUninitialize();
  return 0;
}


void doTranslate(IXMLDOMDocument2Ptr pXMLDoc, const char *excelFilename)
{
  HRESULT hr;
  int i, j;


// 왜 하필 _ApplicationPtr 로 CreateInstance를 하는 걸까?

// 물론 문서에서 그렇게 하라고 하기 때문이다.

// 다음과 같은 짓을 해보면 hr == E_NOINTERFACE 가 된다.

//     _WorksheetPtr sheet;
//     hr = sheet.CreateInstance(L"Excel.Application");


// 이게 뭘 뜻하느냐 하면, _Worksheet 인터페이스는 Excel.Application COM object의

// IUnknown 인터페이스에 물어보면 모르는 인터페이스란 얘기.

// 즉, 다른 인터페이스를 통해 간접적으로 액세스하는 인터페이스라는 말이다.


  _ApplicationPtr app;
  hr = app.CreateInstance(L"Excel.Application");

  if (hr == S_OK)
  {

// excel 버전 보기
    _variant_t var;
    var = app->GetVersion();

// 문서에 sheet 하나만 달랑 있게 하기

    app->PutSheetsInNewWorkbook(1);


// _Worksheet 인터페이스 얻기 (3단계, 다른 수도 있다. 찾아보라.)

    WorkbooksPtr books = app->GetWorkbooks();
    _WorkbookPtr  book = books->Add();
    _WorksheetPtr sheet = book->GetActiveSheet();


// 다시 xml로 돌아가자.

// IXMLDOMNode 는 msxml의 모든 구성요소들이 지원하는 인터페이스다.

// 심지어 IXMLDOMDocument2도 이걸 상속받았다.

// 별로 지원하는 함수가 많지 않다. 주로 parent/child/sibling 뒤지기만 한다.

// 혹시 노드의 attribute값을 보려면, 즉 <TAG type="dummy"> 에서 dummy를 읽으려면

// IXMLDOMElement를 써야 한다.


    _bstr_t bsGimml("GIMML");

// selectSingleNode() 는 name 이 맞는 첫번째 child 노드를 리턴한다. 유용함
    MSXML2::IXMLDOMNodePtr nodeGimml = pXMLDoc->selectSingleNode(bsGimml); 
    _bstr_t bsElements("Elements");
    MSXML2::IXMLDOMNodePtr nodeElements = nodeGimml->selectSingleNode(bsElements);


// selectSingleNode()에서 에러가 나면 리턴값이 NULL 이다.
    if (nodeElements)
    {
      bool error = false;

// 차일드 노드 루프돌기

// GetchildNodes() 함수는 IXMLDOMNodeList 인터페이스를 리턴하는데

// 여기다 대고 nextNode()를 하면 차일드를 다 뒤질 수 있다.
      MSXML2::IXMLDOMNodeListPtr elementlist = nodeElements->GetchildNodes();

// 리스트 갯수를 알아야 루프돌기 편할 것이다.
      int elementCount = elementlist->Getlength();

      /* scan for ALPHA_STRING elements */
      for (i=0; i<elementCount; i++)
      {

// nextNode()는 첫번째 차일드 노드부터 리턴한다.

// 그러니 루프내에서 무조건 부르고 본다.
        MSXML2::IXMLDOMElementPtr anElement = elementlist->nextNode();

        /* node name check (shoud be "Element") */

// 노드명 받기 <TAG type="dummy"> 에서는 TAG가 노드명
        _bstr_t bsNodename = anElement->GetnodeName();
        _bstr_t bsElement("Element");
        if (bsNodename != bsElement) // _bstr_t 비교는 연산자로 가능
        {
          printf("node name is %S. <Element> expected\n", bsNodename);
          error = true;
          break;
        }
               
        /* get id string */
        _bstr_t bsId("id");

// attribute 보기
        _variant_t varElementId = anElement->getAttribute(bsId);
        printf("%S\n", varElementId.bstrVal);

        /* format check (only "AG_FORMAT_ALPHA_STRING" will be processed) */
        _bstr_t bsAlphaString("AG_FORMAT_ALPHA_STRING");
        _bstr_t bsFormat("format");
        _variant_t varFormat = anElement->getAttribute(bsFormat);
        _bstr_t bsFormatValue(varFormat.bstrVal, true);
        if (bsFormatValue != bsAlphaString)
        {
          printf(" Skip: element %S is %S format.\n", varElementId.bstrVal, varFormat.bstrVal);
          continue;
        }


        /* get data */
        MSXML2::IXMLDOMNodeListPtr dataList = anElement->GetchildNodes();
        int dataCount = dataList->Getlength();

        if (dataCount == 0) continue;

        WCHAR wzData[10][1024] = {0,};

        for (j=0; j<dataCount; j++)
        {
          MSXML2::IXMLDOMElementPtr dataElement = dataList->nextNode();

          /* get id value */
          int id = j;
          _bstr_t bsDataId("id");
          _variant_t varDataId = dataElement->getAttribute(bsDataId);
          if (varDataId.vt == VT_BSTR)
          {

// atoi 의 wchar 버전
            id = _wtoi(varDataId.bstrVal);
            if (id < 0 || id >= 10)
            {
              error = true; break;
            }
          }


// 이 함수 내부는 생략했다.

// wzData 에 wchar 스트링을 채워 넣는 함수다.

         if (ucs2StringFromData(dataElement, wzData[id]) == false)
         {
            error = true; break;
         }
        }
               
        /* error in getting data string... stop. */
        if (error) break;


// 다시 액셀로 돌아가자.

// 아까 _Worksheet 까지는 준비해두었다.

// 액셀에 데이터를 넣을 때는 Range로 하나의 셀을 지정한 후에 값을 넣는다.

        /* write a element to excel sheet */
        char colAlphabet;
        int  rowInt;
        char cellString[20]; /* cell id like "Z11" */
        RangePtr cell;
   
        rowInt = i + 2; /* excel cell begins with 1. and added one more for header */
        colAlphabet = 'B';

// cell을 지정하기 위해서 "E13" 형태의 스트링을 만든다.
        sprintf(cellString, "%c%d", colAlphabet, rowInt);


// cell 하나를 선택하고, 값을 넣는다.   
        cell = sheet->GetRange(cellString);
        cell->PutValue2(varElementId.bstrVal);

        for (j=0; j<10; j++)
        {
          colAlphabet = 'C' + j;
          sprintf(cellString, "%c%d", colAlphabet, rowInt);
          cell = sheet->GetRange(cellString);
          cell->PutValue2(wzData[j]);
        }
  
      }

      if (!error)
      {
        /* save if no error */
        char fullpath[1024];
        sprintf(fullpath, "%s\\%s", curDir, excelFilename);

// SaveAs()를 통해 xls 저장.

// Save()를 부르면 파일 다이얼로그가 뜬다. 짜증날 것임.
        sheet->SaveAs(fullpath);
      }
    }
    else
    {
      _bstr_t bsReason;
      pXMLDoc->GetparseError()->get_reason(bsReason.GetAddress());
      printf("%S\n", bsReason);
   }

// 액셀 프로그램을 닫는다.

// 액셀이 안보이지만 프로그램이 떠 있다. 그러므로 Quit()을 해야 한다.
    app->Quit();

// 아까 말했듯이 CreateInstance 한놈은 반드시 Release() 해야 한다.
    app.Release();
  }
  else
  {
    printf("Cannot create Excel application instance.\n");
  }

}


------------------------------------------------


p.s.

혹시 excel 에 "="로 시작하는 스트링을 넣고 싶다면, 앞에 ' 를 붙여넣어라.

' 는 저장되지 않는다.

저장되기는 하는데... GetText() 해보면 '는 빠져 있다.

즉, 액셀이 특수문자로 간주하여 셀 value에서는 제외된다.

신고

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

RTF를 사용하기 위하여  (0) 2007.07.23
소스코드 검색 사이트  (0) 2007.06.09
겨우 찾아낸 제대로 된 XML 파싱  (3) 2007.06.01
BSTR  (0) 2007.05.31
[Win32 API] DialogBoxParam  (0) 2007.05.20
MSXML 사용법 요약  (0) 2007.05.05

BSTR

Projects/CoVNC 2007.05.31 21:48 Posted by soulfree >동네청년<

COM 은 무조건 2바이트를 기본으로 하는 유니코드형 문자만을 사용합니다.
이를 엑세스하기 위한 기본 자료형은 wchat_t 형입니다.
이는 1바이트 문자형인 char 에 대응하는 것입니다.

보통은 wchar_t *을 BSTR 로 형정의(typedef)해서 사용하는데,
아무래도 원시적인 문자열에 대한 포인트에 불과하므로, AnsiString 같은 편리성이 없습니다.
그래서 빌더는 WideString형을 제공하지만,
경우에 따라서 BSTR 문자열을 쉽게 제어할 수 있는 클래스가 필요하기도 합니다.
(COM이나 COM이 아니거나 간에 또는 VC++과 호환을 맞추기 위해)
이 경우 comutil.h 에 정의되어 있는 COM 제어 지원용 _bstr_t 형 클래스를  사용하는 경우가 있습니다.
_bstr_t 는 AnsiString 과 유사하게 2바이트 유니코드 문자열을 다룰 수 있도록 해주는
C++에서만 제공되는 클래스입니다.


COM 은 무조건 2바이트를 기본으로 하는 유니코드형 문자만을 사용합니다.
이를 엑세스하기 위한 기본 자료형은 wchat_t 형입니다.
이는 1바이트 문자형인 char 에 대응하는 것입니다.

보통은 wchar_t *을 BSTR 로 형정의(typedef)해서 사용하는데,
아무래도 원시적인 문자열에 대한 포인트에 불과하므로, AnsiString 같은 편리성이 없습니다.
그래서 빌더는 WideString형을 제공하지만,
경우에 따라서 BSTR 문자열을 쉽게 제어할 수 있는 클래스가 필요하기도 합니다.
(COM이나 COM이 아니거나 간에 또는 VC++과 호환을 맞추기 위해)
이 경우 comutil.h 에 정의되어 있는 COM 제어 지원용 _bstr_t 형 클래스를  사용하는 경우가 있습니다.
_bstr_t 는 AnsiString 과 유사하게 2바이트 유니코드 문자열을 다룰 수 있도록 해주는
C++에서만 제공되는 클래스입니다.


 bstr_t a(L"고구려");
 bstr_t b("goguryur");

 bstr_t c = a+b;

 wchar_t* p1 = (wchar_t*)c;//오퍼레이터
 char*    p2 = (char*)c;      //오퍼레이터

 int size1 = wcslen(p1);
 int size2 = strlen(p2);



출처: http://kylix.borlandforum.com/


 bstr_t a(L"고구려");
 bstr_t b("goguryur");

 bstr_t c = a+b;

 wchar_t* p1 = (wchar_t*)c;//오퍼레이터
 char*    p2 = (char*)c;      //오퍼레이터

 int size1 = wcslen(p1);
 int size2 = strlen(p2);


_bstr_t에서는 아래와 같은 형변환 오퍼레이터를 사용하실 수 있습니다.

operator const wchar_t*() const  throw(); operator wchar_t*() cosnt throw(); operator const char*()


CString에서는 문자열을 가저올때, (LPCTSTR)로 형변환을 하듯이, _bstr_t형 변수를 형변환해서 이용해 주시면 됩니다.

_bstr_t bs;

...

sprintf(ch, "%s", (const char*)bs);

strcpy(ch, (const char*)bs);

신고

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

소스코드 검색 사이트  (0) 2007.06.09
겨우 찾아낸 제대로 된 XML 파싱  (3) 2007.06.01
BSTR  (0) 2007.05.31
[Win32 API] DialogBoxParam  (0) 2007.05.20
MSXML 사용법 요약  (0) 2007.05.05
Microsoft XML Core Service(MSXML)  (0) 2007.05.05

[Win32 API] DialogBoxParam

Projects/CoVNC 2007.05.20 19:45 Posted by soulfree >동네청년<

DialogBoxParam



   원 형       INT_PTR DialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplateName,

                                  HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);


   설 명       대화상자 대부분이 비슷하고 일부분만 조금 다른 대화상자가 여러 개 필요한 경우가 있다.

                 예를 들어 저장을 위한 파일명과 읽기를 위한 파일명을 입력받는 대화상자 둘은 안내 메시지 정도만 다를 뿐 필요한 컨트롤이나 동작방식은 거의 유사하다. 에러 메시지 출력 대화상자도 에러 메시지 정도만 다르고 나머지는 거의 유사할 것이다. 이런 경우는 하나의 대화상자만 만들어 두고 필요할 때마다 대화상자의 동작방법을 조금씩 바꿔가면 사용하면 된다.


그 해결방법으로 가장 쉽게 떠오르는 것은 전역변수를 사용하는 것이다. 대화상자를 부르기 전에 전역변수에 값을 대입하고 대화상자는 이 전역변수의 값에 따라 조금씩 다르게 동작하도록 프로그래밍하면 된다. 이 방법도 물론 원론적으로 문제가 없으며 실전에서도 자주 활용되지만 대화를 위해 전역변수를 남발하는 것은 별로 바람직하지 않다. 좀 더 좋은 방법은 부모 윈도우가 대화상자를 호출할 때 파라미터를 전달하고 대화상자는 파라미터를 해석해서 동작 방법을 결정하는 방법이다. 이때 DialogBoxParam 함수가 사용된다.


함수 원형은 DialogBox 와 거의 유사하되 제일 뒤에 dwInitParam 이라는 인수가 하나 더 추가되어 있다. 이 값은 대화상자를 생성할 때 WM_INITDIALOG 의 lParam 으로 전달된다. 파라미터는 32비트의 정수값이지만 포인터를 전달할 수도 있으므로 구조체나 메모리 핸들같은 큰 데이터도 얼마든지 전달할 수 있다.

 

참조 함수    DialogBox

신고
TAG C++, Win32 API

MSXML 사용법 요약

Projects/CoVNC 2007.05.05 21:21 Posted by soulfree >동네청년<
Summary
This sample application shows how to use MSXML 4.0 to create an XML document using DOM. This application illustrates the following DOM APIs: createProcessingInstruction, insertBefore, createNode, appendChild, createElement, createAttribute, setNamedItem, createComment, createCDATASection, createDocumentFragment, setAttribute, and save.

Our objective is to use MSXML 4.0 DOM and create the XML document that looks like as below:
<?xml version="1.0" encoding="UTF-8"?>
<f:Feedback xmlns:f='www.PerfectXML.com/Feedback'>
	<f:Record f:RecID="231">
		
		<!-- The Feedback Text -->
		<![CDATA[
	PerfectXML is now by far the best source on the Web 
	for up-to-date news on Web services and XML. Congrats!]]>

		<f:Recd>
			Thu Jul 11 2002
		</f:Recd>
		
		<f:Time>
			09:01:40
		</f:Time>

		<f:From>
			Roger
		</f:From>

		<f:Client f:Browser='IE' f:IP='123.123.123.123'/>

	</f:Record>
</f:Feedback>

Steps
Steps that we followed to create this application:
1. Start Visual C++ 6.0 and create a new Win32 Console Application project.
2. Add the following lines in the stdafx.h:
#include <TCHAR.H>
#include <stdio.h>
#include <time.h>

#import "msxml4.dll"
//      ^^^^^^^^^^^^
// If this import statement fails, you need to install MSXML 4.0 SP1 from:
//
// http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml

#include <msxml2.h>
//       ^^^^^^^^^^
// If this include statement fails, you need to install MSXML 4.0 SP1 SDK from:
//
// http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml
//
// You also need to add the include file and library search path
// to Visual C++'s list of directories (Tools > Options... > Directories).

using namespace MSXML2;

inline void EVAL_HR( HRESULT _hr ) 
   { if FAILED(_hr) throw(_hr); }

#define TEMP_SIZE  _MAX_PATH       // size of short buffer
static _TCHAR   szTemp[TEMP_SIZE]; // multipurpose buffer on stack
static DWORD    dwLen;
3. The above lines import the MSXML 4 type library, include the MSXML header file, defines a tiny utility function to check the HRESULT value, and declares some global variables.
4. The main function looks like as below:
int main(int argc, char* argv[])
{
	try
	{
		EVAL_HR(CoInitialize(NULL));

		//	Make sure that MSXML 4.0 is installed
		if (!isMSXMLInstalled())
			return -1;

		CreateAndSaveXMLDocument();
	}
	catch(...)
	{//exception handling
	}
	
	_ftprintf(stdout, "\n\nPress Enter to continue...");
	getchar();
	CoUninitialize();
	return 0;
}
5. The main function begins by calling the utility function isMSXMLInstalled to make sure MSXML 4.0 is installed. This function is discussed in previous two samples, so we'll not repeat the explaination here.

Next, the main function calls CreateAndSaveXMLDocument function which actually creates and saves the XML document. This function is saved in utils.h file. Let's look at this function:
6. The function begins by creating an instance of MSXML DOMDocument object:
void CreateAndSaveXMLDocument()
{
	try
	{
		IXMLDOMDocument2Ptr pXMLDoc = NULL;
		
		//	Create MSXML DOM object
		EVAL_HR(pXMLDoc.CreateInstance("Msxml2.DOMDocument.4.0"));
The first thing we do in this function is create the XML declaration line (<?xml version="1.0" encoding="UTF-8"?>)
		//	---------------------------------------------
		//	Step 6.1: Creating the Processing Instruction
		IXMLDOMProcessingInstructionPtr pPI = NULL;

		pPI = pXMLDoc->createProcessingInstruction
			("xml", "version='1.0' encoding='UTF-8'");

		_variant_t vNullVal;
		vNullVal.vt = VT_NULL;
		pXMLDoc->insertBefore(pPI, vNullVal);
The second parameter to the insertBefore function call above is passed as NULL, which instructs new node to be inserted at the end of the child list. Since we do not have any nodes in the tree yet, the XML declaration statement becomes the very first child.

Next, we create the document root element:
		//	---------------------------------------------
		//	Step 6.2: Creating the Root Element
		IXMLDOMNodePtr pRootNode= NULL; 
		_variant_t varNodeType((short)MSXML2::NODE_ELEMENT);

		pRootNode= pXMLDoc->createNode(varNodeType, 
			_T("f:Feedback"), _T("www.PerfectXML.com/Feedback"));

		pXMLDoc->appendChild(pRootNode);


The first child under the root Feedback node is the Record element:
		//	---------------------------------------------
		//	Step 6.3a: Creating Record Child Element
		IXMLDOMNodePtr pRecNode= NULL; 
		pRecNode = pRootNode->appendChild(pXMLDoc->createElement(_T("f:Record")));

		//	Step 6.3b: Creating RecID attribute for the Record element
		IXMLDOMAttributePtr pRecIdAttr = NULL;
		pRecIdAttr = pXMLDoc->createAttribute(_T("f:RecID"));
		pRecIdAttr->nodeTypedValue = _T("231");
		pRecNode->attributes->setNamedItem(pRecIdAttr);
The above lines of code create the Record element and an attribute named RecID.

The following lines of code create the comments and CDATA section:
		//	---------------------------------------------
		//	Step 6.4: Creating the Comments node
		_bstr_t bstrCommentText = _T(" The Feedback Text ");
		pRecNode->appendChild(pXMLDoc->createComment(bstrCommentText));


		//	---------------------------------------------
		//	Step 6.5: Creating the CDATA section
		_bstr_t bstrCDATAText = 
			_T("\n\tPerfectXML is now by far the best source on the Web"
				" \n\tfor up-to-date news on Web services and XML. Congrats!\n");

		pRecNode->appendChild(pXMLDoc->createCDATASection(bstrCDATAText));
The following lines of code illustrate an important concept of document fragments. Many times it is required to create and append a set of nodes at various places in the document. Instead of creating and appending each node every time, we can create a document fragment; and then just append that in the tree wherever the set of nodes is required.
		//	---------------------------------------------
		//	Step 6.6: Addding the Recd, Time, and From nodes
		//	Illustrating the document fragment feature (IXMLDOMDocumentFragment)
		IXMLDOMDocumentFragmentPtr pFragment = NULL;
		IXMLDOMElementPtr pTempNode = NULL;
		pFragment = pXMLDoc->createDocumentFragment();

		pTempNode = pXMLDoc->createElement(_T("f:Recd"));
		pTempNode->nodeTypedValue = _T("Thu Jul 11 2002");
		pFragment->appendChild(pTempNode );
		
		pTempNode = pXMLDoc->createElement(_T("f:Time"));
		pTempNode->nodeTypedValue = _T("09:01:40");
		pFragment->appendChild(pTempNode );

		pTempNode = pXMLDoc->createElement(_T("f:From"));
		pTempNode->nodeTypedValue = _T("Roger");
		pFragment->appendChild(pTempNode );

		//	Attach the fragment to the DOM tree
		pRecNode->appendChild(pFragment);
Here we are creating three nodes as part of the fragment. We can now use this fragment anywhere else also in the code to add these three nodes in the tree.

Finally, we create the Client child element and its two attributes, and then save the document:
		//	Step 6.7: Creating "Client" element and its two attributes
		IXMLDOMElementPtr pClientElem= NULL; 
		pClientElem = pXMLDoc->createElement(_T("f:Client"));
		pClientElem->setAttribute(_T("f:Browser"), _T("IE"));
		pClientElem->setAttribute(_T("f:IP"), _T("123.123.123.123"));

		pRecNode->appendChild(pClientElem);

		//	Done, now save the document

		pXMLDoc->save(_T("c:\\Feedback.xml"));
	}
	catch(...)
	{//Exception handling
	}
	
}
Here is the text from the ReadMe.TXT file included with the code download for this sample application:
==================================================
       CONSOLE APPLICATION : DOM_CreateXMLDoc
==================================================

	Sample code to illustrate using MSXML 4.0 (SP1) DOM 
	to create an XML document. This application illustrates 
	the following DOM methods: 
	createProcessingInstruction, insertBefore, createNode, appendChild,
	createElement, createAttribute, setNamedItem, createComment, 
	createCDATASection, createDocumentFragment, setAttribute, and save.

	The created document is saved as c:\Feedback.xml

--------------------------------------------------
	Copyright (C) 2002 http://www.PerfectXML.com

	Created: July 12, 2002

	Author: PerfectXML.com Team (msxml@PerfectXML.com)
---------------------------------------------------

///////////////////////////////////////////////////


More Information
신고

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

BSTR  (0) 2007.05.31
[Win32 API] DialogBoxParam  (0) 2007.05.20
MSXML 사용법 요약  (0) 2007.05.05
Microsoft XML Core Service(MSXML)  (0) 2007.05.05
C++을 사용해 바이트 배열에 저장된 DIB정보를 DIB메모리 블럭 만들기  (2) 2007.03.31
DIB/DDB 구조  (0) 2007.03.30
TAG MSXML

Microsoft XML Core Service(MSXML)

Projects/CoVNC 2007.05.05 21:13 Posted by soulfree >동네청년<
DOM or Document Object Model is a W3C specification that defines a standard programming API to build, navigate, update and transform XML documents. MSXML supports DOM Level 2.

With DOM, the parser reads the input XML document and builds the hierarchical tree representation of this document in the memory. Once the complete document is loaded into the memory, the parser DOM methods allow to navigate and edit the document. This method is well-suited if you need random access to the document or need to update the document. However, DOM is not a viable choice for huge XML documents. Refer to the parser SDK documentation for more help on how to use MSXML DOM.       Tip: Chapter 2 (Document Object Model in MSXML) in the book XML Application Development with MSXML 4.0 covers MSXML DOM features in great details.

Let's now look at how to use MSXML 4.0 DOM in JavaScript, VBScript (ASP Pages), Visual Basic, Visual C++, C# (.NET) and VB.NET (early binding and late binding).

The following example(s) simply load a local XML document using DOM and spits out the document's contents.

JavaScript

<script language="JScript">
<!--
	try
	{
		var objDOMDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
		objDOMDoc.async = false;
		if (objDOMDoc.load("c:\\po.xml"))
		{
			alert(objDOMDoc.xml);
		}
		else
		{
			alert("Error: " + objDOMDoc.parseError.reason);
		}
	}
	catch(e)
	{
		alert("Error: " + e);
	}
//-->
</script>
			

VBScript (ASP Pages)

<%
	Option Explicit
	Response.CacheControl = "no-cache"
	Response.AddHeader "Pragma", "no-cache"
	Response.Expires = -1
	Response.Buffer = TRUE

	Dim objDOMDoc
	On Error Resume Next

	Set objDOMDoc = Server.CreateObject("Msxml2.DOMDocument.4.0")
	If Err Then
		Response.ContentType = "text/html"
		Response.Write "Error: " & Err.Description
		Err.Clear()
		Response.End
	End If
	objDOMDoc.async = False
	If objDOMDoc.load (Server.MapPath("po.xml")) Then
		Response.ContentType = "text/xml"
		Response.write objDOMDoc.xml
	Else
		Response.ContentType = "text/html"
		Response.write "Error: " & objDOMDoc.parseError.reason
	End If	
	
%>

Visual Basic

Start Visual Basic 6.0 and create a new Standard EXE project. Add reference (Project | Reference) to Microsoft XML v4.0, double click on the form and write following code under the Form_Load() method:
    Dim objDOMDoc As New MSXML2.DOMDocument40
    
    objDOMDoc.async = False
    If objDOMDoc.Load("c:\po.xml") Then
        MsgBox objDOMDoc.xml
    Else
        MsgBox "Error: " & objDOMDoc.parseError.reason
    End If
    
    Set objDOMDoc = Nothing

Visual C++

Start Visual C++ 6.0, create a new project of type Win32 Console Application and name the project as MSXMLDOMTest. Click OK and select A Simple Application from the next screen and then click on Finish button and then OK. Open MSXMLDOMTest.cpp file and update the file with following code:
#include "stdafx.h"
#include "stdio.h"
#import "msxml4.dll"
using namespace MSXML2;

inline void EVAL_HR( HRESULT _hr ) 
   { if FAILED(_hr) throw(_hr); }

int main(int argc, char* argv[])
{
   try 
   {
		IXMLDOMDocumentPtr objDOMDoc;

		EVAL_HR(CoInitialize(NULL)); 
		EVAL_HR(objDOMDoc.CreateInstance("Msxml2.DOMDocument.4.0"));

		_variant_t varXml("C:\\po.xml");
		_variant_t varOut((bool)TRUE);

		objDOMDoc->async = false;
		varOut = objDOMDoc->load(varXml);
		
		if ((bool)varOut == FALSE)
		 throw(0);
		
		printf(_bstr_t(objDOMDoc->xml)) ;
		printf("\n\nPress ENTER to continue...\n");
		getchar();
		return 0;
	}
	
	catch(...)
	{
		printf("Exception occurred");
		printf("\n\nPress ENTER to continue...\n");
		getchar();
		return -1;
	}

	CoUninitialize();   
}

C# .NET

Note that the .NET framework contains a namespace called System.Xml that contains various classes to work with XML. The following method (using MSXML in .NET applications using COM Interop) should only be used if it is required to quickly migrate (or reuse) the existing code.

The following code is written using .NET Framework Beta 2.


It's really easy to use MSXML with Visual Studio .NET. Simply by Adding Reference to Microsoft XML, v4.0 from the COM tab, creates a runtime callable wrapper that we can use to import the MSXML classes into our .NET application and use then as any other .NET class.

Let's do the same thing using the command prompt tools:

Start the DOS Command prompt (or better, Visual Studio .NET Command Prompt by clicking on Start | Programs | Microsoft Visual Studio .NET | Visual Studio .NET Tools) and type the following command at the prompt:

    >tlbimp msxml4.dll /out:MSXML4DotNet.dll

The type library importer (tlbimp) command line tool builds a proxy class that contains the necessary information used to create the runtime callable wrapper. You might see some warnings and can safely ignore them for now. The above command creates a file named MSXML4DotNet.dll. Start notepad and write the following C# code:
using System;
using MSXML4DotNet;

public class CSharpMSXML
{
	public static void Main()
	{
		try
		{
			DOMDocument40 objDOMDoc = new DOMDocument40();

			objDOMDoc.async = false;

			if (objDOMDoc.load(@"c:\po.xml"))
			{
				Console.WriteLine(objDOMDoc.xml);
			}

			else
			{
				Console.WriteLine("Parse Error: " 
					+ objDOMDoc.parseError.reason 
					+ objDOMDoc.parseError.srcText);
			}
			
		}
		catch(Exception e)
		{
			Console.WriteLine("Error: " + e.Message);
		}
		Console.ReadLine();
	}
}


Save the above file as msxmlcsharp.cs and complile it using the following command on the DOS Command Prompt:

    >csc.exe msxmlcsharp.cs /r:MSXML4DotNet.dll

Run msxmlcsharp.exe. This example illustrated using unmanaged COM code from within .NET C# application using early binding, let's see an example of using COM component through late binding.With the following approach (late binding), it is not required to run tlbimp.exe (or add a reference) to create a proxy class:
using System;
using System.Reflection;

public class CSharpMSXML2
{
	public static void Main()
	{
		try
		{
			Type typDOM = Type.GetTypeFromProgID("Msxml2.DOMDocument.4.0");

			object objDOMDocDisp = Activator.CreateInstance(typDOM);

			object [] param = new object[1];
			param[0] = false;

			typDOM.InvokeMember("async", BindingFlags.SetProperty, 
						null, objDOMDocDisp, param); 

			param[0] = @"c:\po.xml";

			object loadResult = null;

			loadResult = typDOM.InvokeMember("load", BindingFlags.InvokeMethod, 
						null, objDOMDocDisp, param);
			if ((bool)loadResult == true)
			{
				String s = (String)typDOM.InvokeMember("xml", 
							BindingFlags.GetProperty, 
							null, objDOMDocDisp, new object[]{});
				Console.WriteLine(s);
			}
			else
			{
				object pe = typDOM.InvokeMember("parseError", 
						BindingFlags.GetProperty, 
						null, objDOMDocDisp, new object[]{});

				String s = (String)typDOM.InvokeMember("reason", 
						BindingFlags.GetProperty, 
						null, pe, new object[]{});

				Console.WriteLine("Parse Error: " + s);
			}
		}
		catch(Exception e)
		{
			Console.WriteLine("Error: " + e.Message);
		}
		Console.ReadLine();
	}
}


Save the above file as latebinding.cs and run following command on the command prompt to complie the above C# code:

    >csc.exe latebinding.cs

Run latebinding.exe.

VB .NET

Assuming that you have already created the MSXML 4.0 Runtime Callable Wrapper DLL using tlbimp (as described above), here is the VB .NET code equivalent to above C# code:
Option Explicit On
Option Strict On

Imports System
Imports MSXML4DotNet

Public Class VBNETMSXML
	Shared Sub Main
		Try
			Dim objDOMDoc as DOMDocument40 = New DOMDocument40()
			With objDOMDoc
				.async = False
			
				If (.load ("c:\po.xml")) Then
					Console.WriteLine (.xml)
				Else
					Console.WriteLine ("Parse Error: " & _
						.parseError.reason & _
						.parseError.srcText)
				End If
			End With
		Catch e as Exception
			Console.WriteLine ("Error: " & e.Message)
		End Try
		Console.ReadLine()
	End Sub
End Class

Save the above file as vbnetmsxml.vb and complile it using the following command on the DOS Command Prompt:

    >vbc.exe vbnetmsxml.vb /r:MSXML4DotNet.dll

Run vbnetmsxml.exe.


Let's look at another small example to load an XML document and search for a specific node.

Here is the source XML document (c:\1.xml):
<?xml version="1.0"?>
<customers>

 <row ID="1">
  <CustomerID>ALFKI</CustomerID>
  <CompanyName>Alfreds Futterkiste</CompanyName>
  <ContactName>Maria Anders</ContactName>
 </row>

 <row ID="2">
  <CustomerID>ANATR</CustomerID>
  <CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
  <ContactName>Ana Trujillo</ContactName>
 </row>

</customers>
Let's now look at Visual Basic code to load the above XML document using MSXML DOM and then search for an element based on the CustomerID.

Start Visual Basic 6.0, create a Standard EXE Project, add reference (Project | References) to Microsoft XML, v4.0 (MSXML4.DLL), double click on the form and write following code inside the Form_Load method:
Dim objDOMDoc As New MSXML2.DOMDocument40
Dim ResultNode As MSXML2.IXMLDOMNode

objDOMDoc.async = False

If objDOMDoc.Load("c:\1.xml") Then
    Set ResultNode = objDOMDoc.selectSingleNode("/customers/row/CustomerID[.='ANATR']")
    
    'Uncomment the following line to try out unmatching element
    'Set ResultNode = objDOMDoc.selectSingleNode("/customers/row/CustomerID[.='PPPPP']")
    If ResultNode Is Nothing Then
        MsgBox "Not found!"
    Else
        MsgBox "Found: " & vbNewLine & ResultNode.parentNode.xml
    End If
    
    'Searching based on Attribute
    Set ResultNode = objDOMDoc.selectSingleNode("/customers/row[@ID='1']")
    
    'Uncomment the following line to try out unmatching element
    'Set ResultNode = objDOMDoc.selectSingleNode("/customers/row[@ID='99']")
    If ResultNode Is Nothing Then
        MsgBox "Not found!"
    Else
        MsgBox "Found: " & vbNewLine & ResultNode.xml
    End If

Else
    MsgBox "Error: " & objDOMDoc.parseError.reason
End If
The above code loads the XML document (c:\1.xml). If the load succeeds, we use the selectSingleNode method to search for an element by passing the XPath expression as its parameter. We then use the Visual Basic Is Nothing clause to check if the matching node was found or not.

MSXML DOM Resources Around The Web

신고

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

[Win32 API] DialogBoxParam  (0) 2007.05.20
MSXML 사용법 요약  (0) 2007.05.05
Microsoft XML Core Service(MSXML)  (0) 2007.05.05
C++을 사용해 바이트 배열에 저장된 DIB정보를 DIB메모리 블럭 만들기  (2) 2007.03.31
DIB/DDB 구조  (0) 2007.03.30
CListBox  (0) 2007.02.21