|
It seems there has been a misunderstanding when I readed your first message. My apologies.
When you use AfxLoadLibrary to map a DLL to the address space, it's DllMain (Or if you use MFC, it's CWinApp-derived object's InitInstance) gets executed on a seperate thread. This is a feature of AfxLoadLibrary, but I don't believe it will pose a problem.
It, however, means that you cannot pass C++ CWnd or CDialog objects (or their addresses) from the DLL to the main application. This will cause an assertion in the debug version of MFC, and most obviously, a crash in the release version.
You CAN pass the HWND of the dialog, if you need to post messages to it, or alternatively, create an exported function (from the DLL) to send the messages. Afterall, the function you export gets called within the DLL's thread, as you use GetProcAddress to get a POINTER to that function, which you then call from the main application.
Like said, if you export a function from the DLL which returns the HWND of the dialog, you can use this HWND to pass messages to the dialog. However, you can not return the address of the CWnd/CDialog object from the DLL. This violates the above-mentioned object sharing aspect.
The reason why I used custom message pumping in my application was because my application did not have a main window at all. MFC is designed to shut the thread down if, after the execution of InitInstance returning TRUE, the m_pMainWnd member of CWinApp is NULL.
I could've created my own dialog for the example application: I just didn't feel it necessary. Otherwise, your and my app work similarly. Both load a DLL, both create a dialog in that DLL. My case just is that I am force-running the thread to prevent framework from shutting it down before I want it to.
But, like you said, the problem is solved after you changed the plugin dialog to modeless. Good luck for the future development of the app, and feel free to ask if you run into any more problems
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
No apologies necessary. I learned from our discussion and appreciate your time and effort and your example. After all you were the only one to respond so again I say thanks. This does not seem to be an area that most people have a lot of experience with. I know that it has been eye opening experience for me.
One final question though, you mentioned that:
Antti Keskinen wrote:
It, however, means that you cannot pass C++ CWnd or CDialog objects (or their addresses) from the DLL to the main application. This will cause an assertion in the debug version of MFC, and most obviously, a crash in the release version.
Since I am not currently using AfxLoadLibrary could I if I wanted pass a CWnd handle of my dll back to the main application? I am not clear on that point.
- Steve Messer
|
|
|
|
|
In short, you can pass the HWND of the Windows object bound to a CWnd from the DLL back to the main application. This is legal. Now for some explanation:
I ran into a strange problem while creating the example app, and when debugging, my application fired an assertion as I created the CDialog in the DLL and then passed the active C++ object's address to the main application. Here, the term "active" refers to an MFC object means that is bound to an existing Windows window/GDI/whatever object. An "inactive" object would be one that has not had it's 'Create' method (or any other initialization method) called.
Here is an exerpt from wincore.cpp, a MFC source file which defines the behaviour of CWnd::AssertValid, among other things.
ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
ASSERT((CWnd*)p == this); <DIV>
</DIV>
So, like you see on the commented lines, passing the addresses of created C++ objects from one thread to another is a dangerous business, especially if the object is bound to a Windows GDI object already.
The reasons for this are in the core functionality of the MFC. Like you might already know, MFC is just a (huge) collection C++-based classes, which encapsulate the functionality of the major Windows base services (Windows, pens, brushes, DCs, sockets and so on). This is why it is so difficult for most people to make the difference between MFC and the Windows API.
Building on this theory, you now understand why the passing of an active CWnd object's address is dangerous: the object itself is created on a seperate thread, and if you call it's methods, they are executed in the context of the seperate thread as well. The Windows window object bound to the CWnd exists on the seperate thread as well. So, if you were to use the DLL's existing, active CWnd object's address or a reference to it in order to construct a new CWnd object in the main application, you would most likely be greeted by an access violation. Cross-thread communication is very vulnerable to causing those. However, you can store the object's address and call it's methods through a pointer. This is completely fine and legal
Alternatively, you can always use a simple HWND variable in the main application, and use Windows API's SendMessage to post messages to that HWND.
Just create an exported function to the DLL which returns the HWND of the Windows window bound to the CDialog/CWnd object in question. Then call this function through a pointer from the main thread, and vot, you have the HWND.
MFC Reference, however, cautions us from binding two CWnd objects to a same HWND handle, as this may result in serious implications if one of the object is destroyed while the other is still attached to the Windows window object. The destructor of CWnd, by default, attempts to destroy the underlying Windows window object as well. So, if you pass the HWND, use the API's SendMessage to send your message to the window. Do not wrap the HWND into a new CWnd object.
The most safest way is to use pointers. Cross-thread pointers are a very safe way to exchange information between two (or more) threads.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Very informative I am sure your information will save me hours of headaches in the future.
Thanks,
-Steve Messer
|
|
|
|
|
I'm throwing up a message box inside the OnGridEndEdit function of a CGridCtrl object. I want to inform the user that a duplicate name has been entered and a unique one must be supplied. However, after the message box is clicked on, the cursor highlights cells in the grid control and its a wierd side effect. Any suggestions?
Here is the code:
<br />
void RDialogForEditingCanalObjects::OnGridEndEdit(NMHDR *pNotifyStruct,LRESULT* pResult)<br />
{<br />
bool bAcceptChange = false;<br />
CGridCellBase* pRow = NULL;<br />
<br />
NM_GRIDVIEW* pItem = (NM_GRIDVIEW*) pNotifyStruct;<br />
<br />
if (this->m_eCanalObjectType != CO_SSFC) <br />
{<br />
<br />
if (pItem->iRow == 1 && pItem->iColumn == 1)<br />
{<br />
<br />
pRow = this->m_PrimaryGrid.GetCell(pItem->iRow,pItem->iColumn);<br />
<br />
if (pRow) <br />
{<br />
switch(this->m_pCanMan->IsNameUnique(pRow->GetText())) {<br />
case 0:<br />
Beep(999,189);<br />
Beep(999,189);<br />
MessageBox("Please enter a unique name for this object",<br />
"Duplicate Naming Error!",MB_OK);<br />
bAcceptChange = FALSE;<br />
<br />
break;<br />
case 1:<br />
bAcceptChange = TRUE;<br />
break;<br />
} <br />
<br />
}<br />
}<br />
} <br />
}<br />
|
|
|
|
|
All,
I am trying to compile some code that uses the FILETIME structure. When I try and compile it I get the following error message:
c:\Documents and Settings\Me\My Documents\my projects\CPP Projects\First Project\Hello World Proj\Form1.h(27) : error C2872: 'FILETIME' : ambiguous symbol
could be 'C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\WinDef.h(354) : _FILETIME FILETIME'
or 'stdafx.cpp(0) : System::Runtime::InteropServices::FILETIME'
It appears that there are two different declarations for FILETIME. When you search the MSDN Library for just "FILETIME" it tells you to just include windows.h. If you search the MSDN Library for "about FILETIME structure" it says that it is located in the namespace system.runtime.interopservices. I should mention that I have both an include of windows.h and a line for:
using namespace System::Runtime::InteropServices
If I comment out the using namespace line in order to fix the error I get a profusion of different errors because I use message boxes and apparently they need that namespace definition.
c:\Documents and Settings\me\My Documents\my projects\CPP Projects\First Project\Hello World Proj\Form1.h(208) : error C2653: 'MessageBoxA' : is not a class or namespace name
Thanks in advance for any ideas,
Robert
|
|
|
|
|
Here's two options:
1) Qualify FILETIME as being in the global namespace as: ::FILETIME, so that the compiler knows you are not refering to the one in System::Runtime::InteropServices.
2) Instead of importing the entire InteropServices namespace, either qualify them explicitly, or just include the classes that you actually need (e.g. using System::Runtime::InteropServices::Blah).
Dave
http://www.cloudsofheaven.org
|
|
|
|
|
I want to change a toolbar bitmap image Inbox to a different bitmap (or a bitmap with a very different color background) when there are messages in the Inbox. Or some way to give the user an alert that there are new messages in the Inbox. Can this be done?
Elizabeth
|
|
|
|
|
One quick method would be to have two cpies of the same toolbar in your resources which have the same buttons, but one has a different image. When you need to switch bitmaps, you just call pToolbar->LoadToolbar() with the correct resource id for the correct images you want.
I do somehing similar in an app of mine to switch between small/large icons and it works fine.
Roger Allen
Sonork 100.10016
Death come early, death come late,
It takes us all, there is no reason.
For every purpose under heaven,
To each a turn, to each a season.
A time to weep and a time to sigh,
A time to laugh and a time to cry,
A time to be born and a time to die.
Dust to dust and ashes to ashes,
And so I end my song.
|
|
|
|
|
I tried out your method. However, the toolbar flashes whenever the mouse is over it. I had LoadToolBar() at ON_UPDATE_COMMAND_UI(ID_INBOX, OnUpdateInbox). The flashing is very annoying.
Elizabeth
|
|
|
|
|
It sounds like you just need to add a small amount of extra processing that only calls LoadToolbar() when a change in the button state is required. That should remove the flashing in the ON_UPADTE() handler.
Roger Allen - Sonork 100.10016
If your dead and reading this, then you have no life!
|
|
|
|
|
I added some lines to set state of the toolbar, but once it gets out of ON_UPDATE_COMMAND_UI, the state is reset. What I am trying to do is to set the toolbar button ID_INBOX to TBSTATE_PRESSED when there is new mail and TBSTATE_ENABLED when there is no new mail. But the toolbar keeps flashing when I move the mouse over it. Here is some code:
if (pDoc->NewMail())
{
if (m_wndToolBarCtrl.GetState(ID_INBOX) != TBSTATE_PRESSED)
{
m_wndToolBar.LoadToolBar(IDR_MAINFRAME_NEWMAIL);
m_wndToolBar.GetToolBarCtrl().SetState(ID_INBOX, TBSTATE_PRESSED);
}
}
else
{
if (m_wndToolBar.GetToolBarCtrl().GetState(ID_INBOX) != TBSTATE_ENABLED)
{
m_wndToolBar.LoadToolBar(IDR_MAINFRAME);
m_wndToolBar.GetToolBarCtrl().SetState(ID_INBOX, TBSTATE_ENABLED);
}
}
Elizabeth
|
|
|
|
|
hi, im tryin to find some simple code for a water effect in opengl. basically something i can use for an ocean effect. any ideas?
bik
|
|
|
|
|
I downloaded GLUT a week ago, and it has a pretty cool underwater demo which you might be able to modify or use directly.
Glut for win32[^]
If you can keep you head when all about you
Are losing theirs and blaming it on you;
If you can dream - and not make dreams your master;
If you can think - and not make thoughts you aim;
Yours is the Earth and everything that's in it.
Rudyard Kipling
|
|
|
|
|
Hi,
I think you can find more information in this forum...
http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/010669.html[^]
If you read the discussion, you will find out that there is no such thing as simple water effect (if it is simple it is not a water effect). There are also a couple of good article links in the above discussion.
Good Luck...
Orhun Birsoy
|
|
|
|
|
I Apple Mac OS file system.. the files do not have extensions.. but when you open the file, it open with the right creator application. For example,
you create a document using MS Word application and save it without the extension. and close it and you reopen the file again, it opens with MS Word without prompting (like Window OS) openWith dialog.
From what I understanding, Mac OS uses file header or something that tells the type of the file and OS use it, get the right application to open with to open the file
I tried to use the example from Microsoft.com http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/enumall_sample.asp
but only works for Word and Excel files.. others it just dies
Can we do same think like it using c++ or vb for Window OS???
|
|
|
|
|
The given link just works on Microsoft Office files - it looks for values defined in the Microsoft standard, and so will not work on anything else. From memory, the Mac has some meta-information for each file which it uses to determine what to open it with. However, I also recall reading that Apple have deprecated this feature (possibly in favour of file extensions).
If you want to have automatic filetype detection in Windows then you'll have to use file extensions - I dont see this as a problem, and it makes identifying them for a human easier as well. If you want automatic detection within one of your own programs then you can implement your own meta-information, and put a header onto your files, or have an index describing what the file is.
|
|
|
|
|
so what you are saying the given link is just works for Microsoft Office files.. so how come only excel and word files could read but not access and powerpoint files..
<br />
If you want to have automatic filetype detection in Windows then you'll have to use file extensions - I dont see this as a problem, <br />
yes there is a problem in detecting file type base on the file extensions..
because some of the files do not have file extensions and human have to figure it out by trying to open the file with several application to see whether if the file is readable with that application or this application.
and it makes identifying them for a human easier as well.
so it is not easier for human.
it takes time to open on file without the extensions..if i can write the function that could determine the file type, not base on extension, I can just open/print the right application (programmatically)
sometime the file extension is .doc but the file was created with Adobe Acrobat because someone has changed the file extension.
so finding out the file type depending on the file extension is not really good.
I just wondering if MAC can tell the file type of the file without file extension, is there any methods or ways to do the same as MAC
|
|
|
|
|
I have a function show where I have the
following statements:
cout<
|
|
|
|
|
Try to send the fileout as an argument to your function
void parint (offstream &fileout,char *string)
{
fileout<
|
|
|
|
|
Also, you should consider writing an operator << for your class ( I presume all this data is in a class ), then you can just stream the whole lot to any stream type you like, in one go.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
I am just learning C++ can you give me an example how to do this?
|
|
|
|
|
I've written articles here on the CP site on how to do this, so search the site for iostream and look for my name as author.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
I am googling around "what is a callback function" and sort of have gotten the general idea. I've been doing some MFC for a year or so, but havent yet seen it used. I'd appreciate some links to more info on what these are exactly and when they are used since obviously I havent run into a situation where I needed one....
Thanks,
ns
|
|
|
|
|
Callback functions are used in Win32 APIs (eg: during printing). MFC provides more formal callbacks in the form of handlers that you can override, eg: CWnd::OnSize() which is called by the framework when the size of the window has changed.
In OO code, callbacks are usually implemented using the Observer pattern, where your custom code (the callback) is executed when an event of interest occurs.
/ravi
Let's put "civil" back in "civilization"
Home | Articles | Freeware | Music
ravib@ravib.com
|
|
|
|
|