|
|
Comments and Discussions
|
|
 |

|
When hooking the dialog in newer IE versions - things have changed - and trying to do it the original way this article outlines no longer works. After 2 days of banging my head with the new "DirectUIHWND" - I finally managed to "force feed" the filename edit control and the combobox for the save as file type as follows: <b>1. Change the following enum:</b> typedef enum _SaveType { SAVETYPE_HTMLPAGE = 0, SAVETYPE_ARCHIVE <b>= 1</b>, SAVETYPE_HTMLONLY<b> = 2</b>, SAVETYPE_TXTONLY <b>= 3</b> } SaveType;
2. With newer versions of IE - you can no longer count on: HWND hSaveTypeComboWnd = GetDlgItem(hwnd, 0x0470); Therefore: <b>a) change the UpdateSaveAs method as follows:</b> bool CSaveAsWebbrowser::UpdateSaveAs(HWND hwnd){ // editbox : filepath (control id = 0x047c) NOTE (on older IEs) // dropdown combo : filetypes (options=complete page;archive;html only;txt) (control id = 0x0470) // save button : control id = 0x0001 // cancel button : control id = 0x0002 try { if( hwnd ) m_bUpdateUI = TRUE; // select right item in the combobox HWND hSaveTypeComboWnd = GetDlgItem(hwnd, 0x0470); if( IsWindow(hSaveTypeComboWnd ) ){ // Old Style SendMessage(hSaveTypeComboWnd, CB_SETCURSEL, (WPARAM) m_nSaveType, 0); SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0x0470,CBN_CLOSEUP), (LPARAM) hSaveTypeComboWnd); HWND hFileNameEditCtrl = GetDlgItem(hwnd, 0x047c); if( !hFileNameEditCtrl || !IsWindow(hFileNameEditCtrl) ){ hFileNameEditCtrl = GetDlgItem(hwnd, 0x03e9); } // set output filename if( hFileNameEditCtrl && IsWindow(hFileNameEditCtrl) ){ ExchangeEditText(hFileNameEditCtrl, (LPSTR)&m_szFilename); } } else { HWND hWnd1 = FindWindowEx(hwnd,0,"DUIViewWndClassName",""); if( hWnd1 ){ HWND hWnd2 = FindWindowEx(hWnd1,0,"DirectUIHWND",""); if( hWnd2 ){ EnumChildWindows (hWnd2, FloatNotifySinkChildEnumProc, (LPARAM)this) ; } } } if (m_bUpdateUI) SendMessage(GetDlgItem(hwnd, 0x0001), BM_CLICK, 0, 0); // Invoke Save button else SendMessage(GetDlgItem(hwnd, 0x0002), BM_CLICK, 0, 0); // Invoke Cancel button } catch(...){;} return true; }
<b>b) add the following new callback function (for the child window enum)</b> BOOL CALLBACK FloatNotifySinkChildEnumProc (HWND hwnd, LPARAM lParam){ if (GetWindow (hwnd, GW_OWNER)) // Check for icon title return TRUE ; CSaveAsWebbrowser * saWb = (CSaveAsWebbrowser *) lParam; if( saWb ){ // 1st, check to see if this window is of ComboBox class char szWndClassName[MAX_PATH]; memset(&szWndClassName,0,MAX_PATH); GetClassNameA(hwnd,(LPSTR)&szWndClassName,MAX_PATH); if( lstrcmp( (LPCSTR)&szWndClassName, "FloatNotifySink" ) == 0 ){ HWND hChildControl = (HWND) GetWindow(hwnd,GW_CHILD); if( hChildControl ){ char szChildClassName[MAX_PATH]; memset(&szChildClassName,0,MAX_PATH); GetClassName(hChildControl,(LPSTR)&szChildClassName,MAX_PATH); string_to_upper((LPSTR)&szChildClassName); if( lstrcmp("COMBOBOX",(LPSTR)&szChildClassName) == 0 ){ // if it is a combobox - see if it has a "Edit" child winodw, if it does - it's the filename window, otherwise - it's the file type window. HWND hFileNameEditWnd = FindWindowEx(hChildControl, 0, "Edit", ""); if( hFileNameEditWnd ){ saWb->AssignFileName(hFileNameEditWnd); } else { /* Uncomment to peek at the current combobox's selection and selected text int iSelected = 0 ; iSelected = (int) SendMessage(hChildControl,CB_GETCURSEL,0,0); if( iSelected != CB_ERR ){ int iBufLen = SendMessage(hChildControl,CB_GETLBTEXTLEN,0,0); int iMallocLen = (iBufLen * 2) + 2 ; char * szBuffer = (char *) malloc( iMallocLen ); if( szBuffer ){ memset(szBuffer,0, iMallocLen ); SendMessage(hChildControl,CB_GETLBTEXT,(WPARAM)iSelected,(LPARAM)(LPSTR)szBuffer); free(szBuffer); } } */ saWb->AssignFileType(hChildControl); } } } } } return TRUE ; } <b>c) and finally - add these 2 new methods to the class: </b> void CSaveAsWebbrowser::AssignFileName(HWND hwnd){ ExchangeEditText(hwnd, (LPSTR)&m_szFilename); } void CSaveAsWebbrowser::AssignFileType(HWND hwnd){ SendMessage(hwnd, CB_SETCURSEL, (WPARAM) 1, 0); SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID),CBN_CLOSEUP), (LPARAM) hwnd); } Regards, Rene Pilon
-- Modified Friday, July 29, 2011 6:09 PM
|
|
|
|

|
Thanks for the work!
Here are some notes and pitfalls I encountered while trying this out:
string_to_upper((LPSTR) &szChildClassName);
if(lstrcmp("COMBOBOX",(LPSTR) &szChildClassName) == 0){...}
string_to_upper() was unknown to my VS 2008 package, so I deleted that line and used the case insensitive version of lstrcmp() named lstrcmpi() in the following line.
void CSaveAsWebbrowser::AssignFileName(HWND hwnd){
ExchangeEditText(hwnd, (LPSTR) &m_szFilename);
}
"ExchangeEditText()" expects type "CString &" as second argument, "m_szFilename" is already of type CString therefore the cast to "(LPSTR) &" is erroneous.
Same goes for
if( hFileNameEditCtrl && IsWindow(hFileNameEditCtrl) ){
ExchangeEditText(hFileNameEditCtrl, (LPSTR) &m_szFilename);
in "CSaveAsWebbrowser::UpdateSaveAs()"
By mistake I defined the new callback function
BOOL CALLBACK FloatNotifySinkChildEnumProc()
as a member function of CSaveAsWebbrowser.
Problem you get is that it never resolves to the required type in the call to
EnumChildWindows(hWnd2, FloatNotifySinkChildEnumProc, (LPARAM)this);
Therefore "FloatNotifySinkChildEnumProc()" should be defined as global function.
When doing so, one should be aware though, that it perfoms calls to
"CSaveAsWebbrowser::AssignFileName()"
and
"CSaveAsWebbrowser::AssignFileType()"
hence these 2 new methods must be declared as public members of class CSaveAsWebbrowser.
Last thing:
In
void CSaveAsWebbrowser::AssignFileType(HWND hwnd){
SendMessage(hwnd, CB_SETCURSEL, (WPARAM) 1, 0);
SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID),CBN_CLOSEUP), (LPARAM) hwnd);
}
I don't see any access to the file type stored in "m_nSaveType".
The type does change from "complete web page" but it always saves as archive.
Am I missing something?
In this context I also noticed one major drawback of the presented solution:
As it looks, flicking through the child windows of the "Save As" dialog box using EnumChildWindows() always finds the edit control for the filename first and then the combo box for file type. This way IE will always dictate you its file extension no matter what you specify in "m_wbSaveAs.Config("filename","filetype")".
|
|
|
|

|
Good stuff. I posted the sample code to show how I managed to get it working before I modded it further for my needs. You are correct about the CB_SETCURSEL - it's selecting the 2nd choice in the save type combobox - and this is very dependent in IE always having MHT as the 2nd option in the combobox. As well - I should have put the enum value instead of the 1 directly. Rene.
|
|
|
|

|
Having taken a second look at this I have now solved my requests to a satisfactory degree.
1. In
void CSaveAsWebbrowser::AssignFileType(HWND hwnd)
{
SendMessage(hwnd, CB_SETCURSEL, (WPARAM) 1, 0);
SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID),CBN_CLOSEUP), (LPARAM) hwnd);
}
The first SendMessage() should read
SendMessage(hwnd, CB_SETCURSEL, (WPARAM) m_nSaveType, 0);
if you want your website to be saved in a format other than an archive.
2. As regards the order of the selection of the controls the Save as dialog box turned out to be rather bitchy.
Say you want your website to be saved under the name "Source.txt" with save type HTMLONLY then the program would fill in "Source.txt" under filename and then select "HTML only" from the combobox, thus changing the filename to "Source.htm".
So I tried to reverse the order by storing the windows handle for the edit control in a variable and performing the selection of the save type first. The filename gets filled in correctly but the dialog box doesn't use it and reverts to the default name "yahoo.htm" ("yahoo.com" being the website of the example code).
Second approach: Performing the EnumChildWindows() function twice, first for the combobox (works) then for the edit control (didn't do anything). Resulting filename: "yahoo.htm"
Back to method 1: Filling in the edit control twice: "Source.txt" (first edit) -> "Source.htm" (after combobox selection) -> "Source.txt" (second edit) -> "Source.htm" (resulting filename).
Obviously the edit control needs something else before accepting the submitted string (like the combobox needing a CBN_CLOSEUP message) but I haven't figured out what this might be.
I did find out however, that performing a "Select All" (Ctrl+A) on the edit control does the trick.
Well, maybe not the most elegant solution by someone who knows what he is doing and what is going on in the internals of MS Windows, but here are the code changes:
Add the variable m_hFileNameEditWnd of type HWND as a public member to the class CSaveAsWebbrowser.
Add 3 lines to UpdateSaveAs()
bool CSaveAsWebbrowser::UpdateSaveAs(HWND hwnd)
{
try
{
if(hwnd)
m_bUpdateUI = TRUE;
HWND hSaveTypeComboWnd = GetDlgItem(hwnd, 0x0470);
if(IsWindow(hSaveTypeComboWnd))
{
SendMessage(hSaveTypeComboWnd, CB_SETCURSEL, (WPARAM) m_nSaveType, 0);
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0x0470, CBN_CLOSEUP), (LPARAM) hSaveTypeComboWnd);
HWND hFileNameEditCtrl = GetDlgItem(hwnd, 0x047c);
if(!hFileNameEditCtrl || !IsWindow(hFileNameEditCtrl))
hFileNameEditCtrl = GetDlgItem(hwnd, 0x03e9);
if(hFileNameEditCtrl && IsWindow(hFileNameEditCtrl))
ExchangeEditText(hFileNameEditCtrl, m_szFilename);
}
else
{
HWND hWnd1 = FindWindowEx(hwnd,0,"DUIViewWndClassName","");
if(hWnd1)
{
HWND hWnd2 = FindWindowEx(hWnd1,0,"DirectUIHWND","");
if(hWnd2)
{
m_hFileNameEditWnd = NULL;
EnumChildWindows(hWnd2, FloatNotifySinkChildEnumProc, (LPARAM) this);
if(m_hFileNameEditWnd)
AssignFileName(m_hFileNameEditWnd);
}
}
}
if (m_bUpdateUI)
SendMessage(GetDlgItem(hwnd, 0x0001), BM_CLICK, 0, 0); else
SendMessage(GetDlgItem(hwnd, 0x0002), BM_CLICK, 0, 0); }
catch(...){;}
return true;
}
Change 1 line of FloatNotifySinkChildEnumProc()
BOOL CALLBACK FloatNotifySinkChildEnumProc(HWND hwnd, LPARAM lParam)
{
if (GetWindow(hwnd, GW_OWNER)) return TRUE;
CSaveAsWebbrowser *saWb = (CSaveAsWebbrowser *) lParam;
if(saWb)
{
char szWndClassName[MAX_PATH];
memset(&szWndClassName, 0, MAX_PATH);
GetClassNameA(hwnd, (LPSTR)&szWndClassName, MAX_PATH);
if(lstrcmp((LPCSTR)&szWndClassName, "FloatNotifySink") == 0)
{
HWND hChildControl = (HWND) GetWindow(hwnd, GW_CHILD);
if(hChildControl)
{
char szChildClassName[MAX_PATH];
memset(&szChildClassName, 0, MAX_PATH);
GetClassName(hChildControl, (LPSTR) &szChildClassName, MAX_PATH);
if(lstrcmpi("COMBOBOX", (LPSTR)&szChildClassName) == 0)
{
HWND hFileNameEditWnd = FindWindowEx(hChildControl, 0, "Edit", "");
if(hFileNameEditWnd)
saWb->m_hFileNameEditWnd = hFileNameEditWnd;
else
{
saWb->AssignFileType(hChildControl);
}
}
}
}
}
return TRUE;
}
Finally to get AssignFileName() to send Ctrl+A:
void CSaveAsWebbrowser::AssignFileName(HWND hwnd)
{
ExchangeEditText(hwnd, m_szFilename);
SendMessage(hwnd, WM_KEYDOWN, 0x00000011, 0x001D0001); SendMessage(hwnd, WM_KEYDOWN, 0x00000041, 0x001E0001); SendMessage(hwnd, WM_CHAR, 0x00000001, 0x001E0001);
SendMessage(hwnd, WM_KEYUP, 0x00000041, 0xC01E0001);
SendMessage(hwnd, WM_KEYUP, 0x00000011, 0xC01D0001);
}
|
|
|
|

|
I am navigating to a secure website and i need to click on a file to save it as and I am trying to interact with the dialog box to save as a certain file
Any help would be greatly appreciated
Thanks
|
|
|
|

|
Thanks for all the people on this thread. here is working example..
Usage :
To use from IE plugin :
SHDocVw.IWebBrowser2 browser = GetCurrentBrowser();
MHTHelper mhtHelper = new MHTHelper();
bool bMhtFile = mhtHelper.SaveAs(browser, filePath, EnumBrowserFileSaveType.SAVETYPE_ARCHIVE);
#region ---- EnumBrowserFileSaveType ----
public enum EnumBrowserFileSaveType
{
SAVETYPE_HTMLPAGE = 0,
SAVETYPE_ARCHIVE,
SAVETYPE_HTMLONLY,
SAVETYPE_TXTONLY
}
#endregion
public class MHTHelper
{
#region ---- Constructor ----
public MHTHelper()
{
}
#endregion
#region ---- Private Attributes ----
private IWebBrowser2 webBrowser;
private string filePath;
private EnumBrowserFileSaveType saveType;
private WindowHookProc HookProcedure;
private int windowHook = 0;
private IntPtr hwndSaveAsDlg = (IntPtr)0;
private MHTHelper saveAsMht = null;
#endregion
#region ---- Public Attributes ----
public IWebBrowser2 WebBrowser
{
get { return webBrowser; }
set { webBrowser = value; }
}
public string FilePath
{
get { return filePath; }
set { filePath = value; }
}
public EnumBrowserFileSaveType SaveType
{
get { return saveType; }
set { saveType = value; }
}
#endregion
#region ---- SaveAs ----
/// <summary>
/// In this function we are automating the following functionality.
/// 1.Select 'File->Save AS' menu item on IE
/// 2.Take SaveAS dialog out of screen so that user cannot interact with it.(we cannot hide it, because of IE security policy.)
/// 3.Set the required file path to the save as dialog.
/// 4.Click on save button.
/// 5.IE automatically display the status bar to show the extraction process of currently displayed web page into mht file.
/// </summary>
/// <param name="webBrowser"></param>
/// <param name="pathFile"></param>
/// <param name="saveType"></param>
/// <returns></returns>
public bool SaveAs(IWebBrowser2 webBrowser, string pathFile, EnumBrowserFileSaveType saveType)
{
try
{
this.WebBrowser = webBrowser;
this.FilePath = pathFile;
this.SaveType = saveType;
//If no path is supplied or file already exists then it prompts for user action.
if (0 == pathFile.Length)
pathFile = "untitled";
if ((null == webBrowser) || (0 != windowHook))
return false;
this.HookProcedure = new WindowHookProc(this.SaveAsHookProc);
// prepare SaveAs dialog hook and activate it.
this.windowHook = SetWindowsHookEx(5 /*WH_CBT*/, HookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId());
if (this.windowHook == 0)
return false;
try
{
// This following code shows the save as dialog
this.saveAsMht = this;
object o = null;
webBrowser.ExecWB(SHDocVw.OLECMDID.OLECMDID_SAVEAS, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER, ref o, ref o);
this.saveAsMht = null;
return true;
}
finally
{
//Here we took out our hook .
UnhookWindowsHookEx(this.windowHook);
this.windowHook =0;
}
}
catch (Exception ex)
{
ExceptionHandler.Display(ex);
return false;
}
}
#endregion
#region ---- SaveAsHookProc ----
/// <summary>
/// This proc is required to handle Window messages and do appropriate action for our requirements.
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
public int SaveAsHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
switch (nCode)
{
case 3: // HCBT_CREATEWND
CBT_CREATEWND cw = (CBT_CREATEWND)Marshal.PtrToStructure(lParam, typeof(CBT_CREATEWND));
CREATESTRUCT cs = (CREATESTRUCT)Marshal.PtrToStructure(cw.lpcs, typeof(CREATESTRUCT));
if (cs.lpszClass == 0x00008002)
{
this.hwndSaveAsDlg = (IntPtr)wParam; // Get hwnd of SaveAs dialog
cs.x = -2 * cs.cx; // Move dialog off screen
}
break;
case 5: // HCBT_ACTIVATE
IntPtr hwnd = (IntPtr)wParam;
//Here we get Save as dialog handle
if (hwnd == this.hwndSaveAsDlg && this.hwndSaveAsDlg != (IntPtr)0)
{
//Prepare a thread to act as required messages source.Also set File path and its save type.
ThreadPressOk tpok = new ThreadPressOk(hwnd, this.saveAsMht.FilePath, this.saveAsMht.SaveType);
this.hwndSaveAsDlg = (IntPtr)0;
// Create a thread to execute the task, and then
// start the thread.
new Thread((new ThreadStart(tpok.ThreadProc))).Start();
}
break;
}
//This is required to pass control to next hook if exists on this process.
return CallNextHookEx(this.windowHook, nCode, wParam, lParam);
}
#endregion
#region ---- Win32APIs ----
//Import for SetWindowsHookEx.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int SetWindowsHookEx(int idHook, WindowHookProc lpfn, IntPtr hInstance, int threadId);
//Import for UnhookWindowsHookEx.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool UnhookWindowsHookEx(int idHook);
//Import for CallNextHookEx.
//Use this function to pass the hook information to next hook procedure in chain.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
//This delegate is required to fetch our function to the thread.
public delegate int WindowHookProc(int nCode, IntPtr wParam, IntPtr lParam);
//These Win32 structures are requred to handle windows messages/state
[StructLayout(LayoutKind.Sequential)]
public struct CBT_CREATEWND
{
public IntPtr lpcs;
int hwndInsertAfter;
};
[StructLayout(LayoutKind.Sequential)]
public struct CREATESTRUCT
{
int lpCreateParams;
int hInstance;
int hMenu;
int hwndParent;
int cy;
public int cx;
int y;
public int x;
int style;
int lpszName;
public int lpszClass;
int dwExStyle;
}
#endregion
#region ---- Thread Requirements ----
//The following class is defined here because it is used in the above class only.
//It sends all required thread messages to IE's save as dialog.
class ThreadPressOk
{
public ThreadPressOk(IntPtr hwnd, string pathFile, EnumBrowserFileSaveType saveType)
{
this.hwndDialog = hwnd;
this.pathFile = pathFile;
this.saveType = saveType;
}
IntPtr hwndDialog;
string pathFile;
EnumBrowserFileSaveType saveType;
// Imports of the User32 DLL.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDlgItem(IntPtr hWnd, int nIDDlgItem);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern private bool SetWindowText(IntPtr hWnd, string lpString);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
// The thread procedure performs the message loop and place the data
public void ThreadProc()
{
//To avoid race condition, we are forcing this thread to wait until Saveas dialog is displayed.
while (!IsWindowVisible(hwndDialog))
{
Thread.Sleep(100);
Application.DoEvents();
}
Application.DoEvents();
//Get the handle to SaveType combo box on the save as dialog.
IntPtr typeB = GetDlgItem(hwndDialog, 0x0470);
//Get the handle to file path on the saveas dialog.
IntPtr nameB = GetDlgItem(hwndDialog, 0x047c);
//Get the handle to saveas on the saveas dialog.
IntPtr saveBtn = GetDlgItem(hwndDialog, 0x0001);
if (((IntPtr)0 != typeB) && ((IntPtr)0 != nameB) && ((IntPtr)0 != saveBtn) && IsWindowVisible(hwndDialog))
{
//select save type
SendMessage(typeB, 0x014E /*CB_SETCURSEL*/, (int)saveType, 0);
SendMessage(hwndDialog, 0x0111 /*WM_COMMAND*/, 0x80470/*MAKEWPARAM(0x0470, CBN_CLOSEUP)*/, (int)typeB);
// set save as filepath
SetWindowText(nameB, pathFile);
// Invoke Save button click.
SendMessage(saveBtn, 0x00F5 /*BM_CLICK*/, 0, 0);
}
// Clean up GUI - we have clicked save button.
//GC is going to do that cleanup job, so we are OK
Application.DoEvents();
//Terminate the thread.
return;
}
}
#endregion
}
Thanks
Maydipalle
|
|
|
|

|
Hi to all, it been a long time since my last time I write/ask in the forum.
I have the problem I hope you can help me:
I’m using the guide:
http://www.codeproject.com/KB/shell/iesaveas.aspx
(Automated IE SaveAs MHTML)
I have the problem when I’m running the code in Windows Vista
In the method:
void CSaveAsWebbrowser::UpdateSaveAs(HWND hwnd)
{
// editbox : filepath (control id = 0x047c)
// dropdown combo : filetypes (options=complete page;
// archive;html only;txt) (control id = 0x0470)
// save button : control id = 0x0001
// cancel button : control id = 0x0002
// select right item in the combobox
SendMessage(GetDlgItem(hwnd, 0x0470), CB_SETCURSEL,
(WPARAM) m_nSaveType, 0);
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0x0470,CBN_CLOSEUP),
(LPARAM) GetDlgItem(hwnd, 0x0470));
// set output filename
SetWindowText(GetDlgItem(hwnd, 0x047c), m_szFilename);
// Invoke Save button
SendMessage(GetDlgItem(hwnd, 0x0001), BM_CLICK, 0, 0);
}
The problem is that we send the control id ‘0x047c’,(for the combo box and the output file), I noticed that the method GetDlgItem(hwnd, 0x047c), return 0, I’m thinking the problem is that the code id '0x047c' in Vista is not relevant, I found out that for NT, Windows 98 and 95 the combobox and output file has different ID ‘0x0480’, I was wandering I someone know where I can found the id’s for Vista, or someone have another idea why this is not working.
Thanks
|
|
|
|

|
Hello!
I use this code to run success on Windows Xp (whith IE8) but can't exact on Windows 7 (with IE8).
Help me!
|
|
|
|

|
I would like to use custom dialog to save as webpages from internet explorer. It would be done in C#.
Do you know the libraries for C# ? I have been looking for libraries in c# but i cant find anything !
|
|
|
|

|
Hi
I am using your application for programmatically saving file from IE
Automated IE SaveAs MHTML
Well only one small change I have made.
In your application
1)You create a separate browser control
2)Navigate it to web page
3)And then Save the file using
HRESULT hr = m_pWebBrowser->ExecWB(cmdid, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
I have included SaveAsThread.cpp and SaveAsWebBrowser.cpp in my application.
Only change I have made is in your SetWebBrowser method,
Instead of setting your application's browser control,
I get an instance of currently running IE(IE version 8) and set it in SetWebBrowser method
Then I have added one button on IE toolbar and on click of it I call
m_wbSaveAs.Config( CString(finalFilePath), SAVETYPE_ARCHIVE );
m_wbSaveAs.SaveAs()
where finalFilePath is path of file to be saved
Now when ever I surf lighter pages or pages with small size, I am able to Save pages and your program runs amazing.
But when ever i surf heavy pages for example home page of http://indiatimes.com my instance of IE gets hanged and page is not being able to saved.
Same heavy page when I surf in your application and in your web browser control instead of IE itself, application works absolutely fine and is able to save page.
Do you have any idea, why IE itself is not able to perform the same.
Any clues or help would be of great help
Thanks in advance
|
|
|
|

|
hi
Can we in any way use SetWindowsHookEx in hooking printer dialogs using printHookProc()??plz tell me otherwise how to do so?if somebody can explain giving sample code that will be more helpful to me as i'm a newbie in this..
thanks and regards
Rm
|
|
|
|

|
Is this possible? I am also a VB.net user but any info or sample would be very helpfull. thanks
|
|
|
|

|
I have spend days looking for this information. Now that I've finally found it, it is NOT in vb.net. Ever thought of converting it?
|
|
|
|

|
Hello,
cool...Its a nice work.I have a problem of saving HTML.I developed a project which is load url into Internet Explorer(shell Executing iexplore.exe). But I cann't save that Url automatically. I want to save it without showing its saveAs Dialog.I am trying it with your project. But I cann't. Can you please give me any ideas.
Thanks
Kallol
|
|
|
|

|
Hi,
First of all I would like to thank the author for the excellent article. This works perfectly for HTML pages.
Now I have a requirement where the URL link may point to a excel file or a pdf file or any other kind of binay file. When I use the program for excel file, the save as dialog box does popup but the BM_CLICK message does not work to invoke the save button. I noticed that this is because there is another kind of save as dialog that appears when we try to save the excel file (different from the one that appears when you try to do save as for HTML pages). I thought that the resource id for save button must have changed and tried 1 to 100 all ids not just 1. But no success. Then I tried to use Spy++ drag and drop feature to identify the save button window, but unfortunately even Spy++ does not identify this save button as an independent window.
Possible questions:
How can I indentify the right button resource id?
How can invoke the save button in this new kind of save as dialog?
Any help is appreciated.
Thanks & regards,
Nitesh
|
|
|
|

|
I have a problem with the printer. I want to know whether a printer is physically connected and then I want to issue a print command. If any one can help me I would be greatful.
|
|
|
|

|
What has this to do with the article?
|
|
|
|

|
Ofcourse it is not related but some one working with printers may respond.
|
|
|
|

|
Your code is very good in debug version, but in release version, I can't save any .mhtml file. This is a big bug, I hope you find why the Problem occur only in Release version.
Zjroland from http://www.outsourcexp.com
|
|
|
|

|
I mean how to save a web page without navigate to the page just from the url ?
also the save as dialog box should not be shown.
Thank you sir
|
|
|
|

|
Hi,
I used your code in order to save several pages in a loop.
The problem acuur, while its in prosses. The desktop is flickering, assume when the hidden dialog being closed.
Have someone an idea how to resolve it?
--UPDATE--
In realese mode there is a problem in varibal m_bUpdateUI that somehow is always false!!!
Some idea??
thanks.
Great and Excellent job!
|
|
|
|

|
http://www.codeproject.com/shell/iesaveas.asp?msg=483194#xx483194xx
|
|
|
|

|
Thanks.
What about the flickering prob?
|
|
|
|

|
Hi
I am working in Win32 API SDK, at my program, I am hooking IE window and I am using my own BHO dll (whenever IE is open, dll will attach with IE browser) through this dll I want to save the complete web page without prompting the save as dialogbox. With your example help, I tried by using as follows
HRESULT hr = m_pWebBrowser->ExecWB(OLECMDID_SAVEAS,
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
I used MSOCMDEXECOPT_DONTPROMPTUSER options, even though I am getting dialog box and even if try to save the web page through save as dialog box also, page is not saving. I am getting the error msg "This Web page could not be saved".
Can you please help me to save the complete web page without prompting save..as dialog box.
Thanks in Advance
Baskar
|
|
|
|

|
How can I save the modified HTML page to local using C++?
|
|
|
|

|
You have to switch IE in edit mode first. There are numerous articles available out there (even a few on codeproject if I remember well).
|
|
|
|

|
I need to modify the HTML form's value (say one entry field Name) and then save this HTML page with the given name to the local machine. I tried to use this example to save the HTML page to local, it is OK , but the page does not contain modified value (name) in the entry field. Could you explain more and any alternative to do this in C++?
|
|
|
|

|
Did you (anyone?) ever find a solution how to save the modified html page to mht? I would be interested to know.
Regards, Fredrik
|
|
|
|

|
I can't get this to work with Win98 even if use the tip mentioned in the previous thread. It seems to hang before it even gets to that point. If anyone can help I would greatly appreciate it.
Best regards,
Norrie Taylor
|
|
|
|

|
Great article but it fails for me using IE6 on Win98. I think the reason is that the dialog IDS are different. For example GetDlgItem(hwnd, 0x47c) returns NULL for me in UpdateSaveAs.
Does anyone know either
1. What the correct dialog IDS for win 98
2. Which dll the resource is in so I can try to find out the dialog ID
3. A way around this problem.
Cheers
|
|
|
|

|
Appologies for answering my own question but the dll in question is COMDLG32.DLL and the SAVEAS resource in this has the following id change
editbox filepage = 0x480 (0x047c on xp)
so if you change the code in
void CSaveAsWebbrowser::UpdateSaveAs(HWND hwnd) to use this ID when running on 98 it works fine.
|
|
|
|

|
Thanks for the follow up. I admit I didn't want to install a vmware with a WIN98 guest OS only to retrieve that damn ctrl id.
|
|
|
|

|
Thanks, This follow up saved my butt!!
|
|
|
|

|
How would you retrieve that ctrl id? I have a win98 guest running but I can't get spy++ to run on win98. Now I am kinda stuck.
Thanks
|
|
|
|

|
If you can't get spy++ to run, then this doesn't bode well for the rest. You can find alternatives to spy++ in codeproject.
Also I wonder why the ip provided in this thread (id = 0x480) wouldn't work for you, unless you have a totally different version of IE - a version where the file dialogs would be hooked by a third-party or something like that.
I admit the way of trying to achieve the save as mhtml is not that good in practice. It's probably bes tto either rely on a third-party (read old threads), or reuse the IE cache to get the bits and create the mhtml yourself.
|
|
|
|

|
Thanks for the quick reply.
It seems that in Win 98 there is a problem getting the handle to the "Save Web Page" dialog.
In the callback proc under XP three dialogs actually get processed during the HCBT_CREATEWND case. The "Save Web Page" being the third and last. You can trace the names of these dialogs as they pass through the call back. However, in Win 98 only two two seem to pass through the callback function, none of which have the name "Save Web Page". However, the window still gets moved to the side.
Without the third and last window going through the callback proc the handle never get saved. Thus you can't manipulate the window later on.
Got any ideas?
Thanks again!!!
|
|
|
|

|
Well I found a work around that I think might make this slightly more stable and that would fix my issue mentioned above.
In the callback function just replace this:
if (hwnd == g_hWnd)
with this:
TCHAR buff[512];
GetWindowText( hwnd, buff, 512 );
if ( strcmp( buff, "Save Web Page") == 0 )
Best regards,
Norrie
|
|
|
|

|
About the print dialog hook.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie55/html/wb_print.asp
Page Cannot Be Found
We apologize for the inconvenience, but the page you are seeking cannot be found in this location.
googled no result too.
Sing when we're programming.
|
|
|
|

|
Hello
When I tried to ren your demo application, It flases an error saying that
---------------------------
Browser.exe - Unable To Locate Component
---------------------------
This application has failed to start because MFC70D.DLL was not found. Re-installing the application may fix this problem.
---------------------------
Can u give me solution for this problem?
Thanks in advance...
ajay sonawane
|
|
|
|

|
Recompile the source code with VC6.
|
|
|
|

|
I'm using WebBrowser embedded in my application.
I just need to get one image after it is downloaded and displayed,
I have it's URL and IHTMLImgElement interface (but this interface contains only methods for getting image's file size and date, not it's local name).
Is it a good idea to use this solution, or is there some easier way ?
Thank you
rrrado
|
|
|
|

|
Here is how you would do that with C# (http://www.codeproject.com/jscript/htmlgetshooked.asp?msg=774194&mode=all&userid=42845#xx774194xx). With C++, use UrlDownloadFile (or something like that instead of the C# webrequest helper).
|
|
|
|

|
Thank you, but unfortunately image I need to download is not cached because of HTTP cache control, and is dynamically created, so it is different every time it is downloaded. So I can't use this solution.
rrrado
|
|
|
|
|

|
Use Winpcap to sniff the image is the most easy solution, if it is not cached and you can/may not turn this of in your browser.
|
|
|
|

|
Hi I'm trying to use this code in .EXE (the code is actually in a DLL) and save the current IE Web page. I'm using http://www.codeproject.com/shell/iehelper.asp[^] to get an IWebBrowser2* for the instance of IE.
My first problem was that ExecWB() always failed. I replaced that with lpOleCommandTarget->Exec() which works.
My next problem is with SetWindowsHookEx(). I can't use GetCurrentThreadId() as that is my app. I've tried setting this to NULL and setting hMod to the DLL hInstance but the VC++ debugger spits the dummy. If I set hMod and dwThreadId to NULL SetWindowsHookEx() fails.
So I figure if I can get the threadid for the IWebBrowser2* object, that may work. Any ideas how to get the thread id for an IWebBrowser2* or any other suggestions on how to get this to work in app where I just want to get IE to save its current page to a mht.
Thanks a bunch for any help. It has been a very long day of head scratching.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|

|
Neville Franks wrote:
My first problem was that ExecWB() always failed. I replaced that with lpOleCommandTarget->Exec() which works.
Doesn't sound good. The article embeds the browser within a MFC view. Is your app really different from that?
Neville Franks wrote:
My next problem is with SetWindowsHookEx(). I can't use GetCurrentThreadId() as that is my app.
Unless IE as running in a separate process, there is no reason not to use GetCurrentThreadId(). The thread id acts as a filter and since we hook the system, waiting for a dialog box to appear, is kind of required to avoid hooking a dialog box from another app. Of course, if IE is in a separate process, it's a totally different story : in this case, may be you can get that active InternetExplorer_ServerWindow by enumerating the windows, and the find the running thread.
All in all this does not sound too much practical anyway. Creating the archive file yourself may be just as convenient, and less dependent to IE, therefore less prone to errors and potential hangs. I would definitely recommend this route : either buy a third-party generator (see the comments below), or build your own (I did from one of my sharewares and it was much more easy then I predicted).
Good luck!
|
|
|
|

|
In the IE history directory,you can see the internet address you have accessed.I can use the IShellFolder to get the interface of the object,but I cann't get the URL of an item.Is there a simple way to get the URL of an item in the IE history directory?
|
|
|
|

|
The official way of retrieving the browser history is to use the IUrlHistory interface (Platform SDK, urlhist.h), available with IE5.5 and up.
Of course, it's just as smart to do like you did, get the user's History IShellFolder, then start traversing all underlying IShellFolder nodes. You need a special algorithm for that, since there are particular names, etc. Your best bet in my opinion is to get one or two pieces of code that try to mimic Windows Explorer, and supports all the underlying shell namespaces. I know there are a couple of those available in codeproject articles.
Good luck!
-- modified at 5:14 Saturday 5th November, 2005
|
|
|
|

|
I want to set URL of the Internet Explorer through Visual C++ program.
If we have given a set of links and now my program will set first link and SaveAs the HTML page and proceed to the next link.
Thanks,
Shri
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
This article demonstrates how to automate IE's Save As functionality
| Type | Article |
| Licence | |
| First Posted | 4 Sep 2002 |
| Views | 272,422 |
| Downloads | 5,979 |
| Bookmarked | 88 times |
|
|