|
Create a Sink to the desired event and fire your own program to download instead
1) Get a pointer to the connection point container (IConnectionPointContainer).
2) Call the FindConnectionPoint method to find the connection point that you want. For Internet Explorer 4.0 you want the DWebBrowserEvents2 connection point interface. (Optionally, you can call EnumConnectionPoints to enumerate through all the connection points that the server supports.)
3) Advise the connection point that you want to receive events. Pass a pointer to the IUnknown interface of the event sink. Remember that the connectable object will use the IUnknown pointer to query the client for the event sink interface. Most connectable objects will return a failure code from Advise if the client does not support the event sink interface. In the case of Internet Explorer 4.0, if the client does not support the event sink interface, Internet Explorer 4.0 will then query the client for IDispatch.
4) Implement IDispatch::Invoke to handle any events that are fired.
5) When you no longer want to receive events, you can call Unadvise and pass it the cookie that you got from the call to Advise
Cheers
Alfadhly
<marquee>
whoop there it is...
|
|
|
|
|
Hey guys,
I'm new to using MFC and to programming in general. I'm having great difficulty with Using CString to read off reg_sz values from the registry.
I keep getting this Debug assertion after i leave the function i have these registry reads in
Program: MyApp
File: dbgheap.c
Line:1011
Expression:_CrltsValidHeapPinter(pUserData)
exception 03h in my MyApp.exe
heres the function snippet:
DWORD dwType =0, dwSize=256;
.........
.......
float ftemp;
for(int i=0; i<6 ;i++)
{
//open key
......
RegQueryValueEx(tempKey,"Label", NULL, &dwType,(BYTE*) RegRead.GetBuffer(256), &dwSize);
RegRead.ReleaseBuffer();
//convert string to float value
ftemp=atof(LPCTSTR(RegRead));
m_sClass->Function(i,ftemp,value);
.......
m_sClass->Function1(i,ftemp,value,value2);
}
Once i leave the function this loop is contained in, the compiler throws that degug assertion. If i remove all references to this operation i dont get the assertion. Therefore i assume im using CString wrong somehow. Am i? What is the proper way to make the registry read then?
Background:
I am trying to retrieve a float value i wrote to the registry as a REG_SZ and then use it.
This may be a stupid question but it's not to someone new at this.
I appreciate any help
"DWORD my man!"
|
|
|
|
|
I've been programming in MFC since 1994, and I never directly modify the CString buffer, it just seems wrong to me.
Why not just use a character array? What do you gain by futzing around in CString's underwear?
ie:
char buffer[256]; /* or */ char buffer = new char[dwSize];
RegQueryValueEx(tempKey,"Label", NULL, &dwType,buffer, &dwSize);
ftemp=atof(buffer);
delete buffer; // (if 'new' was used)
Having said that, I wasn't able to duplicate your error, and your use of CString seems correct. There is a very thin registry wrapper class in ATL called CRegKey. It saves you a little trouble. Here is my test of your problem, using both CRegKey and your direct api calls:
<br />
#include <stdio.h><br />
#include <afx.h><br />
#include <atlbase.h><br />
<br />
void Function1(float f)<br />
{<br />
printf("ftemp: %f\n",f);<br />
}<br />
<br />
#define USE_CREGKEY<br />
void main(int argc, char* argv[])<br />
{<br />
DWORD dwType =0, dwSize=256;<br />
float ftemp;<br />
CString RegRead;<br />
<br />
#ifdef USE_CREGKEY<br />
CRegKey myKey; <br />
LONG result = myKey.Open(HKEY_CURRENT_USER,"deleteThisKey",KEY_READ);<br />
<br />
ASSERT(result == ERROR_SUCCESS);<br />
<br />
for(int i=0; i<6 ;i++)<br />
{<br />
result = myKey.QueryValue(RegRead.GetBuffer(dwSize), "Label", &dwSize );<br />
ASSERT(result == ERROR_SUCCESS);<br />
RegRead.ReleaseBuffer();<br />
<br />
ftemp=(float)atof(LPCTSTR(RegRead));<br />
<br />
}<br />
<br />
#else<br />
HKEY tempKey;<br />
RegOpenKeyEx(<br />
HKEY_CURRENT_USER,
"deleteThisKey",
0,
KEY_READ,
&tempKey
);<br />
<br />
for(int i=0; i<6 ;i++)<br />
{<br />
<br />
::RegQueryValueEx(tempKey,"Label", NULL, &dwType,(BYTE*) RegRead.GetBuffer(256), &dwSize);<br />
RegRead.ReleaseBuffer();<br />
<br />
ftemp=(float)atof(LPCTSTR(RegRead));<br />
<br />
}<br />
#endif <br />
<br />
Function1(ftemp);<br />
}<br />
When I use the registry, I like to use Sam Blackburn's WFC utility classes. He has a CString aware class called CRegistry that should be included in MFC. Even if you don't use the classes, Sam has done a super job of giving us great windows/MFC code to use as examples.
http://www.samblackburn.com/wfc/
I'm sorry I couldn't pinpoint your problem, but I hope this helps.
Jim
PS: Be sure you close tempKey with RegCloseKey(tempKey) when you are done with it. CRegKey does that for you.
|
|
|
|
|
Jim thank you for all your help and effort. I took your advice and used a good old character array and my problem magically went away. Lol, it is still bugging me though as to why that debug assertion ig getting thrown...lol i'll play around with it once i meet my deadline.
Thank You once again!
"DWORD my man!"
|
|
|
|
|
Is the application UNICODE? If so then there might be some problems with:
RegQueryValueEx(tempKey,"Label", NULL, &dwType,(BYTE*) RegRead.GetBuffer(256), &dwSize);
if this IS unicode then GetBuffer(256) will return 512 bytes (256 wchar_t) meaning your dwSize parameter is incorrect.
Another possible problem would be if the RegQueryValueEx is appending a terminating NULL. Try calling RegRead.ReleaseBuffer(-1) instead.
|
|
|
|
|
Hi,
I'd trying to spawn a thread from my class, and want the threadproc function to be a member function of the class.
I have defined the member function like this:
class MyClass
{
DWORD WINAPI ThreadProc(.......
.........
and the procedure that contains CreateThread is like this:
myhandle=CreateThread(...,ThreadProc,...);
It won't even compile... i get this error:
cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)
I don't want to use MFC in this app- trying to stick just to api functions. hence CreateThread().
I tried adding __stdcall, and also extern "C" to my function definition but to no avail.
I dont really understand this problem very well, any help would be much appreciated.
Thanks
Jon Hulatt
|
|
|
|
|
Declare the function as static.
|
|
|
|
|
Thanks- i did that, and with some tweaks it now works.
What exactly did the static declaration do? i looked in help docs but it didn't really make sense. does having a static member mean i can only have one instance of my class in the program?
Thanks again for your help!
Jon
|
|
|
|
|
|
> does having a static member mean i can only have one instance of my class in the program?
No, but it does have the effect of making all classes share the same member (in the case of a variable) and freeing it from the clutches of the class vtable (in the case of a function).
Basically, you're dealing with a language that has no built in threading support, so you need to ask the OS for it, and the OS is in C, and C only understands static ('global') functions in this context - you'll find you need to do the same thing if you want to pass a member function to something like EnumWindows as a callback procedure.
One other important note is that static member functions can't access non-static member vars, so if your thread proc needs to access some other members, you can pass a pointer to the class (e.g. this ) as a/the parameter to the threadproc function, then access members (with appropriate access locks) through this.
I think multi-threaded apps can give us some of the most difficult to manage code bases of all modern cs concepts. It can be very difficult to get right.
|
|
|
|
|
can someone suggest me how to go about making the Multiline list control using embeddedVC++. The regular method for desktop using VC++ just doesn't work anyhow in none of the ways.....
|
|
|
|
|
I have two property sheets that need to share a common set of CPropertypage(s) but I need the titles to change dependant on the parent CPropertypage. If I call SetWizardMode() any subsequent calls to SetTitle have no effect. Any ideas how to get around this?
Confused Programmer!
|
|
|
|
|
Hi.
Try to get parent frame (i'll called it pFrame) of each PropertySheet then type:
pFrame->SetTitle(lpszTitle);
pFrame->SetWindowText(lpszTitle);
I've notice that when you use SetTitle, the title is effectivly modify but on resize.
Use CWnd::SetWindowText to modify directly the title, but if you forgot to call SetTitle, then
on resize the title will restore to the previous name that why you should call two methods.
Unknown.
|
|
|
|
|
Thanks, but I'm just as confused......
I've added the following to the ::OnSetActive event of one of my pages:
CPropertySheet* pParent = (CPropertySheet*)GetParent();
CFrameWnd* pFrame1 = pParent->GetParentFrame();
CFrameWnd* pFrame2 = pParent->GetTopLevelFrame();
Both of the frame vars are null, I'm obviously missing my way to the parent frame! Can you advise?
Still Confused Programmer!
|
|
|
|
|
Once you're in wizard mode your property sheet will use the title of the current page as its title, so you need to change the title of the property pages themselves:
CTabCtrl* pTab = ((CPropertySheet*)GetParent())->GetTabControl(); //This assumes this code is in one of the pages
ASSERT (pTab);
TC_ITEM ti;
ti.mask = TCIF_TEXT;
ti.pszText = szTitleYouWant;
VERIFY (pTab->SetItem (nPageIndex, &ti));
|
|
|
|
|
Brilliant! - This works a treat, thanks.
|
|
|
|
|
Anyone know a good report writer tool with graphic editor and source code
for VC++??
Tanks
DL
|
|
|
|
|
Environment: VC++ 6.0, Windows NT 4.0
I'm trying to write a app that talks to a database
via Embedded SQL statements. The app is designed to run
continuously, looping through a small amount of code.
The Problem is that while generating the SQL statements,
memory is leaked by Constant Assigned Strings.
eg. CString fred = "fred";
The following code written to check memory usage:
void CTestSQLStringDlg::OnButton1() {
while(1) {
CMemoryState m1, m2, mdiff;
m1.Checkpoint();
fred();
m2.Checkpoint();
mdiff.Difference(m1, m2);
mdiff.DumpStatistics();
TRACE("\n");
}
}
void CTestSQLStringDlg::fred(){
CString string ="hello";
}
The Results (irrelevant data removed) were, after two loops:
mdiff - Total allocations: 18 bytes.
m1 - Total allocations: 7240 bytes.
mdiff - Total allocations: 18 bytes.
m1 - Total allocations: 7258 bytes.
As can be seen, each time through the loop, the Total Memory Allocations
increases by 18 bytes.
If a global CString is used, there is no memory leak ie:
CString str = "hello";
void CTestSQLStringDlg::fred(){
CString string =str;
}
Although I can use this workaround, it is very impractical to Globally
declare all of the constant strings I need.
I would like to know why this memory leak occurs or an alternate
practical work around??
Thanks
Simon
|
|
|
|
|
Simon,
Are you sure that a) the memory is truly leaking, and b) it is coming from the static CString? (I have trouble believing that CString, one of the most popular members of the MFC library, would leak memory. Also consider that CString uses reference counting; seperate CString objects set to the same static data always point to the same m_pchData, until one or the other is changed).
I suspect that what you're witnessing is a false memory leak; either that, or code in other parts of fred() is leaking memory. Using CMemoryStatus::DumpAllObjectsSince() shows no leaks when a static CString is alloted in fred(); perhaps using that function might better point out the exact location of any leaks which might exist.
Walter Gildersleeve
Freiburg, Germany
walter.gildersleeve@pe-gmbh.de
|
|
|
|
|
I agree with Walter. I set up a test with this code:
<br />
class CTestSQLStringDlg<br />
{<br />
public:<br />
void fred();<br />
void OnButton1();<br />
};<br />
<br />
void CTestSQLStringDlg::fred()<br />
{<br />
CString string ="hello";<br />
}<br />
<br />
void CTestSQLStringDlg::OnButton1() <br />
{<br />
int i=0;<br />
while(i<10) <br />
{<br />
CMemoryState m1, m2, mdiff;<br />
m1.Checkpoint();<br />
fred();<br />
m2.Checkpoint();<br />
mdiff.Difference(m1, m2);<br />
mdiff.DumpStatistics();<br />
TRACE("\n");<br />
++i;<br />
}<br />
<br />
}<br />
<br />
void main(int argc, char* argv[])<br />
{<br />
CTestSQLStringDlg ts;<br />
ts.OnButton1();<br />
}
I get no leak.
CString is the most popular MFC class, I really doubt that it is leaking, because if it were then almost no MFC apps would work for long.
Jim
|
|
|
|
|
Well,
CString is not the greatest thing since the sliced bread
"When CString::ReleaseBuffer is called and the length of
the string is less than the allocated buffer length,
the extra bytes are not released.
This just means that your program might end up maintaining more memory than absolutely necessary.
This will not cause a memory leak.
All of the memory will be freed when the CString object is destroyed."
This was the case for version 4.0 and earlier versions of VC.
I don't know if this is reaccuring in VC 6.0 .
It would be intersting though.
Cheers
Alfadhly
|
|
|
|
|
<RANT>
That particular bug is fixed in VC 6.0, but you can certainly cause problems by directly writing to the CString internal buffer. A "Releasebuffer" call just sends chills up my spine. I'd rather you use a few dozen goto's than write into the CString buffer.
As I pointed in another post here a couple of days ago, I've been writing MFC code since 1994 and have never directly changed a CString internal buffer. There is never a good reason to do this. Not ever. Not even once. I never told any one to lie. Using the evil GetBuffer/ReleaseBuffer members combines the worst features of C++ and C. I'm not against a nonmodifable pointer to the buffer ( like STL's c_str() ), but casting away the constness of the buffer is worse than murder.
I think that it is evil to muck about with the internal buffer of a string object. If you want to diddle with a buffer then make a proper buffer and party on. The fact that CString GetBuffer/ReleaseBuffer tempts you unzip it's pants and reach inside is the major reason that CString is not as good as sliced bread.
</RANT>
Jim
|
|
|
|
|
lol,
Sometimes it too scary to question the authorities, isn't?
Mike and his team recomended, posted it as a sample work around. So there.
Personally , I will use it when I use goto... but perhaps _asm is better
And don't shoot the masenger.
Cheers
Alfadhly
|
|
|
|
|
I really don't understand what you problem is with GetBuffer/ReleaseBuffer.
The reason you don't want to mess with the internal buffer is because you confuse CStrings internal state. GetBuffer/ReleaseBuffer provide a mechanism in which the internal state will stay correct.
There is no other reason to not use the internal buffer, and there is no difference between using CStrings buffer and allocating one yourself on the heap, except that if you need to copy the data into a CString anyways, you save the hassle of an extra copy.
GetBuffer/ReleaseBuffer were designed to be used this way, why not take advantage of it?
|
|
|
|
|
When I started with VC there was the known bug mentioned above. Even though that bug has been fixed, I still consider GetBuffer/ReleaseBuffer to be evil.
The reason is because they violate what seem to me to be good object oriented design critera.
I think that an object ought to manage its own interal state. But if you call "GetBuffer" then you have to keep this in mind:
"If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions. ... Note that if you keep track of the string length yourself, you should not append the terminating null character. You must, however, specify the final string length when you release the buffer with ReleaseBuffer. If you do append a terminating null character, you should pass –1 for the length to ReleaseBuffer and ReleaseBuffer will perform a strlen on the buffer to determine its length. "
Please gag me with a spoon. The way I read this is as follows: "If you call Getbuffer then we will lay these mines around. Try not to step on them."
Call GetBuffer and instead of having a nice solid string object that can take care of itself, you now have to stop thinking about the problem you are trying to solve and start thinking about your string object causeing a catastrophe. Let's see now, am I sure there will be null at the end? And what is the lenght of my string now? I wrote it down on a postit note somewhere, where did I put it? Why kid yourself using a string class at all if you are going to track the null character and the length yourself? Wouldn't it be more honest to just directly instantiate a buffer and use standard 'C' on it? At least then everyone seeing the code would know that you don't mind living on the edge.
It just seems to me that there would be fewer errors in the world if CString did not allow direct write access to its buffer. CString has all the members you need to make the string grow, shrink, jump, and dance all you want without worrying. Why not use them?
Now please me excuse while I write an expose on the "goto" statement.
Jim
|
|
|
|
|