|
Use the CreateThread function to initialize two HANDLE variables in your windows callback procedure. By default, the functions/objects associated with the handles will execute concurrently.
ralf.riedel@usm.edu
|
|
|
|
|
Create them both suspended, and then start them. Then ensure you are using whatever synchonization primitives are needed to get your threads working correctly. Go read Threads 101.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
When filling the BROWSEINFO struct, provide a callback function.
Use the following:
int CALLBACK MyBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED) {
LPCTSTR path = (LPCTSTR) lpData;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) path);
}
return 0;
}
LPCTSTR path = "c:\\whatever\\you\\want";
BROWSEINFO binf;
...
binf.lpfn = MyBrowseCallbackProc;
binf.lParam = (LPARAM) path;
pidl = SHBrowseForFolder(&binf);
Happy coding
Peter
The cops still stand around and eat koeksisters - Paul Watson, The Lounge, 2002
|
|
|
|
|
Hi, the following code is in a function. I'm doing multithread. When my thread function call this function, i got error message and program terminate......what happened????? HELP!!!!!
{
cs.Lock(); //Critical Section Lock
std::vector <SCHEDULER_MESSAGE>::iterator Scheduler;
if (!Scheduler_MSG.empty())
{
for ( Scheduler = Scheduler_MSG.begin() ; Scheduler != Scheduler_MSG.end() ; Scheduler++ )
{
if (((*Scheduler).msg == ABORT_MSG) || ((*Scheduler).msg == COMMIT_MSG))
{
std::vector <WAITQUEUE_STRUCT>::iterator Iter;
for (int i=0; i<NumOfDBObject; i++)
{
if (LockTable[i].CurrentThread == (*Scheduler).pThread)
{
LockTable[i].CurrentThread = NULL;
LockTable[i].CurrentLock = CurrentNoLock;
}
if (!LockTable[i].WaitQueue.empty())
{
for ( Iter = LockTable[i].WaitQueue.begin() ; Iter != LockTable[i].WaitQueue.end() ; Iter++ )
{
if ((*Iter).pThread == (*Scheduler).pThread)
LockTable[i].WaitQueue.erase(Iter);
}
}
}
Scheduler_MSG.erase(Scheduler); //Finished and erase this message
}
}
}
cs.Unlock(); //Critical Section Lock
}
|
|
|
|
|
Using erase on a vector invalidates the iterators.
Maybe if you changed your loop to...
while (!(!Scheduler_MSG.empty())
{
Scheduler = Scheduler_MSG.begin();
.... the rest of the code
}
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
So i change the code liked this:
while (!Scheduler_MSG.empty())
{
Scheduler = Scheduler_MSG.begin();
AfxMessageBox("Update start");
if (((*Scheduler).msg == ABORT_MSG) || ((*Scheduler).msg == COMMIT_MSG))
{
//AfxMessageBox("In the IF loop");
std::vector <WAITQUEUE_STRUCT>::iterator Iter;
for (int i=0; i<NumOfDBObject; i++)
{
if (LockTable[i].CurrentThread == (*Scheduler).pThread)
{
LockTable[i].CurrentThread = NULL;
LockTable[i].CurrentLock = CurrentNoLock;
}
if (!LockTable[i].WaitQueue.empty())
{
for ( Iter = LockTable[i].WaitQueue.begin() ; Iter != LockTable[i].WaitQueue.end() ; Iter++ )
{
if ((*Iter).pThread == (*Scheduler).pThread)
{
LockTable[i].WaitQueue.erase(Iter); <=====Something wrong here...
}
}
}
}
//AfxMessageBox("Before erase");
Scheduler_MSG.erase(Scheduler); //Finished and erase this message
//AfxMessageBox("After erase");
}
}
I found something wrong in the statement LockTable[i].WaitQueue.erase(Iter); (stated)... when i disable this line.....it's no terminate message.........how to change it?
Thanks!!!!!
|
|
|
|
|
It is the exact same problem. Calling erase invalidates the iterator.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Your iterator has been invalidated after erase. Change your loop to this and it should work fine.
for ( Iter = LockTable[i].WaitQueue.begin() ; Iter != LockTable[i].WaitQueue.end();)
{
if ((*Iter).pThread == (*Scheduler).pThread)
{
iter=LockTable[i].WaitQueue.erase(Iter); // chg here
}
else // chg here
{
++iter;
}
}
|
|
|
|
|
I have a button on my dialog window that i need to give it a function to get the value of an edit box and insert it into a combo box. I can get this working so that it can do it once. But what i really need is for it to hold the value in the combo box and store it there, then when i change the value of the edit box and press the button again to add it to the combo box, both the first value is still there as is also the second one.
Please oh please help me.
Help me to help you............(jerry maguire)
|
|
|
|
|
Maybe something like this would do the trick.
your_on_button_click_handler () {<br />
<br />
CString s;<br />
MyEditBox.GetWindowText ( s );<br />
int pos = MyComboBox.AddString ( s );<br />
MyComboBox.SetCurSel ( pos );<br />
<br />
}
cheers,
-Ben
|
|
|
|
|
Here's an obscure one for you. I fought this battle long ago and came up with a workaround, but we're now looking for a more legitimate solution than my hack.
Objects that are DECLARE_SERIAL depend on MFC's runtime class info. If you add a class to your program but do not instantiate an object of that type, you will not be able to deserialize this class from disk. This is because the linker scans the code generated from IMPLEMENT_SERIAL that adds a CRuntimeClass object to the global list of runtime class objects (that get traversed on serialization operations), and strips it out if there's no reference to that class. Pointers don't count. Consequently, when you try to deserialize a class that hasn't been instantiated, the global list routine politely asks, "Class? What class?" and declines the serialization request.
The hack was to have a function called at startup that just instantiated an object of each type on the stack. The linker saw the reference, and therefor didn't strip the code. Ugly, cheap & sleazy, but it worked.
However, now we want to do things "the right way" and actually understand and solve the problem. And so I put it to you, my low level guru friends, how the heck do you tell the linker to leave the darned object alone, regardless of whether or not it's been instantiated?
This is a quick summary of a rather obscure problem, be happy to offer further details. However, I'm thinking that I can't be the only one to have fought this battle. Any brilliant insights would be most appreciated.
Kapla.
Chistopher Duncan
Author - The Career Programmer: Guerilla Tactics for an Imperfect World (Apress)
|
|
|
|
|
Try /OPT:NOREF. That might do it.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Tim Smith wrote:
Try /OPT:NOREF. That might do it.
Man, I was hoping that it would be something that simple. Unfortunately, no joy. The search continues.
Hey, if you don't end up in the middle of the MFC code every now and then, you're just not having any fun, right?
Chistopher Duncan
Author - The Career Programmer: Guerilla Tactics for an Imperfect World (Apress)
|
|
|
|
|
This worked like a dream, I thought I would never find the solutions to this problem.
Thanks.
AndyC
|
|
|
|
|
This is a rather convoluted but IMHO safe and portable way:
template <typename T> struct instantiator
{
void serialize(CArchive& ar)
{
T t;
ar>>t;
ar<<t;
}
}
template instantiator<CMyClass>; You get the idea. Explicit instantiation of the template drags along all the equipment needed to serialize a CMyClass , which is then guaranteed to survive linker's stripping process. The code of the template itself is never executed, though.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Joaquín M López Muñoz wrote:
This is a rather convoluted
Hey, in the Real World, results are usually all that count! However, one of the things that we're looking to accomplish is to eliminate the maintenance issue of having to update a bit of code whenever we add a new class.
Pretty cool, though!
Chistopher Duncan
Author - The Career Programmer: Guerilla Tactics for an Imperfect World (Apress)
|
|
|
|
|
You can use some replacement for IMPLEMENT_SERIAL like this:
#define NONSTRIPPABLE_IMPLEMENT_SERIAL(class_name,base_class_name,wSchema) \
IMPLEMENT_SERIAL(class_name,base_class_name,wSchema) \
template instantiator<class_name>; which is affordable as for the maintenance burden.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Take a look at #pragma comment. My guess now is that the linker doesn't even realize you want the object included in the executable. Maybe you could place the RUNTIME_CLASS object in an include statement to force it.
#pragma comment (linker, /include:classCMyClass)
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
CListCtrl *pList = (CListCtrl *) GetDlgItem(IDC_LIST_REG);
int nrtn;
DWORD dw = pList->GetExtendedStyle();
dw = LVS_REPORT;
pList->SetExtendedStyle(dw);
TRACE( " did we set the style? %x \n",pList->GetExtendedStyle());
pList->SetItemCount(100);
nrtn = pList->InsertColumn(0, "Key" , LVCFMT_LEFT,500 );
nrtn = pList->InsertColumn(1, "Value" , LVCFMT_LEFT,500 );
|
|
|
|
|
LVS_REPORT is a regular style (SetStyle ), not an extended one.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
The app I'm working on is multithreaded. It dynamically loads several DLL's, all of which (I think) use a single entry point (not the approach I would have chosen).
I've written a new DLL (using appwizard) that uses MFC and also has a single entry point. This DLL uses COM, but CoInitialize and CoUninitialize are both called from the application itself. As far as I know, this is the only DLL in our app that uses COM.
hen I don't load this DLL, the program exits just fine (if you ignore the maddening memory leaks from Stingray). However, if I load my DLL, I get untraceable crashes when I try to shutdown the app in what appear to be very valid parts of the program.
The DLL appears to clean up itself properly, aand uinloads from memory propperly, so I don't think there's any problems with the DLL itself, but something connected with this DLL appears to be stomping all over creation when the program exits.
Any DLL experts out there that wanna take a swing at this?
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
When you say untraceable, do you mean that the IP address is in invalid memory?
If so, then chances are a DLL is getting unloaded while a window or callback etc is still using it. Run the program, get the crash and note the IP. Then run the program again, break it and see if the IP matches a DLL. That might give you an idea which DLL is getting goofed.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
You gotta see this code to envision my hell.
I can honestly understand some of the stuff they did, but it just seems to me that they made it harder to maintain. Objects that create pointers to themslves so that the programmer doesn't have to worry about calling delete himself. The ability to orphan the pointer so that you can call delete if you want to. Gads.
Anyway, there are callbacks in place, but I didn't change the application, I merely added the DLL to the list of possible DLL's that could load. None of the other DLL's are exhibiting this behavior, so I'm kind of at a loss as to even how to describe it.
I wonder if it's got anything to do with us using that damn stingray crap, and my DLL just pushed the whole application over the edge...
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Objects that create pointers to themslves so that the programmer doesn't have to worry about calling delete himself.
I really wish people would stop trying to make C/C++ idiot proof. It just makes it harder for really programmers to do their job!!!
Have you tried not unloading the DLL? There really isn't any harm in it.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
No, but I don't really have any control over that. The app exists in what amounts to an un-editable state, meaning I'm not permitted to change the app to work with my DLL. This actually makes sense to me because we have other DLL's that could be used instead of the one I've written that work the way the app is current written.
There are aspects of this code that are INFURIATING, but the legacy is over seven years old. Like any other project I've been involved with over the last 15 years, nobody wants to pony up the bucks to make the code more maintainable by programmers that are new to the team. There's an almost complete lack of real technical documentation, and most of the guys that wrote the original code are LONG gone.
Of course, in-source comments are non-existant in the most critical parts of the code, so the only wehicle we have is to review the source code one line at a time. I'm apprehensive about rebuilding the code unless we start from scratch because nobody is absolutely sure (and more often than not, not even remotely knowledgable) about how all the code interacts.
It doesn't help when the code exhibits an eclectic coding style and non-adherance to anything that could be called corporate policy about how to write/format the code. Add to that an insane lack of use of MFC except when (apparently) absolutely necessary, and things start to get real whacked out.
Finally, there's the issue of source code control. We use Visual SourceSafe, and most fot eh files are linked between major revisions of the code, so changing version 2 will also effect changes version 1. How absolutely stupid is that?
What's funny is that we all agree that it needs to be fixed, but upper management would just laugh us out of the office if we suggested that we take the time to do so at our own expense (without having a "customer" to pay the bill). The effort would probably require the better part of a year (or more) just because we no longer have the original authors availble to us, and we lack the documentation that describes the architecture.
Let this be a lesson to everyone else - you can NEVER have too much design and implementation documentation.
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|