After searching lot on the internet we have found following code to get only body part of the web page loaded onto web browser control
IPIEHTMLDocument2 *pHTMLDocument;
IPIEHTMLElement* pBodyElement;
CComPtr<IDispatch> spDispDoc;
HRESULT res = m_spWebBrowser2->get_Document(&spDispDoc);
if(SUCCEEDED(res))
{
spDispDoc->QueryInterface( __uuidof(IPIEHTMLDocument2), (void**)&pHTMLDocument);
WCHAR szText[256];
DISPID id;
OLECHAR FAR* szTemp;
// store "body"
szTemp = szText;
StringCchPrintf(szText, 256, L"body", id);
// get the body
pHTMLDocument->GetIDsOfNames(IID_NULL, &szTemp, 1, LOCALE_USER_DEFAULT, &id);
VARIANT varResult;
varResult.vt = VT_DISPATCH;
VARIANT FAR *pVarResult = &varResult;
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
pHTMLDocument->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, pVarResult, NULL, NULL);
BSTR bodyValue;
if( NULL != pVarResult->pdispVal)
{
pVarResult->pdispVal->QueryInterface(IID_IPIEHTMLElement, (void**)&pBodyElement);
pBodyElement->get_innerHTML(&bodyValue);
}
}
But now how we get the remaining head and other tag document text from the loaded web page,
even we have tried passing "head" string to the GetIDsOfNames() method and it passes fail value, so we are struck.
Please provide us the method to access/ extract entire web page content in windows mobile 6.0
Thanks,
Ramanand Bhat.
void CBrowserWindow::ExtractWebPageDoc()
{
HRESULT hrResult = E_FAIL;
IDispatch *pIDisp = NULL;
IPIEHTMLDocument3 *pIHTMLDocument = NULL;
IPIEHTMLElementCollection *pHTMLElementcol = NULL;
IPIEHTMLImgElement *pHTMLImgElement = NULL;
hrResult = m_spIWebBrowser2->get_Document( &pIDisp);
if (NULL != pIDisp)
{
hrResult = pIDisp->QueryInterface( __uuidof(IPIEHTMLDocument3), (void**)&pIHTMLDocument);
if( NULL != pIHTMLDocument)
{
IPIEHTMLElement* pElement = NULL;
CComBSTR pHTMLElement;
hrResult = pIHTMLDocument->get_documentElement( &pElement);
if (SUCCEEDED(hrResult))
{
pElement->get_innerHTML(&pHTMLElement.m_str);
SaveToHTMLFile( pHTMLElement);
}
hrResult = pIHTMLDocument->get_images( &pHTMLElementcol);
if (NULL != pHTMLElementcol)
{
CComBSTR strImage;
VARIANT vtBase, vtIndex;
long pHTMLElementCollectionLength = 0;
VariantInit( &vtBase);
vtIndex.vt = VT_UINT;
hrResult = pHTMLElementcol->get_length( &pHTMLElementCollectionLength);
for (int ilen = 0; ilen < (int)pHTMLElementCollectionLength ; ilen++)
{
vtIndex.lVal = ilen;
pIDisp = NULL;
hrResult = pHTMLElementcol->item( vtBase, vtIndex , &pIDisp);
if (NULL != pIDisp)
{
hrResult = pIDisp->QueryInterface( __uuidof(IPIEHTMLImgElement), (void**)&pHTMLImgElement);
if (NULL != pHTMLImgElement)
//CComQIPtr<IPIEHTMLImgElement> imgElement( pIDisp);
//imgElement->get_src( &strImage.m_str); //I get it here :)
pHTMLImgElement->get_src( &strImage.m_str);
}
}
}
}
}
}
Above mentioned code gets the entire web page content in windows mobile devices.
Related
I have 2 bugs in methods that save products to local storage (when a user adds them to 'favorites').
The code is part of Angular service, but it can be read without this reference also.
First bug: Sometimes, when a user saves a product to favorites, not one, but multiple products get stored.
Second bug: When I store too many products, I get an error saying that the storage is full (it's full because I parse JSON wrongly, so unwanted additional backslashes are added).
This is the codepan (you can see the result in the console): https://codepen.io/mandy555/pen/dyPVGxj
storage;
storageKeys;
x;
i = 0;
saveId;
arr;
normalArr;
productInStore;
productsInStore;
idsInStore;
newIds;
newProducts;
favorites;
storageAvailable(type) {
try {
this.storage = window[type];
this.x = '__storage_test__';
this.storage.setItem('x', this.x);
this.storage.removeItem('x');
return true;
}
catch (e) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(this.storage && this.storage.length !== 0);
}
}
storeFavorite(product = '', productId = '') {
productId = String(productId);
this.normalArr = [];
if (this.storageAvailable('localStorage')) {
this.storage = window.localStorage;
if (!this.storage.getItem('favorites_id')) {
this.saveId = productId;
this.normalArr.push(product);
} else {
this.productsInStore = JSON.parse(this.storage.getItem('favorites_product'));
if (this.storage.getItem('favorites_id').indexOf(',') === -1) {
this.arr = [this.storage.getItem('favorites_id')];
this.normalArr = this.productsInStore;
} else {
this.arr = this.storage.getItem('favorites_id').split(',');
this.normalArr = this.productsInStore;
}
if (!this.arr.includes(productId) && productId !== '') {
this.saveId = this.storage.getItem('favorites_id') + ',' + productId;
this.normalArr.push(product);
} else {
this.saveId = this.storage.getItem('favorites_id');
}
}
this.storage.setItem('favorites_id', this.saveId);
this.storage.setItem('favorites_product', JSON.stringify(this.normalArr));
} else {
this.storage = null;
}
}
deleteFavorite(productId = '') {
productId = String(productId);
this.normalArr = [];
if (this.storageAvailable('localStorage')) {
this.storage = window.localStorage;
if (this.storage.getItem('favorites_id') && this.storage.getItem('favorites_product')) {
this.productsInStore = JSON.parse(this.storage.getItem('favorites_product'));
if (this.storage.getItem('favorites_id').indexOf(',') === -1) {
this.storage.clear();
} else {
this.idsInStore = this.storage.getItem('favorites_id').split(',');
this.newIds = this.idsInStore.filter(id => {
return id !== productId;
});
this.newproducts = this.productsInStore.filter(product => {
return String(product.id) !== productId;
});
this.newIds = this.newIds.join();
this.storage.setItem('favorites_id', JSON.stringify(this.newIds));
this.storage.setItem('favorites_product', JSON.stringify(this.newproducts));
}
}
} else {
this.storage = null;
}
}
The first problem was that I forgot to assign storage to local storage. The second solution was to save x and not JSON.stringify(x) in the local storage, since x was already a string. The corrected version is here:
https://codepen.io/mandy555/pen/dyPVGxj
I want to extract some data like " email addresses " .. from table which are in PDF file and use this email addresses which I extract to send email to those people.
What I have found so far through searching the web:
I have to convert the PDF file to Excel to read the data easily and use them as I want.
I find some free dll like itextsharp or PDFsharp.
But I didn't find any snippet code help to do this in C#. is there any solution ?
You absolutely do not have to convert PDF to Excel.
First of all, please determine whether your PDF contains textual data, or it is scanned image.
If it contains textual data, then you are right about using "some free dll". I recommend iTextSharp as it is popular and easy to use.
Now the controversial part. If you don't need rock solid solution, it would be easiest to read all PDF to a string and then retrieve emails using regular expression.
Here is example (not perfect) of reading PDF with iTextSharp and extracting emails:
public string PdfToString(string fileName)
{
var sb = new StringBuilder();
var reader = new PdfReader(fileName);
for (int page = 1; page <= reader.NumberOfPages; page++)
{
var strategy = new SimpleTextExtractionStrategy();
string text = PdfTextExtractor.GetTextFromPage(reader, page, strategy);
text = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(text)));
sb.Append(text);
}
reader.Close();
return sb.ToString();
}
//adjust expression as needed
Regex emailRegex = new Regex("Email Address (?<email>.+?) Passport No");
public IEnumerable<string> ExtractEmails(string content)
{
var matches = emailRegex.Matches(content);
foreach (Match m in matches)
{
yield return m.Groups["email"].Value;
}
}
Using bytescout PDF Extractor SDK we can be able to extract the whole page to csv as below.
CSVExtractor extractor = new CSVExtractor();
extractor.RegistrationName = "demo";
extractor.RegistrationKey = "demo";
TableDetector tdetector = new TableDetector();
tdetector.RegistrationKey = "demo";
tdetector.RegistrationName = "demo";
// Load the document
extractor.LoadDocumentFromFile("C:\\sample.pdf");
tdetector.LoadDocumentFromFile("C:\\sample.pdf");
int pageCount = tdetector.GetPageCount();
for (int i = 1; i <= pageCount; i++)
{
int j = 1;
do
{
extractor.SetExtractionArea(tdetector.GetPageRect_Left(i),
tdetector.GetPageRect_Top(i),
tdetector.GetPageRect_Width(i),
tdetector.GetPageRect_Height(i)
);
// and finally save the table into CSV file
extractor.SavePageCSVToFile(i, "C:\\page-" + i + "-table-" + j + ".csv");
j++;
} while (tdetector.FindNextTable()); // search next table
}
public void Convert(string fileNames) {
int pageCount = 0;
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(fileNames);
pageCount = reader.NumberOfPages;
string ext = System.IO.Path.GetExtension(fileNames);
//string[] outfiles = new string[pageCount];
//Excel.Application app = new Excel.Application();
//app.Workbooks.Add("");
CSVExtractor extractor = new CSVExtractor();
//string outfilePDF1 = fileNames.Replace((System.IO.Path.GetFileName(fileNames)), (System.IO.Path.GetFileName(fileNames).Replace(".pdf", "") + "_rez" + ".csv"));
string outfilePDFExcel1 = fileNames.Replace((System.IO.Path.GetFileName(fileNames)),
(System.IO.Path.GetFileName(fileNames).Replace(".pdf", "") + "_rez" + ".xls"));
extractor.RegistrationName = "demo";
extractor.RegistrationKey = "demo";
string folderName = #"C:\Users\Dafina\Desktop\PDF_EditProject\PDF_EditProject\PDFs";
string pathString = System.IO.Path.Combine(folderName, System.IO.Path.GetFileName(fileNames).Replace(".pdf", "")) + "-CSVs";
System.IO.Directory.CreateDirectory(pathString);
for (int i = 0; i < pageCount; i++)
{
string outfilePDF = fileNames.Replace((System.IO.Path.GetFileName(fileNames)),
(System.IO.Path.GetFileName(fileNames).Replace(".pdf", "") + "_" + (i + 1).ToString()) + ext);
extractor.LoadDocumentFromFile(outfilePDF);
//string outfile = fileNames.Replace((System.IO.Path.GetFileName(fileNames)),
// (System.IO.Path.GetFileName(fileNames).Replace(".pdf", "") + "_" + (i + 1).ToString()) + ".csv");
string outfile = fileNames.Replace((System.IO.Path.GetFileName(fileNames)),
(System.IO.Path.GetFileName(fileNames).Replace(".pdf", "") + "-CSVs\\" + "Sheet_" + (i + 1).ToString()) + ".csv");
extractor.SaveCSVToFile(outfile);
}
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
Console.WriteLine("Excel is not properly installed!!");
return;
}
Excel.Workbook xlWorkBook;
object misValue = System.Reflection.Missing.Value;
xlWorkBook = xlApp.Workbooks.Add(misValue);
string[] cvsFiles = Directory.GetFiles(pathString);
Array.Sort(cvsFiles, new AlphanumComparatorFast());
//string[] lista = new string[pageCount];
//for (int t = 0; t < pageCount; t++)
//{
// lista[t] = cvsFiles[t];
//}
//Array.Sort(lista, new AlphanumComparatorFast());
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
for (int i = 0; i < cvsFiles.Length; i++)
{
int sheet = i + 1;
xlWorkSheet = xlWorkBook.Sheets[sheet];
if (i < cvsFiles.Length - 1)
{
xlWorkBook.Worksheets.Add(Type.Missing, xlWorkSheet, Type.Missing, Type.Missing);
}
int sheetRow = 1;
Encoding objEncoding = Encoding.Default;
StreamReader readerd = new StreamReader(File.OpenRead(cvsFiles[i]));
int ColumLength = 0;
while (!readerd.EndOfStream)
{
string line = readerd.ReadLine();
Console.WriteLine(line);
try
{
string[] columns = line.Split((new char[] { '\"' }));
for (int col = 0; col < columns.Length; col++)
{
if (ColumLength < columns.Length)
{
ColumLength = columns.Length;
}
if (col % 2 == 0)
{
}
else if (columns[col] == "")
{
}
else
{
xlWorkSheet.Cells[sheetRow, col + 1] = columns[col].Replace("\"", "");
}
}
sheetRow++;
}
catch (Exception e)
{
string msg = e.Message;
}
}
int k = 1;
for (int s = 1; s <= ColumLength; s++)
{
xlWorkSheet.Columns[k].Delete();
k++;
}
releaseObject(xlWorkSheet);
readerd.Close();
}
xlWorkBook.SaveAs(outfilePDFExcel1, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal,
misValue, misValue, misValue, misValue, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive,
misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkBook);
releaseObject(xlApp);
var dir = new DirectoryInfo(pathString);
dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;
dir.Delete(true);
}
Probably the Best code would be to use Third party dll
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
string pathToPdf = #"D:\abc\abc.pdf";
string pathToExcel = Path.ChangeExtension(pathToPdf, ".xls");
SautinSoft.PdfFocus f = new SautinSoft.PdfFocus();
f.ExcelOptions.ConvertNonTabularDataToSpreadsheet = false;
// 'true' = Preserve original page layout.
// 'false' = Place tables before text.
f.ExcelOptions.PreservePageLayout = true;
// The information includes the names for the culture, the writing system,
// the calendar used, the sort order of strings, and formatting for dates and numbers.
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-US");
ci.NumberFormat.NumberDecimalSeparator = ",";
ci.NumberFormat.NumberGroupSeparator = ".";
f.ExcelOptions.CultureInfo = ci;
f.OpenPdf(pathToPdf);
if (f.PageCount > 0)
{
int result = f.ToExcel(pathToExcel);
// Open the resulted Excel workbook.
if (result == 0)
{
System.Diagnostics.Process.Start(pathToExcel);
}
}
}
}
}
I'm having problems displaying my Haxe game in IE9. It's actually not displaying at all. We tracked down the issue inside the compiled JS file for Haxe and found out that the problem is within the haxe.HTTP API.
There are certain things that need to be checked and done for IE9 to work with xmlhttprequests. These things were not done in the Haxe API.
This is the http class without my fix:
this.url = url;
this.headers = new List();
this.params = new List();
this.async = true;
};
$hxClasses["haxe.Http"] = haxe.Http;
haxe.Http.__name__ = ["haxe","Http"];
haxe.Http.prototype = {
setParameter: function(param,value) {
this.params = Lambda.filter(this.params,function(p) {
return p.param != param;
});
this.params.push({ param : param, value : value});
return this;
}
,request: function(post) {
var me = this;
me.responseData = null;
var r = this.req = js.Browser.createXMLHttpRequest();
var onreadystatechange = function(_) {
if(r.readyState != 4) return;
var s;
try {
s = r.status;
} catch( e ) {
s = null;
}
if(s == undefined) s = null;
if(s != null) me.onStatus(s);
if(s != null && s >= 200 && s < 400) {
me.req = null;
me.onData(me.responseData = r.responseText);
} else if(s == null) {
me.req = null;
me.onError("Failed to connect or resolve host");
} else switch(s) {
case 12029:
me.req = null;
me.onError("Failed to connect to host");
break;
case 12007:
me.req = null;
me.onError("Unknown host");
break;
default:
me.req = null;
me.responseData = r.responseText;
me.onError("Http Error #" + r.status);
}
};
if(this.async) r.onreadystatechange = onreadystatechange;
var uri = this.postData;
if(uri != null) post = true; else {
var $it0 = this.params.iterator();
while( $it0.hasNext() ) {
var p = $it0.next();
if(uri == null) uri = ""; else uri += "&";
uri += encodeURIComponent(p.param) + "=" + encodeURIComponent(p.value);
}
}
try {
if(post) r.open("POST",this.url,this.async); else if(uri != null) {
var question = this.url.split("?").length <= 1;
r.open("GET",this.url + (question?"?":"&") + uri,this.async);
uri = null;
} else r.open("GET",this.url,this.async);
} catch( e1 ) {
me.req = null;
this.onError(e1.toString());
return;
}
if(!Lambda.exists(this.headers,function(h) {
return h.header == "Content-Type";
}) && post && this.postData == null) r.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var $it1 = this.headers.iterator();
while( $it1.hasNext() ) {
var h1 = $it1.next();
r.setRequestHeader(h1.header,h1.value);
}
r.send(uri);
if(!this.async) onreadystatechange(null);
}
,onData: function(data) {
}
,onError: function(msg) {
}
,onStatus: function(status) {
}
,__class__: haxe.Http
};
and this is the code WITH the fix:
haxe.Http = function(url) {
this.url = url;
this.headers = new List();
this.params = new List();
this.async = true;
};
$hxClasses["haxe.Http"] = haxe.Http;
haxe.Http.__name__ = ["haxe","Http"];
haxe.Http.prototype = {
setParameter: function(param,value) {
this.params = Lambda.filter(this.params,function(p) {
return p.param != param;
});
this.params.push({ param : param, value : value});
return this;
}
,request: function(post) {
var me = this;
me.responseData = null;
var r = this.req = js.Browser.createXMLHttpRequest();
var onreadystatechange = function(_) {
console.log('in onreadystatechange function');
//if(r.readyState != 4) return;
console.log(r.responseText);
console.log('r.status: ' + r.status);
me.req = null;
me.onData(me.responseData = r.responseText);
};
if(typeof XDomainRequest != "undefined") {
console.log('XDomainRequest');
r.onload = onreadystatechange;
}
var uri = this.postData;
try {
console.log('calling r.open with url: ' + this.url);
r.open("GET",this.url);
} catch( e1 ) {
me.req = null;
this.onError(e1.toString());
return;
}
//r.send(uri);
//do it, wrapped in timeout to fix ie9
setTimeout(function () {
r.send();
}, 0);
//if(!this.async) onreadystatechange(null);
}
,onData: function(data) {
}
,onError: function(msg) {
}
,onStatus: function(status) {
}
,__class__: haxe.Http
};
Note that this only implements the IE9 fix without doing the if statements to keep support for other browsers. But it's really easy. the IF statement is simply
if(typeof XDomainRequest != "undefined") return new XDomainRequest();
Basically, I know what the issue is, I just have no idea how I can change these things within the core of Haxe itself.
Thanks.
https://github.com/HaxeFoundation/haxe/pull/3449
BAM! Got it working in a local version of my haxe. Fixed for all browsers and sent a pull request. :D
Good job on this one!
You have to contact the Haxe mailing list directly, most thinking heads are over there rather than here :)
https://groups.google.com/d/forum/haxelang
I want so every added\changed record will have a time stamp of creation\change.
But - so it will be easy to embed and easy to manage - automatically.
Overwrite the 'DbContext' class or embed this in the '.tt' file (Codefirst \ DBFirst)
The code assume so you have the fields 'CreatedOn'\'ModifiedOn' inside the POCO.
If you don't have them, or you have only one - the code will work fine.
Be aware! If you use a extension (as this one) so allow you to do batch updates or changes from a stored procedure - this will not work
EDIT:
I found the source of my inspiration - thanks 'Nick' here
public override int SaveChanges()
{
var context = ((IObjectContextAdapter)this).ObjectContext;
var currentTime = DateTime.Now;
var objectStateEntries = from v in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
where v.IsRelationship == false && v.Entity != null
select v;
foreach (var entry in objectStateEntries)
{
var createdOnProp = entry.Entity.GetType().GetProperty("CreatedOn");
if (createdOnProp != null)
{
if (entry.State == EntityState.Added)
{
if (createdOnProp != null)
{
createdOnProp.SetValue(entry.Entity, currentTime);
}
}
else
{
Entry(entry.Entity).Property("CreatedOn").IsModified = false;
}
}
var modifiedOnProp = entry.Entity.GetType().GetProperty("ModifiedOn");
if (modifiedOnProp != null)
{
modifiedOnProp.SetValue(entry.Entity, currentTime);
}
}
return base.SaveChanges();
}
I'm generating HTML pages from strings stored in a database by using the IHTMLDocument2 write(SAFEARRAY) method. This works OK.
When CTRL+F is pressed the Find dialog appears as expected, but there are never any matches. What is being searched by CTRL+F? Perhaps an object is missing(that I must create) that the search looks at?
Here's some relevant code:
CComPtr<IDispatch> m_spDisp;
CComPtr<IWebBrowser2> m_spWeb2;
HRESULT m_hr;
IHTMLDocument2* m_document;
BOOL CSwiftDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_BackMenuButton.SetToolTipText(_T("Back"));
m_bInitialised = true;
m_bBackClicked = false;
m_svURLList.clear();
m_nCurrentPage = -1;
m_bitBack.LoadBitmap(IDB_BACK_BITMAP);
m_BackMenuButton.SetBitmap(m_bitBack);
m_spGlobal.CreateInstance(__uuidof(GLOBVARSLib::Global ) );
m_browser.Navigate(CSTR m_sURL, NULL, NULL, NULL, NULL);
GetDocument();
WriteHTMLString();
SetWindowSize(512,384);
return TRUE;
}
void CSwiftDlg::GetDocument()
{
m_hr = S_OK;
m_spDisp = m_browser.get_Application();
if (m_spDisp != NULL && m_spWeb2 ==NULL)
{
m_hr = m_spDisp->QueryInterface(IID_IWebBrowser2,(void**)&m_spWeb2);
}
if (SUCCEEDED(m_hr) && m_spWeb2 != NULL)
{
// get browser document's dispatch interface
IDispatch *document_dispatch = NULL;
m_hr = m_spWeb2->get_Document(&document_dispatch);
if (SUCCEEDED(m_hr) && (document_dispatch != NULL))
{ // get the actual document interface
m_hr = document_dispatch->QueryInterface(IID_IHTMLDocument2, (void **)&m_document);
// release dispatch interface
document_dispatch->Release();
}
}
}
void CSwiftDlg::WriteHTMLString()
{
if (m_document == NULL)
GetDocument();
SAFEARRAY *empty_array = SafeArrayCreateVector(VT_VARIANT,0,1);
// construct text to be written to browser as SAFEARRAY
SAFEARRAY *safe_array = SafeArrayCreateVector(VT_VARIANT,0,1);
VARIANT *variant;
SafeArrayAccessData(safe_array,(LPVOID *)&variant);
variant->vt = VT_BSTR;
variant->bstrVal = m_sHTML.AllocSysString();
SafeArrayUnaccessData(safe_array);
// write SAFEARRAY to browser document
m_document->write(empty_array);
m_document->close();
m_document->write(safe_array);
}
Answer:
As #Yahia suggested, it was a focus problem. I added m_document->execCommand("Refresh",...) after the m_document->write(safe_array) statement, as when I did "refresh" from the context menu Ctrl-F worked as expected. That fixed the "focus issue".
CTRL+F is focus-aware... you need to call focus on the parentWindow of m_document after WriteHTMLString(); and/or SetWindowSize(512,384);...