m_ctHtmlSrcText.SetWindowTextW( m_sHtml ); // populate the Editbox
//------------------------------------------------
// update the HTML source box with changes from HTML Editor
//
void CEditHtmlDlg::SyncSrcToHtml()
{
m_ctlEditHtml.GetDocumentHTML( m_sHtml );
int nLine= m_ctHtmlSrcText.GetFirstVisibleLine(); // remember cur pos
m_ctHtmlSrcText.LockWindowUpdate(); // avoid some flashing
m_ctHtmlSrcText.SetWindowTextW( m_sHtml );
m_ctHtmlSrcText.LineScroll(nLine, 0);
m_ctHtmlSrcText.UnlockWindowUpdate();
m_fSrcNeedsSync= false;
}
//------------------------------------------------
// update the Browser view changes from source text box
void CEditHtmlDlg::SyncHtmlToSrc()
{
//------- all this to locate the scroll position...
long nOffsetTop;
IHTMLDocument2* pDoc;
BOOL fRet= m_ctlEditHtml.GetDHtmlDocument( &pDoc );
IHTMLElement* pBody;
pDoc->get_body( &pBody );
IHTMLElement2* pBody2;
pBody->QueryInterface (IID_IHTMLElement2, (void**)&pBody2);
pBody2->get_scrollTop( &nOffsetTop );
//------- update the HTML
m_ctHtmlSrcText.GetWindowTextW( m_sHtml );
m_ctlEditHtml.SetDocumentHTML( m_sHtml );
m_ctlEditHtml.LockWindowUpdate(); // avoid some flashing
AwaitReady( 2 ); // CHtmlEditCtrl takes time for "document complete"
//------- now scroll back to saved position
IHTMLWindow2* pWin;
pDoc->get_parentWindow( &pWin );
pWin->scrollTo(0,nOffsetTop);
m_ctlEditHtml.UnlockWindowUpdate();
m_fHtmlNeedsSync= false;
}
Updating the source text window was basically a no-brainer, but handling the HTML editor update was a bit trickier. Re-loading the HTML into the CHtmlEditCtrl causes it to redisplay at the top -- a
very rude thing to do to a user. I had to use the
IHTMLElement2 get_scrollTop for the document body to obtain the current scroll position and the
IHTMLWindow2 scrollTo function to restore it after reloading the HTML.
void CEditHtmlDlg::OnEnChangeHtmlsrc()
{
m_dwLastEnChangeTick= GetTickCount();
m_fHtmlNeedsSync= true;
}
//--------------------------------------------
// I used a StartTimer() in OnInit Dialog
// to execute this 10 times per second
//
void CEditHtmlDlg::OnTimer(UINT_PTR nIDEvent)
{
if ( m_fSrcNeedsSync ) {
SyncSrcToHtml(); // update source view, set m_fSrcNeedsSync false
}
else { // check to see if HTML has changed
CString sCurHtml;
m_ctlEditHtml.GetDocumentHTML( sCurHtml );
if ( sCurHtml != m_sHtml ) {
m_sHtml= sCurHtml;
m_fSrcNeedsSync= true; // update on next pass through
}
}
if ( m_fHtmlNeedsSync ) {
// here, we wait until the user stops typing (1 second)...
if( GetTickCount() > m_dwLastEnChangeTick + M_MsDelayBeforeUpdate ) {
SyncHtmlToSrc(); // update HTML view, set m_fHtmlNeedsSync false
}
}
CDialog::OnTimer(nIDEvent);
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (3)
Commented:
Author
Commented:In playing around with copy-to-clipboard operations, I read that Microsoft states that it always places a "valid HTML fragment" on the clipboard. My guess is that they have some interesting technology in place to create valid HTML from invalid HTML.
There is no standard for how a browser should "correct" invalid HTML. I recall a long argument in the Browsers TA about this. Some say that "standards based browsers" are more correct when they just break (and show garbage) than Microsoft's technique of attempting to find a reasonable way to render the bad HTML.
Commented: