|
The problem is the 'order of construction' problem for global variables.
If the global/static 'cListBuilder1' and 'cListBuilder2' objects are constructed BEFORE the global 'g_list' object, then the calls to 'g_list.AddNode' are most likely failing (because g_list does not yet exist, so you can't add to it). Note that this means you can call a member function of an object that has not yet been constructed!! This is perfectly valid C++ code, but not likely to be what you want. You are probably lucky that you are getting just 'failed function call' - often this behaviour will lead to crashes.
Why would the 'listBuilder' objects be created before 'g_list'? Well, since they are all global objects in different compilation units, the order of construction is undefined - the compiler/linker can schedule the calls to the required constructors in any order they like - as long as all global objects get constructed before the 'main' is called. What makes this kind of problem even worse is that the order of construciton can change simply by adding a new global variable into some file in the project - in this case, the compiler/linker can totaly change the order of global constructions, causing previously "working" code to now fail.
The solution is to use "Create On First Use" semantics for the g_list object. This means you don;t make it a global - you create it the first time it is used (the first call to "AddNode" from a global 'cListBuilder' object constructor, for example. To implement this, put the variable into a function, like this :
cLinkedList& g_List()
{
static cLinkedList theList_;
return theList_;
}
Now, your constructors for the cListBuilder become :
class cListBuilder {
cListBuilder()
{
cData* poData = new CData;
g_list().AddNode("NodeName", poData);
}
};
Since the ListBuilder construtor is now calling a function 'g_list()' rather than a variable 'g_list' you do not have to worry about the order of construction. The rules for static variables inside functions means that the internal 'theList_' object is created only once, and only when the function is called. The function cannot be called without creating the static variable, unlike memeber functions of global variables (which can be called from constructors of other objects before the 'owning' object's constructor!).
I think the reason this was working in an EXE and not the DLL is just blind luck - although, you should note that if all 3 global varaibles are in the same compilation unit (eg, the same cpp file) then the order of construction is normally fixed at the order of the variable declarations (but I'm not sure if the language guarantees this!)
|
|
|
|
|
Aaaah, now I get it. I tried your suggestion and now it works like
a charm (woohoo!) Thanks for the help!
Steve The Plant
|
|
|
|
|
Hello all,
I know that when you export a function from a dll that uses MFC dynamicaly, you have to use the AFX_MANAGE_STATE() macro.
If you export a class from a dll that links to MFC dynamically , do you have to use the AFX_MANAGE_STATE() macro in each member function of the class? If so, what about protected and private functions that won't be called by the client app???
Thanks!
|
|
|
|
|
Hi all,
I'm in the process of writing a Text Viewer application. Notepad does not open large files, and Wordpad opens them but reads them all into RAM and brings the OS to its knees with the swap files, etc.
What I want to do is to open a text file and just read in the portion of the file that should be showing (and some extra for caching, but not terribly urgent right now). Then as the user runs the scroll bar, I would redraw the text that I need to redraw.
A future addition to this program will be for other file types, so I wil have a class to work with Text drawing, and then add other classes as necessary to draw TIFF's or our own file format, etc.
Unfortunately, as I work with this, I keep running into problems with MFC.
I'm working with MS Visual C++ 6.0, SP 4, MFC 6.
Using CScrollView I can print the file, and print preview, but when I try to scroll the file on the screen, it chops off the top, or the bottom, or chops the bottom off lines of text, etc.
Any thoughts about a good way to go about this? Is ScrollView too much of a "helper" if you're not planning on reading the whole file into RAM? Would CView be better? Should I just scrap MFC and write it using the APIs myself?
Any thoughts would be appreciated.
Jeff
|
|
|
|
|
Oops, additional info.
I'm currently working on Windows 98, but any solution would need to work on Windows NT and Windows 2000 as well.
Thanks for any info
Jeff
|
|
|
|
|
Thanks for who that answer me on this question.
But I have still problem with it.
my code is so :
-------------------------------------------------------
CFile file;
CFileException ex;
if(!file.open(str_pathName, CFile::modeRead, &ex))
{
//error
}
else
{
//open
}
.
-------------------------------------------------------------------------
when I run it I gets this error:
: error C2039: 'open' : is not a member of 'CFile'
c:\program files\microsoft visual studio\vc98\mfc\include\afx.h(1202) : see declaration of 'CFile'
Error executing cl.exe
-----------------------------------------------------------------------------
------ WHY ???????????????????????
|
|
|
|
|
Is Open, no open, with Capital 'O'
Cheers!!!!
Carlos Antollini.
|
|
|
|
|
detail , please!
|
|
|
|
|
Incorrect Case:
file.open(str_pathName, CFile::modeRead, &ex)
Should be:
file.Open(str_pathName, CFile::modeRead, &ex)
|
|
|
|
|
thank you very much !!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
|
Hi *.*
I have written an MFC application in MS Visual C++6. Now I want to compile it with a different compiler but the one from MS. Is there a way to compile the whole project with borland's c++ compiler?
Are there any other good (or even better) compilers you can recommend?
thanks
|
|
|
|
|
I once used the Borland CPP Builder 4 VC++ Project Conversion Utility on a simple VC6 MDI project just to test. Worked well. My version of Builder has MFC files that corespond to VC5, but that wasn't a big issue for the simple test app.
|
|
|
|
|
I'm looking for some documentation on serial port communication in VC++. Does MFC support it?
- john
|
|
|
|
|
Never mind, I'm a moron. However it wouldn't let me delete my previous message, so I'm just saying I figured it out (and feel stupid)
|
|
|
|
|
Now I really wonder what I missed. Is there a nice class for this?
Eric Hansen
ehansen@pmsi.cc
|
|
|
|
|
Is there a nice class for this?
Look at P.J. Naughter's Serial Port class right here on CodeProject.
|
|
|
|
|
I couldn't find any classes in MFC for Serial Port Comms back when I was looking (about one year ago) so I started to write one...but that project has been on hold for a LONG while now. Unfortunately I'm a bit short on time right now so I'm just going to cut up some of my code send it along, hope it helps (I've never posted code to one of these but I have a feeling this isn't going to be that easy to read ).
Opening a port:
if (portOpen)
{
return portHandle;
}
else
{
// Try to open the comm port
char str[30];
sprintf( str, "\\\\.\\COM%d", portNum );
HANDLE hCom;
DWORD dwError;
hCom = CreateFile( str,
GENERIC_READ | GENERIC_WRITE,
0, // comm devices must be opened w/exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hCom == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
TRACE0("Invalid Comm Handle in openPort()\n");
// handle error
return NULL;
}
else
{
portOpen = true;
portHandle = hCom;
return hCom;
}
}
Example of writing to and reading a response from a comm port (setting baud rate etc):
DCB dcb;
fSuccess = GetCommState(portHndl, &dcb);
if (!fSuccess)
{
// Handle the error.
}
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(portHndl, &dcb);
if (!fSuccess)
{
// Handle the error.
}
//unsigned char lpData[140] = {1,0,0,16,85,0,1,0,0,0,0,0,0,0,0,103 };
DWORD numActual = 0;
OVERLAPPED osWrite = {0};
BOOL succ;
DWORD error;
succ = WriteFile(portHndl,
sendBuffer, //Data to write to comm port
sendBytes, //number of bytes to write
&numActual, //pointer to number of bytes written
&osWrite // pointer to structure for overlapped I/O
);
if (!succ)
{
error = GetLastError();
TRACE("Bad Comm Write: %d,%d\n",portHndl,error);
}
else
TRACE("Good Comm Write: %d,%d\n",portHndl,error);
succ = ReadFile(portHndl, // handle of file to read
receiveBuffer, // pointer to buffer that receives data
receiveBytes, // number of bytes to read
&numActual, // pointer to number of bytes read
&osWrite // pointer to structure for data
);
if (!succ)
error = GetLastError();
Eric Hansen
ehansen@pmsi.cc
|
|
|
|
|
I have found how to replace the file type combo in the File "Open" dialog with a new one graphically. I want to replace the standard combo box with CComboBoxEx so I can put icons next to the types. But once I do that - how do I communicate to the common dialog when the user selects a new file type? The original file type combo box of the common dialog is still available but invisible. Both combos have the same text. I have tried to programatically set the selection of the original combo to that of the extended combo thinking that that action would cause the appropriate updates but it does not work. Any ideas?
|
|
|
|
|
> I have tried to programatically set the selection of the original combo
> to that of the extended combo thinking that that action would cause
> the appropriate updates but it does not work.
I don't think hidden windows send notifications, so you could try changing the selection and the explicitly sending the CBN_SELCHANGE notification to the dialog using the original combo-box's window handle.
UINT nID = ::GetDlgCtrlID ( hOldCombo );
SendMessage ( WM_COMMAND, MAKELPARAM ( nID, CBN_SELCHANGE ), hOldCombo );
Not sure if this will work, since I've never tried it.
-Ben
"Its funny when you stop doing things not because they’re wrong, but because you might get caught." - Unknown
|
|
|
|
|
Looks like the reply here is for another topic. Anyone with any ideas for the original question?
|
|
|
|
|
It looks like the response here is for another thread. Getting back to this now and no luck yet. Any responses still greatly appreciated
|
|
|
|
|
I want to record a sound and play a sound in MFC! How will I do that....
Is there any classes that supports multimedia? I know about the MCI.... but I only have code in Win32
HELP!!
/*
BETA
*/
|
|
|
|
|
You may want to check out.. http://www.codeproject.com/audio/fister.asp
Rob Jones
|
|
|
|
|
You may want to check out.. http://www.codeproject.com/audio/fister.asp
Rob Jones
|
|
|
|
|
I want to run one program from my code in two ways; (a) run it and wait until it closes, and (b) run it, and then later on check if it is still running and if so, shut it down.
I use ShellExecute() to run it (successfully), giving me an HINSTANCE.
I was under the impression that MsgWaitForMultipleObjects() would be able to wait until the program had finished, so I used this:
MsgWaitForMultupleObjects(1,(HANDLE *)&hInst, TRUE, INFINITE, 0);
but it doesn't wait, it just goes right on to the next statement. I also tried QS_ALLINPUT originally for the last parameter; no change. I'm not quite sure what that last parameter does exactly.
So, how do I wait for that program to finish? WaitForSingleObject() says it is not advised to use it in case the run program creates other threads (or something like that, it's all too deep for me), which is why I used MsgWait...().
Also, in 16-bit MFC you could call GetModuleUsage() to find out if the hInst was still running... how do I do this in 32-bit MFC? Also, how do I get a handle to the main window of that EXE from that hInst?
Lastly, some functions such as GetModuleFileNameEx() require a module handle AND a process handle... MSDN says a module is an EXE or DLL, so if my hInst is an EXE, how on Earth do I get the process handle it belongs to? Or are they one and the same in this case?
Help!
|
|
|
|
|