|
If you use MFC you might look at CFileFind
Cheers,
|
|
|
|
|
|
|
u can also use API FindFirstFile()AND
FindNextFile()
|
|
|
|
|
I am very new to using Internet Explorer MSHTML Controls, mostly developing my code by gleaning the web for useful code snippits. However, I have not been able to find anything that addresses the issue I am having. Hopefully somebody knows the answer to my question. I found DHTMLUI on this site, but it only has placeholders for the "SELECT ELement" code I seek.
I am programming using Visual C++ version 6.0.
I am running Internet Explorer 6.0.3790.1830 on OS Microsoft Windows Server 2003 Web Edition Service Pack 1.
Background:
I am trying to automate a web-based management interface to our company's product. My first step is to come up with a proof-of-concept that will demonstrate that I can control any of the DOm elements that I encounter. After much Googling I have been able to write a C++ program to navigate the Internet Explorer web-browser to the desired login page, parse that login page and input username/password to login, parse the various frames in the subsequent frames, (as a test) and automatically click on all anchor links in the frame that contains "navigation-related" links and see another frame display the various different pages.
Question:
Now I am trying to set values in things such as SELECT/OPTION elements, radio inputs, etc.
However, I am having trouble with the SELECT/OPTION and radio inputs. The problem is that there is an "onchange=<javascript_function>" in the SELECT and radio inputs. I have tried to select an option in various ways, and the visible browser does in fact show the Selected value in the GUI changes, but for some reason the onchange javascript function does not execute.
Does anybody know how to do what I am trying to do? How can I debug this issue? I feel that the "event" for onchange is not "firing". I read some user group posting (from another website) that made an off-handed reference to a possible bug in IE, but I would be surprised if that were true because I think I am doing something very basic.
FYI, here is the HTML that contains the example select/option item I am trying to control/automate via MSHTML C++:
10
25
50
100
All
Basically, it is supposed to refresh the screen with more items-per-page depending on what the user selects. When I manually do it with my mouse, it works fine. I just cannot seem to get it to do the ChangeRecPerPage() when I use IE MSHTML Controls. Here is a code excerpt of what I am doing in C++:
bool
Frame::SetOptionElement(IHTMLSelectElement*& prSelect, const char* pOptionName)
{
IHTMLOptionElement* ptr_option = NULL;
IDispatch* ptr_disp = NULL;
HRESULT hr;
long len = 0;
prSelect->get_length(&len);
// find and set the option value specified
for (int i=0; i < len; i++)
{
VARIANT var_index;
var_index.vt = VT_UINT;
var_index.lVal = i;
hr = prSelect->item(var_index, var_index, &ptr_disp);
if (FAILED(hr))
{
// error: could not get option item dispatcher
cerr << i << ") Could not get option item dispatcher " << hr << endl;
continue;
}
hr = ptr_disp->QueryInterface(IID_IHTMLOptionElement,(LPVOID*)&ptr_option);
if (FAILED(hr))
{
// error: could not get option item
cerr << i << ") Could not get option item" << hr << endl;
continue;
}
BSTR text;
ptr_option->get_text(&text);
CString text_str = text;
if(text_str.Find(pOptionName) >= 0)
{
cerr << "Found option named " << text_str << endl;
BSTR value;
hr = ptr_option->get_value(&value);
hr = prSelect->put_value(value);
/*
// Also attempted using put_selectedIndex with hard-coded index value.
// It did change the value shown (i.e. index 3 -> display "100"), but the
// displayed number of items per page remained.
long selected_index = 0;
hr = prSelect->get_selectedIndex(&selected_index);
long debug_selected_index = 3;
hr = prSelect->put_selectedIndex(debug_selected_index);
hr = prSelect->get_selectedIndex(&selected_index);
*/
return true;
}
}
return false;
}
|
|
|
|
|
The following is from MSDN documentation for onchange Event[^] (emphasis added):
Remarks
This event is fired when the contents are committed and not while the value is changing. For example, on a text box, this event is not fired while the user is typing, but rather when the user commits the change by leaving the text box that has focus. In addition, this event is executed before the code specified by onblur when the control is also losing the focus.
The onchange event does not fire when the selected option of the select object is changed programatically.
I've never worked with any of this, but I'd think you might be able to do what you want if, after changing the selection, you use IHTMLDocument4::createEventObject[^] to create an event, set the relevant properties for that event using the IHTMLEventObj Interface[^] (check the doc for the onchange Event[^] to see which properties are available for handlers), and finally use either IHTMLDocument4::fireEvent[^] or IHTMLElement3::fireEvent[^] to the fire the event yourself.
As a side note, I don't see in your code the Release calls for the COM interfaces you are acquiring. Consider using ATL's CComPtr[^] and CComQIPtr[^], which automatically handle that for you.
Hope that helps,
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
Thanks for the information. It gives me more to try. I do have a follow-up question to you or anyone else based on your reply:
Is there a way to programmatically (C++) make the select element "lose focus" after setting its value? Would that cause the event to fire?
Any example code to create an event would also be helpful. I just recall I looked at the fireEvent interface but it was not readily apparent what to do. But I will look again.
Thanks again.
|
|
|
|
|
SureshMahanty wrote:
Is there a way to programmatically (C++) make the select element "lose focus" after setting its value?
To make it lose focus, I think you could make something else get it, and yes, I think that would be possible, but...
SureshMahanty wrote:
Would that cause the event to fire?
I don't think so.
SureshMahanty wrote:
Any example code to create an event would also be helpful.
As I said before, I've never worked with this so I'm afraid I can't offer any concrete example.
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
Thanks Jose. I was actually posting the follow-up to anyone who may want to respond. I appreciate the info you have given already.
If anyone has pointers on how to use the fireEvent method to fire an onchange event for a particular SELECT Element, that would be much appreciated. Here is what the MSDN documentation says for fireEvent:
IHTMLDocument4::fireEvent Method Internet Development Index
Fires a specified event on the object.
Syntax
HRESULT fireEvent( BSTR bstrEventName,
VARIANT *pvarEventObject,
VARIANT_BOOL *pfCancelled
);
Parameters
bstrEventName
[in] BSTR that specifies the name of the event to fire.
pvarEventObject
[in] Pointer to a VARIANT that specifies the IHTMLEventObj
interface from which the event properties are obtained.
pfCancelled
[out, retval] VARIANT_BOOL that receives one of the
following values:
VARIANT_TRUE - Event fired successfully.
VARIANT_FALSE - Event was cancelled.
If I just want to fire the onchange event, does anybody have a clue what the parameters values should be?
Should bstrEventName literally be set to "onchange"?
How do I create an IHTMLEventObj for pVarEventObj and what would the "event properties" be? It must somehow include a "handle" to the specific DOM object (i.e. the specific SELECT element) or some sort of event "handler". I am just using those terms as a "lay person", rather than exact meanings.
Also, I am not sure how to get the IHTMLDocument4 object...I already have an IHTMLDocument2, do I just "redundantly" call queryInterface in the same way/context that I got the IHTMLDocument2 object, except query for IID_IHTMLDocument4?
BTW, I ordered "Programming Internet Explorer 5" and hopefully it will help with this question (whenever it arrives). But unfortunately, I need to try to push forward regardless of whether it arrives or is useful.
|
|
|
|
|
Hi guys,
I have an application tool which needs to safely and effectively close down other applications. I have seen a few posts on here about getting the PROCESSENTRY32 structure and then issuing a TerminateProcess command on it, however, this doesn't seem the safest method. Using SendMessage(WM_CLOSE,0,0) appears to be a safer option. Therefore my question is: is it possible to get a window handle to the main window created by a known PROCESSENTRY32 structure?
Thanks in advance,
Simon
|
|
|
|
|
Try using EnumWindows. Look it up on MSDN. EnumWindows will look at every windows handle for you, and then you just need a way of telling which window you want!
You need to write a function that EnumWindows will call. In this function use GetWindowText or GetClassName. Then compare each window with the text or class name you know you're looking for. How do you know what the text or class name for the window is? The text is easy. That's what's displayed in the bar at the very top of the window. The class name is better, if the program you're targeting has a stable class name. To find the class name of the window you want to target use Spy++. Be careful, though, because a program can have several windows and several class names for the windows. You just have to make sure to get the class name of the parent.
This method works great! I've used it myself. You have to be careful, though, because not all programs will let you close them safely. Internet Explorer or Windows Explorer (I think they're virtually the same thing) won't close if you send them the WM_CLOSE message. But hey, if you can find a way to safely close them, I'd like to know too!
Danny
|
|
|
|
|
srev wrote:
herefore my question is: is it possible to get a window handle to the main window created by a known PROCESSENTRY32 structure?
this will help
Is it possible to get info between HWND and Process handle?[^]
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
|
|
|
|
|
Any recommendations from those who tried both? I would like to use something simpler like RMI for C++[^], but it's still young and under development, and I need something mature, stable and scalable
My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
|
|
|
|
|
did you have a look at ICE[^]?
|
|
|
|
|
Very interesting. Too bad it is GPL, and at this point I can't purchase a commercial license.
My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
|
|
|
|
|
Nemanja Trifunovic wrote:
Any recommendations from those who tried both? I would like to use something simpler like RMI for C++[^], but it's still young and under development, and I need something mature, stable and scalable
XML-RPC[^] seems to have gained momentum as lightweight alternative for distributed computing (disclaimer: haven't tried it).
|
|
|
|
|
Nah, too much overhead. This needs to be a binary protocol.
BTW, I have already worked with SOAP, and it seemed to me that it was a XML-RPC killer.
My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
|
|
|
|
|
Hello,
I tried CORBA, but I (and every other student) didn't like it. You have incredibly much initialization to do and additional servers to run if you want maximum flexibility and scalability.
If it's no problem for your client to integrate the CORBA infrastructure and you can get passed the initialization, everything works like a charm. As far as I know (D)COM, your code with CORBA will look much more cleaner.
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
Who can help me to add to a title bar a menu( or a dialog ) in a MFC SDI application?
NG
|
|
|
|
|
Hi,
Is it possible to create a macro that would create an instance of a class? I'm trying this but the compiler won't accept it:
#define Logger() (MyLogger tempLogger(__FUNCTION__, __FILE__, __LINE__))
Thanks
Hua-Ying
|
|
|
|
|
|
error C2059: syntax error : ')'
error C2146: syntax error : missing ')' before identifier 'tempLogger'
error C3861: 'tempLogger': identifier not found, even with argument-dependent lookup
|
|
|
|
|
class MyLogger
{
MyLogger( char*, char*, char*)
{
}
};
#define Logger() (MyLogger tempLogger(__FUNCTION__, __FILE__, __LINE__))
no error on visual c++ 6.0...
NG
|
|
|
|
|
The syntax error only occurs when I try to use the macro. The errors are:
error C2059: syntax error : ')'
error C2146: syntax error : missing ')' before identifier 'tempLogger'
error C3861: 'tempLogger': identifier not found, even with argument-dependent lookup
Hua-Ying
|
|
|
|
|
#include <iostream>
using namespace std;
#define Logger() MyLogger tempLogger(__FUNCTION__, __FILE__, __LINE__)
class MyLogger
{
public:
MyLogger(char *pFunction, char *pFile, long Line)
{
cout<
|
|
|
|
|