moshem
asked on
Adding HTML Control to Visual C++ program
Hi
I wrote a C++ software that displays text with links, I used richedit control fot this.
I now want to "upgrade" to HTML based control, but I can't find a way to do it unless I use MFC or ATL.
my software is Win32 API only. I need to use internet explorer HTML control (the lightest version since I want to keep my software small and compact).
can someone show me the way or even better share a Visual studio sample project ?
thanks
I wrote a C++ software that displays text with links, I used richedit control fot this.
I now want to "upgrade" to HTML based control, but I can't find a way to do it unless I use MFC or ATL.
my software is Win32 API only. I need to use internet explorer HTML control (the lightest version since I want to keep my software small and compact).
can someone show me the way or even better share a Visual studio sample project ?
thanks
ASKER
I tried it, but it does not work, browser window fails to create.
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass , szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
bool b = false;
b=AtlAxWinInit();
HWND browser =
CreateWindowEx(NULL,"AtlAx Win","http://www.PlanetCpp.com",
WS_CHILD|WS_VISIBLE|WS_VSC ROLL|WS_HS CROLL,0,0, 447,295,
hWnd,NULL,hInstance,NULL);
ShowWindow(browser, nCmdShow);
UpdateWindow(browser);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
bool b = false;
b=AtlAxWinInit();
HWND browser =
CreateWindowEx(NULL,"AtlAx
WS_CHILD|WS_VISIBLE|WS_VSC
hWnd,NULL,hInstance,NULL);
ShowWindow(browser, nCmdShow);
UpdateWindow(browser);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
i just made a program from scratch and it works, i don't know what you did, make sure the lib is included, header and you aso don't need to use ShowWindow on it, i used WS_VISIBLE in the style.
the window isn't showing at all? sounds like you didn't include what was needed.
the window isn't showing at all? sounds like you didn't include what was needed.
also is the createwindow code for atlaxwin in winmain? if not you have to use your global hinstance variable you might have overlooked that. better to just get the hinstance each time, theres other methods but i use
(HINSTANCE)GetWindowLong(h wnd,GWL_HI NSTANCE)
(HINSTANCE)GetWindowLong(h
ASKER
I did exactly that... I created a new project with a Win32 skeletlton (Visual Studio.net), then added :
first the includes:
#pragma comment(lib, "atl.lib")
#include <atlbase.h>
then winmain :
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_DISPLAYHTML, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance) ;
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance , (LPCTSTR)IDC_DISPLAYHTML);
bool b = false;
b=AtlAxWinInit();
// this fails
HWND browser =
CreateWindowEx(NULL,"AtlAx Win","http://www.google.com",
WS_OVERLAPPEDWINDOW|WS_VIS IBLE|WS_VS CROLL|WS_H SCROLL,0,0 ,447,295,
0,NULL,hInstance,NULL);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg .hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
What is wrong ?
first the includes:
#pragma comment(lib, "atl.lib")
#include <atlbase.h>
then winmain :
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_DISPLAYHTML, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance)
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance
bool b = false;
b=AtlAxWinInit();
// this fails
HWND browser =
CreateWindowEx(NULL,"AtlAx
WS_OVERLAPPEDWINDOW|WS_VIS
0,NULL,hInstance,NULL);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
What is wrong ?
ASKER
sorry, one line got replaced, this is how I do it:
HWND browser =
CreateWindowEx(NULL,"AtlAx Win","http://www.google.com",
WS_CHILD|WS_VISIBLE|WS_VSC ROLL|WS_HS CROLL,0,0, 447,295,
hWnd,NULL,hInstance,NULL);
now, what am I doing wrong ?
HWND browser =
CreateWindowEx(NULL,"AtlAx
WS_CHILD|WS_VISIBLE|WS_VSC
hWnd,NULL,hInstance,NULL);
now, what am I doing wrong ?
i don't know, only differences is i use vs 6 and i dont have it create a skeleton i just write it out. that shouldn't be a problem, i don't know why it won't work for you, i'm not doing anything special and it's only like 3 lines of code. not much to go on.
ASKER
can you share your project files? I will complile it as it
email me at Hound@PlanetCpp.com and ill zip it up and mail it. ill be back a little later. if ti doesnt work after that then it's definately a .NET thing.
ASKER
I got your project and your executable works fine for me, I tried to compile the project using Visual Studio.NET and it compiled but when I run it, it exhibit the exact same problems I saw with my own program, meaning, it does not work!
any ideas what I need to change in order for it to work with the latest version of the compiler?
thanks!
any ideas what I need to change in order for it to work with the latest version of the compiler?
thanks!
ASKER
Ok, I figured it out, I changed the window class name to "AtlAxWin7" instead of AtlAxWin" and it works.
the question is will it also work with other OS ?
the question is will it also work with other OS ?
you wrote a win32 api program,,the whole thing won't work in another OS.
ASKER
I meant another Windows OS
shouldn't be a problem at all
i just read an MSDN article saying that in .NET atlaxwin was renamed to atlaxwin7, from what i read it didn't say why.
i just read an MSDN article saying that in .NET atlaxwin was renamed to atlaxwin7, from what i read it didn't say why.
ASKER
Ok, one last question, how do I recieve events from the Atl window? can you write a few lines of sample code here or send me to a link?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks, but I meants more control specific events...
I'll give you the points, you were more than helpfull, if you can be more specific as for object events and can post it here, I'll be very glad.
thanks!
I'll give you the points, you were more than helpfull, if you can be more specific as for object events and can post it here, I'll be very glad.
thanks!
i didn't know you wanted to use this as a fully functional web browser. i usually use it to display one thing, maybe some html.
just make a small change, make the startup text "Shell.Explorer.1" instead of a webpage.
now the rest i can only point you in the right direction cause i havent played with it much.
you need to create an IUnknown
IUnknown *pUnk;
then use
AtlAxGetControl(browserwin dow,pUnk);
then you need to make a CComPtr
CComPtr browserPtr
then through the iunknown you have to call QueryInterface
pUnk->QueryInterface(IID_I WebBrowser 2,(void**) &browserPt r);
i'm not 100% sure just using -> will be ok, the compiler might not know what it's dereferencing, but try it.
if you got anything but NULL in browserPtr then your good to go
from there the only command i know of is Navigate2
browserPtr->Navigate2(..im not sure of the parametrs)
for more info lookup the functions i wrote and also
CComVariant - youll need to pass this type to functions
i'm sure it's not hard i just never played with it yet.
just make a small change, make the startup text "Shell.Explorer.1" instead of a webpage.
now the rest i can only point you in the right direction cause i havent played with it much.
you need to create an IUnknown
IUnknown *pUnk;
then use
AtlAxGetControl(browserwin
then you need to make a CComPtr
CComPtr browserPtr
then through the iunknown you have to call QueryInterface
pUnk->QueryInterface(IID_I
i'm not 100% sure just using -> will be ok, the compiler might not know what it's dereferencing, but try it.
if you got anything but NULL in browserPtr then your good to go
from there the only command i know of is Navigate2
browserPtr->Navigate2(..im
for more info lookup the functions i wrote and also
CComVariant - youll need to pass this type to functions
i'm sure it's not hard i just never played with it yet.
ASKER
Hi,
if I can impose one more question, how can I reset the source of the explorer window, if I want display HTML using MSHTML: and later change the HTML without destroying the control and recreating it, how would I do that?
thanks
if I can impose one more question, how can I reset the source of the explorer window, if I want display HTML using MSHTML: and later change the HTML without destroying the control and recreating it, how would I do that?
thanks
navigate2 would do that
when you get the pointer to the control and the interface pointer you can control it much better
when you get the pointer to the control and the interface pointer you can control it much better
ASKER
yeah, I tried to get the pointer but it keeps failing!
do you have a code snippet?
BTW, I only need to change the HTML each time or to add to the exisitng HTML (push into the top). I have no need for it to navigate to a site.
I tried using SetWindowText, but it does nothing!
do you have a code snippet?
BTW, I only need to change the HTML each time or to add to the exisitng HTML (push into the top). I have no need for it to navigate to a site.
I tried using SetWindowText, but it does nothing!
i just did the happy dance! i scoured MSDN for 10 minutes and found bits and peices of info on this and put it all together and im very surprised that it worked lol
here is how to use Navigate2 (i really suggest you do what im going to do now which is so find more info, i might be using something and not releasing it or something like that)
add <exdisp.h> to your includes first off
i keep seeing one called <mshtml.h> but so far ive needed nothing from it
after you create the browser window
HWND browser =
CreateWindowEx(NULL,"AtlAx Win","http://www.google.com",
WS_CHILD|WS_VISIBLE|WS_VSC ROLL|WS_HS CROLL,0,0, 400,300,
hWnd,NULL,hInstance,NULL);
IUnknown *pUnk = NULL;
//i had to fight with this next line to get it right
AtlAxGetControl(browser,(I Unknown**) &pUnk);
if(pUnk == NULL)
MessageBox(0,"can't get pointer","error",MB_OK); //might want to exit too
//this is instead of CComPtr, it looks more appropriate to use in this case
IWebBrowser2 *iweb = NULL;
pUnk->QueryInterface(IID_I WebBrowser 2,(void**) &iweb);
pUnk->Release();//iweb is what we want now
if(iweb)
{
CComVariant ccv,ccvurl("http://www.PlanetCpp.com");
iweb->put_Visible(VARIANT_ TRUE);
iweb->Navigate2(&ccvurl,&c cv,&ccv,&c cv,&ccv);
}
that's all hopefully it's no different in .NET
i changed it form "Shell.Explorer.1" to any site cause,,well you'll see why it makes scrollbars double up for some reason.
here is how to use Navigate2 (i really suggest you do what im going to do now which is so find more info, i might be using something and not releasing it or something like that)
add <exdisp.h> to your includes first off
i keep seeing one called <mshtml.h> but so far ive needed nothing from it
after you create the browser window
HWND browser =
CreateWindowEx(NULL,"AtlAx
WS_CHILD|WS_VISIBLE|WS_VSC
hWnd,NULL,hInstance,NULL);
IUnknown *pUnk = NULL;
//i had to fight with this next line to get it right
AtlAxGetControl(browser,(I
if(pUnk == NULL)
MessageBox(0,"can't get pointer","error",MB_OK); //might want to exit too
//this is instead of CComPtr, it looks more appropriate to use in this case
IWebBrowser2 *iweb = NULL;
pUnk->QueryInterface(IID_I
pUnk->Release();//iweb is what we want now
if(iweb)
{
CComVariant ccv,ccvurl("http://www.PlanetCpp.com");
iweb->put_Visible(VARIANT_
iweb->Navigate2(&ccvurl,&c
}
that's all hopefully it's no different in .NET
i changed it form "Shell.Explorer.1" to any site cause,,well you'll see why it makes scrollbars double up for some reason.
ASKER
that's great, it actually works, but the damn thing won't work with custom HTML (using MSHTML:) anymore! and that is what I need, damn!
ASKER
Ok, I tried creating the window with a MSHTML string,
then changed your code to:
IUnknown *pUnk = NULL;
//i had to fight with this next line to get it right
AtlAxGetControl(browser,(I Unknown**) &pUnk);
if(pUnk == NULL)
MessageBox(0,"can't get pointer","error",MB_OK); //might want to exit too
//this is instead of CComPtr, it looks more appropriate to use in this case
IHTMLDocument2 *iweb = NULL;
pUnk->QueryInterface(IID_I HTMLDocume nt2,(void* *)&iweb);
pUnk->Release();//iweb is what we want now
if(iweb)
{
CComVariant ccv,ccvurl("mshtml:<html>< body><b>hi </b></body ></html>") ;
// iweb->put_Visible(VARIANT_ TRUE);
// iweb->Navigate2(&ccvurl,&c cv,&ccv,&c cv,&ccv);
iweb->write
}
and it works, just that iweb->write, expects SAFEARRAY, you don't know how to hand it a string, don't you ?
then changed your code to:
IUnknown *pUnk = NULL;
//i had to fight with this next line to get it right
AtlAxGetControl(browser,(I
if(pUnk == NULL)
MessageBox(0,"can't get pointer","error",MB_OK); //might want to exit too
//this is instead of CComPtr, it looks more appropriate to use in this case
IHTMLDocument2 *iweb = NULL;
pUnk->QueryInterface(IID_I
pUnk->Release();//iweb is what we want now
if(iweb)
{
CComVariant ccv,ccvurl("mshtml:<html><
// iweb->put_Visible(VARIANT_
// iweb->Navigate2(&ccvurl,&c
iweb->write
}
and it works, just that iweb->write, expects SAFEARRAY, you don't know how to hand it a string, don't you ?
id have to look around to figure that out it seems wierd
try using a local htm file, thats what i use on one of my programs, i keep opening a tmp.htm in my programs directory and i change it when needed. i dont use the navigate2 method but it should work
try using a local htm file, thats what i use on one of my programs, i keep opening a tmp.htm in my programs directory and i change it when needed. i dont use the navigate2 method but it should work
ASKER
this works, writing into a file is one option, but a clumsy one. dynamic updating would be much nicer...
this works, but now I need to pass it dynamic string, one that takes char* or std::string...
HRESULT hresult = S_OK;
VARIANT *param;
SAFEARRAY *sfArray;
BSTR bstr = SysAllocString (OLESTR("hi"));
// Creates a new one-dimensional array
sfArray = SafeArrayCreateVector(VT_V ARIANT, 0, 1);
if (sfArray == NULL || iweb == NULL) {
goto cleanup;
}
hresult = SafeArrayAccessData(sfArra y,(LPVOID* ) & param);
param->vt = VT_BSTR;
param->bstrVal = bstr;
hresult = SafeArrayUnaccessData(sfAr ray);
hresult = iweb->write(sfArray);
cleanup:
SysFreeString(bstr);
if (sfArray != NULL) {
SafeArrayDestroy(sfArray);
}
this works, but now I need to pass it dynamic string, one that takes char* or std::string...
HRESULT hresult = S_OK;
VARIANT *param;
SAFEARRAY *sfArray;
BSTR bstr = SysAllocString (OLESTR("hi"));
// Creates a new one-dimensional array
sfArray = SafeArrayCreateVector(VT_V
if (sfArray == NULL || iweb == NULL) {
goto cleanup;
}
hresult = SafeArrayAccessData(sfArra
param->vt = VT_BSTR;
param->bstrVal = bstr;
hresult = SafeArrayUnaccessData(sfAr
hresult = iweb->write(sfArray);
cleanup:
SysFreeString(bstr);
if (sfArray != NULL) {
SafeArrayDestroy(sfArray);
}
first you need to include a header and link to a lib, i use #pragma to link to libs but you can just use the project settings if you want to:
#include <atlbase.h>
#pragma comment(lib,"atl.lib")//or
then in wm_create or winmain:
//INIT ATL FOR BROWSER
AtlAxWinInit();
then tada!:
browser = CreateWindowEx(NULL,"AtlAx
and thats all, that's only to show stuff if you want to add more functionality you'll have to look up how to do that with atlaxwin, i only used it to show html code a program i wrote generated.
to show raw html you need to prefix the html with MSHTML:
so you can pass it "MSHTML:<b>Hello World</b>"