|
Do you mean an image on a web page that links to another page ?
If so you should look at the HTML DOM interfaces.
Start with IHTMLDocument2 .
|
|
|
|
|
thanks for your reply.
Yes, I want to get all the page link and image address in some web page in depth 5.
When use the Regular expression. I find that some error URLwill be got.
|
|
|
|
|
Create an HTML DOM object and use the IHTMLDocument2::write to load the HTML.
Now use IHTMLDocument2::get_images to get a collection of all the images in the web page.
Iterate through the collection to get the IHTMLElement interface for each image.
Now call IHTMLElement::getAttribute with SRC as the attribute name to get the source URL of the image.
Here is an article to help you with manipulating the HTML DOM - Capture an HTML document as an image[^]
|
|
|
|
|
|
Hi,
I am having trouble with VariantCopy() when the source variant is a VT_ARRAY. I have used VariantInit() and VariantClear() on the destination variant as suggested on MSDN but VariantCopy still does not work. It works OK with non-arrays but then thats easy. In the code fragmet below, pValue points to a VARIANT containing array data.
VariantInit(&m_value);
VariantClear(&m_value);
HRESULT hr = VariantCopy(&m_value, pValue);
if(FAILED(hr))
{
TRACE("Failed to copy variant\n");
}
I can't find any useful examples on MSDN. Anyone have any idea as to where I am going wrong?
Thanks
Tony
|
|
|
|
|
Its OK, I found the cause of the problem. All the time I was thinking that there was something wrong with the destination variant but in fact it was the source variant that was messed up. I had set the variant type to VT_ARRAY, but failed to say what type of array it was e.g. m_value.vt = VT_R8 | VT_ARRAY.
Tony
|
|
|
|
|
I'm trying to use the RegEnumValue function, but I can't get the correct values in the ValueName and data fields
Its seems that the enum itself is ok since its runs the correct number of loops and the sizes parameter are correct.
I get the same result again and again in the ValueName valuedata fields.
Thanks in advance for any help
here is the code I'm using
HKEY hKey = NULL;
LONG enumresult = 0;
WCHAR valuename[1024];
DWORD valuenamesize = 1024;
DWORD valuedatasize = 1024;
WCHAR valuedata[1024];
long index = 0;
const WCHAR* subkey = L"Software\\xxx";
if( RegOpenKey(HKEY_LOCAL_MACHINE, subkey ,&hKey) == ERROR_SUCCESS)
{
while( RegEnumValue(hKey, index++, valuename, valuenamesize, 0,
NULL, (LPBYTE)valuedata, valuedatasize) != ERROR_NO_MORE_ITEMS)
{
cou<
|
|
|
|
|
Are you sure this code works?
I'm asking because the valuenamesize is a pointer to a DWORD and you're simply passing a DWORD instead.
|
|
|
|
|
In addition to what Superman said, valunamesize is an in/out paramter, which means that it will be changed when the function completes.
You need to be sure to reset it to a proper value before each call (i.e. within your while loop).
Hope that helps.
Karl - WK5M
PP-ASEL-IA (N43CS)
PGP Key: 0xDB02E193
PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
|
|
|
|
|
Thanks, That was the problem, needed to reset the size parameters
|
|
|
|
|
Arnon A wrote: cou<<valuedata;< blockquote="">
Shouldn't this be wcout ?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
I have run into a very strange error today and was wondering if anyone else has seen this. Some digging on google suggests it might be a compiler error. I've seen this on VS2008 and GCC 4.1.2.
I was able to build a test harness to repro the issue. It is below:
<pre>
#include <iostream>
class Cloneable
{
public:
template<class TYPE> TYPE* clone() const { return dynamic_cast< TYPE* > ( clone() ); }
virtual Cloneable* clone() const = 0;
};
// simple template class that defines an interface
// for cloning objects.
class X : public Cloneable
{
public:
X(int _y ) : data(_y) { }
virtual ~X() { /* DO NOTHING */ }
virtual Cloneable* clone() const { return new X(data); }
protected:
X() { /* DO NOTHING */ }
int data;
};
class Y : public X
{
public:
Y(double f, int y) : X(y), dataf(f) { /* DO NOTHING */ }
virtual ~Y() { /* DO NOTHING */ }
virtual Cloneable* clone() const { return new Y(dataf, data); }
protected:
double dataf;
};
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char* argv[])
{
X* x = new X(1);
X* x1 = x->clone<X>();
Y* y = new Y(2.12, 4);
Y* y1 = y->clone<Y>();
delete y;
delete y1;
delete x;
delete x1;
return 0;
}
</pre>
The clone<TYPE> fails in both cases in the main function. It should cast properly. There seem to be two ways to fix this. If i move the templated function from Cloneable to X & Y it works in both cases. The other is to use clone() in the main function and dyna cast there.
A standard C cast in the templated function also doesn't work. Its like the compiler is erroneously changing the protection level on the function and then gets confused and just dumps out the error.
<pre>
1>Compiling...
1>main.cpp
1>.\main.cpp(40) : error C2275: 'X' : illegal use of this type as an expression
1> .\main.cpp(12) : see declaration of 'X'
1>.\main.cpp(40) : error C2059: syntax error : ')'
1>.\main.cpp(43) : error C2275: 'Y' : illegal use of this type as an expression
1> .\main.cpp(24) : see declaration of 'Y'
1>.\main.cpp(43) : error C2059: syntax error : ')'
</pre>
Anyone seen this work in a different compiler or know of a workaround to make it compile (aside from the ones I mentioned)?
--
Joseph Dempsey
Sr. Software Engineer
joseph_r_dempsey@yahoo.com
<div class="modified">modified on Friday, November 5, 2010 2:18 PM</div>
|
|
|
|
|
You're code is not fully visible.
Make sure "Encode < characters while pasting" option is checked while you paste your code.
|
|
|
|
|
It was already checked. It shows up fully in my browser (chrome) and in IE just fine. Not sure why you can't see it.
--
Joseph Dempsey
Sr. Software Engineer
joseph_r_dempsey@yahoo.com
|
|
|
|
|
I'm using chrome and this is what I see -
#include
class Cloneable
{
public:
template TYPE* clone() const { return dynamic_cast< TYPE* > ( clone() ); }
virtual Cloneable* clone() const = 0;
};
class X : public Cloneable
{
public:
X(int _y ) : data(_y) { }
virtual ~X() { }
virtual Cloneable* clone() const { return new X(data); }
protected:
X() { }
int data;
};
class Y : public X
{
public:
Y(double f, int y) : X(y), dataf(f) { }
virtual ~Y() { }
virtual Cloneable* clone() const { return new Y(dataf, data); }
protected:
double dataf;
};
int main(int argc, char* argv[])
{
X* x = new X(1);
X* x1 = x->clone();
Y* y = new Y(2.12, 4);
Y* y1 = y->clone();
delete y;
delete y1;
delete x;
delete x1;
return 0;
}
|
|
|
|
|
ok... not sure whats going on there but i tried repasting it with and w/o the checkbox and it still shows up erred.
Its missing the angle brackets obviously. The code itself is correct syntactically. Just pretend they are there If you're real interested in seeing the actual file i can email it.
* EDIT: Screw it... just removed HTML completely. should show up right now.
--
Joseph Dempsey
Sr. Software Engineer
joseph_r_dempsey@yahoo.com
|
|
|
|
|
|
Good call, forgot about using using to add functions to the overload set.
Cheers,
Ash
|
|
|
|
|
Have a dig in the standard for the rules on overload resolution and how it interacts with template expansion. As both VC++ later than 2002 and gcc 4.x agree on the behaviour it's probably standard. Essentially it looks like what's happening is that clone<T> is not part of the overload set for Y::clone() and X::clone() as there functions with that name already in the class of the pointer you're calling through.
One of three solutions spring to mind. Either make clone<t> an ordinary function, change it's name or call it explicitly. e.g. if you change your base class to:
class Cloneable
{
public:
template<class TYPE> TYPE* clone_as() const { return dynamic_cast< TYPE* > ( clone() ); }
virtual Cloneable* clone() const = 0;
};
and change your client code to match things work the way I think you think they should. Incidentally be very careful writing code like this... You can write leaky code very easily:
int main()
{
X x( 7 );
Cloneable *p = &x;
Y *py = p->clone_as<Y>();
}
leaks an X. I'd be tempted to return shared_ptrs or auto_ptrs to avoid this sort of faux pas.
Basically the interaction between overloading, overriding and templates (i.e. when templates are expanded and considered part of the set of overload candidates) is a nightmare. My advice would be avoid it unless you're writing a compiler.
Cheers,
Ash
PS: This is very similar to the well known interaction between overrides and overloads with implicit conversion:
class base
{
public:
virtual void do_something( int ) { std::cout << "Doing the base class int thing" << std::endl; }
virtual void do_something( double ) { std::cout << "Doing the base class double thing" << std::endl; }
};
class derived : public base
{
public:
virtual void do_something( double ) { std::cout << "Doing the derived class double thing" << std::endl; }
};
int main()
{
derived d;
d.do_something( int( 7 ) );
}
This could always prints the derived class double message. You get around this by either changing the name or calling the function explicitly.
PPS: Superman's solution from the mouth of Bjarne would work as well - I didn't consider it as using declarations have their own fun properties which you may or may not be happy with.
modified on Saturday, November 6, 2010 2:48 AM
|
|
|
|
|
I wouldn't recommend to do it that way at all.. Let Clonable be what it is, an interface with no implementation, skip the template member completely. In your example you don't need to cast anything, if you use covariant return type for overrides of clone inimplementations of Clonable :
class X : public Cloneable
{
virtual X* clone() const { return new X(data); }
};
class Y : public X
{
virtual Y* clone() const { return new Y(dataf, data); }
};
int main(int argc, char* argv[])
{
X* x = new X(1);
X* x1 = x->clone();
Y* y = new Y(2.12, 4);
Y* y1 = y->clone();
return 0;
}
As suggested above, usage of an std::auto_ptr is preferable, but only in client code, since otherwise you loose the ability to define covariant return types. I am using a "Cloner" utility for comfortable casts to derived types which looks something like this:
class ClonerUtility {
template <class TCoVariantClonable>
static std::auto_ptr<TCoVariantClonable> CloneAs(const Clonable& pToBeCloned) {
std::auto_ptr<Clonable> tClone(pToBeCloned.clone());
if (TCoVariantClonable* tCoVariantClone =
dynamic_cast<TCoVariantClonable*>(tClone.get())) {
tClone.reset(0);
return std::auto_ptr<TCoVariantClonable>(tCoVariantClone);
}
return std::auto_ptr<TCoVariantClonable>();
}
template<class TCoVariantClonable>
static std::auto_ptr<TCoVariantClonable> Clone(const TCoVariantClonable& pToBeCloned) {
return std::auto_ptr<TCoVariantClonable>(pToBeCloned.clone());
}
};
int main(int argc, char* argv[])
{
std::auto_ptr<X> tX(new X);
std::auto_ptr<X> tCloneX = ClonerUtility::Clone(*tX);
Clonable& tPureClonable = *tCloneX;
std::auto_ptr<X> tOtherCloneOfX = ClonerUtility::CloneAs<X>(tPureClonable);
}
modified on Sunday, November 7, 2010 4:05 AM
|
|
|
|
|
I'm trying to get write a message-only window to receive device change notification messages for a USB device. I am using MFC, C++, and Visual Studio 2008. Everything compiles, and it runs without crashing or locking up, but the event handler is never triggered. The device of interest is installed on Windows as a virtual COM port.
My main application instantiates the class described below then waits for a character input from the keyboard polling using a while loop. It is during this wait time that I remove and insert my USB device expecting the event to get fired.
class CMessageOnlyWindow : public CWnd
{
DECLARE_DYNAMIC(CMessageOnlyWindow)
private:
DEV_BROADCAST_DEVICEINTERFACE * _pDevIF;
HDEVNOTIFY _hNotifyDev;
public:
CMessageOnlyWindow();
virtual ~CMessageOnlyWindow();
protected:
afx_msg BOOL OnDeviceChange( UINT nEventType, DWORD dwData );
private:
void RegisterNotification( void );
void UnregisterNotification( void );
protected:
DECLARE_MESSAGE_MAP()
};
For simplicity, I've removed all the cleanup and error-handling:
DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, \
0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);
IMPLEMENT_DYNAMIC(CMessageOnlyWindow, CWnd)
CMessageOnlyWindow::CMessageOnlyWindow()
{
CString cstrWndClassName = ::AfxRegisterWndClass( NULL );
BOOL bCreated = this->CreateEx( 0, cstrWndClassName,
L"CMessageOnlyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, 0 );
this->RegisterNotification();
}
CMessageOnlyWindow::~CMessageOnlyWindow() {}
BEGIN_MESSAGE_MAP(CMessageOnlyWindow, CWnd)
ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()
afx_msg BOOL CMessageOnlyWindow::OnDeviceChange( UINT nEventType, DWORD dwData )
{
switch ( nEventType )
{
case DBT_DEVICEARRIVAL:
break;
case DBT_DEVICEREMOVECOMPLETE:
break;
default:
break;
}
return TRUE;
}
void CMessageOnlyWindow::RegisterNotification(void)
{
_pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
_pDevIF->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
_pDevIF->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
_pDevIF->dbcc_classguid = GUID_INTERFACE_CP210x;
_hNotifyDev = RegisterDeviceNotification( this->m_hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
}
void CMessageOnlyWindow::UnregisterNotification(void)
{
UnregisterDeviceNotification( _hNotifyDev );
}
Any thoughts or suggestions would be much appreciated. If any details are missing, let me know, and I will be glad to add them. Thanks.
Does the message-only window need to be started in a new thread, or does creating a new window automatically spin off a new thread?
ADDITIONAL INFO
Changing the type of recipient handle passed to `RegisterDeviceNotification` to `DEVICE_NOTIFY_ALL_INTERFACE_CLASSES` caused it to start working. Do you know why that would make a difference, or are there any problems, if I leave it like this?
modified on Friday, November 5, 2010 12:18 PM
|
|
|
|
|
AFAIK the window will only get messages when it is "visible" and non-minimized, which means you should show it on the desktop, at any location you like, including (-1000,-1000) to keep it out of sight.
|
|
|
|
|
Thanks, Luc. I tried specifying a location with the same lackluster results:
BOOL bCreated = this->CreateEx( 0, cstrWndClassName,
L"CMessageOnlyWindow", -1000, -1000, 100, 100, 0, HWND_MESSAGE, 0 );
|
|
|
|
|
I was thinking you had to actually show the window (hence the off-screen coordinates), howver my source code (which is C#) doesn't, and works well. I'm afraid I can't help you.
|
|
|
|
|
Hi again,
I happened to require detection of memory stick insertions (in C# again), and experimented a bit more. My conclusion is the app needs a window that is shown, non-minimized, possibly off-screen, and then overriding the wndProc yields the necessary events. So I chose "manual window position" with a bounding rectangle of (-32000,-32000,100,100) and it works well; it does not when minimized or not shown at all.
|
|
|
|
|