I am trying to create a new frame window with toolbars inside a dll.
I was able to create the frame and the toolbars but however the messages do not work properly in the CToolbar. Particularly the ON_UPDATE_COMMAND_UI messages are never called in the DLL.
After some research I came to know that this is because
PreTranslateMessage(MSG* pMsg)
and
OnIdle(LONG lCount)
need to be called.
But my calling application is Delphi based and this cannot be done.
After research I came to know that this is best possible from an Extension dll.
Since MFC extension dlls can only be called from an MFC application. I thought of the following solution.
Delphi calls an regular MFC dll
The MFC dll calls the Extension dll.
But I have run into problems because of asserts in in MFC AfxGetResourceHandle() and AfxGetInstanceHandle().
But I am also aware that AFX_MANAGE_STATE(AfxGetStaticModuleState()); cannot be called from an extension dll.
Does anybody have a solution for this problem?
The ON_UPDATE_COMMAND_UI messages are created by the MFC message loop. You don't have one. You will have to build your own ON_UPDATE_COMMAND_UI translator or something equivalent. It all starts with this in your frame window message map:
ON_WM_INITMENUPOPUP()
Your OnInitMenuPopup handler will be called when the user selects a menu, before the menu is displayed.
Related
I have big,old MFC source code. It is very difficult to debug the code. I am using Spy++ to examine one of the dialog. Following is snapshot of Spy++ of the dialog of MFC application.
Is there any way to find name of class of Dialog, or dialog ID?
Secondly, is there any tool in Visual Studio (using 2008) which can map button callback with correct method of source code.
I know second question sounds greedy, but just trying to see if this type of tool exists?
Launch the Debugger.
Run the application.
Hit Break All
Look into the call stack
You should find the code location that calls DoModal. And there you find the appropriate class that is used.
We have a VB6 application that we have provided extended functionality through an MFC DLL. However, there's a specific problem with CDialog-based classes in the DLL. We pass in Me.hWnd from the VB6 app's main form to give to the CDialog constructor so that DoModal() knows what its parent is. Although the CDialog-based classes are staying on top of the VB6 app on DoModal(), they do not block the VB6 app the way that's expected by a modal dialog. That is, while the DLL dialog remains in front of the EXE's window, I can still click the button that called the DLL, showing the dialog again (and again).
There's not much to show from the VB6 code. As I mentioned it just passes in Me.hWnd. The MFC code is simple enough:
HWND exeHwnd = pSessionContext->GetHWnd(); // our state container for the DLL
CWnd* exeWnd = CWnd::FromHandle(exeHwnd);
MyCDialog dlg(exeWnd);
INT_PTR result = dlg.DoModal();
// waits, stays in front, but does not "block" the window
switch (result) // ...
I traced the values along the way and confirmed window handles with Spy++. Everything seems to be fine. Any ideas what I'm missing or doing wrong?
ADDITIONAL INFO
That hwnd value is used elsewhere for MessageBox and works as expected.
A simplistic solution might be to disable the parent VB6 app in the VB6 code just before calling the DLL, and when the DLL code returns re-enable the VB6 app. Something like this (air code)
Me.Enabled = False
MagicDLL.ShowTheDialog(Me.hWnd)
Me.Enabled = True
I am writing a DLL written in MFC to be used by other application.
project settings:
1. Use MFC in static library
2. preprocessor : AFXDLL
3. MD Build
I have also used AFX_MANAGE_STATE (AfxGetStaticModuleState()) before calling
CWinApp which internally calls InitInstance and DLL main.
This Dialog has tab in it and I am able to see only the first tab all other tab are coming as blank. When I am running the same DLL as exe (with required changes) its working fine.
Also DLL is crashing when i am calling AfxGetApp() ?
I suppose major problem is due to DOMODAL(). Can anyone tell what might be the issue of tab control not working?
Update I found out that CRichEditCtrl was the problem. In dialog tab I had this as well when I removed this It worked fine. Can anyone know the reason of this..
I have used AfxInitRichEdit2() before in InitiInstance()
I am new to MFC so let me know if you need any more info
You have to call AfxInitRichEdit() before the rich edit control is used.
Do you call AfxInitRichEdit2 in InitInstance of the EXE?
Try putting it in the DLL's InitInstance too!
First of all: Is this even possible?
I have a third party dll that interfaces some hardware. It's written in MFC. I received (from the dll vendors) a sample Visual Studio 2010 solution which has only one project: An MFC application (.exe) which calls the third party dll in question. It works fine.
When I try to use the third party dll from my dll (which is plain C++, no MFC, no .NET), I can call its functions fine, but there's a catch: the sample MFC app seems to "override" MessageProc in order to capture certain messages that the third party dll generates. And though the dll has a function called "RegisterFuncCallback" and I use it, my callback never gets called.
So here's the problem: How can I capture those messages without creating an MFC app? (Is it even possible?)
Alright, I made it. Here's how:
Create a class which inherits from CWnd
Declare a message map associating the desired messages and their handlers
When creating the Window, use the CreateEx function (I did it in my class's constructor), and pass it the HWND_MESSAGE flag in the last but one parameter. This will create the window as a "Message Window", that is, invisible.
Once I'm done initializing the window and the MFC dll, I call RunModalLoop on my hidden window, in a separate thread, since it's blocking. This fires up the message pump, and starts receiving the MFC dll's messages.
Edit: I could finally do it using just Win32 API. Here's my story, code included:
Programate Algo Blog. Don't worry, it's in English.
If the DLL works with Win32 messages you won't get around them. But you do not neccessarily need MFC for that, a simple WinAPI solution would suffice. MFC just wraps the Win32 API. If those messages aren't Win32 messages, you do not need a Win32 application.
I would like to have the ability to process Win32 messages in a console app and/or inside a standalone DLL.
I have been able to do it in .NET with the following article and it works great in C# inside a console app and standalone DLL
http://msdn.microsoft.com/en-us/magazine/cc163417.aspx
Is there a way to do the equivalent with C/C++ Win32 APIs? I have tried doing RegisterClassEx(...) and CreateWindow(...) even passing in HWND_MESSAGE to hWndParent but the trouble is that after the "invisible" window is created messages are not being processed probably due to the lack of a message pump.
Where would the message pump go if you had a DLL entry point? I have tried creating another thread in a DLL and put while(GetMesage(..)) there but that did not work either.
Any ideas?
You need a message pump yes. The window also has thread affinity so it needs to be created on the same thread that you're running the message pump on. The basic approach is sound, if you include more code it may become clear what the problem is.
In addition to what Logan Capaldo said, you also have the problem that, as a DLL, you don't know at compile time what kind of process is going to be loading you at runtime.
If you are being loaded by a console application (/SUBSYSTEM:CONSOLE), then creating a hidden window of your own and setting up a message pump on that same thread will work fine (as long as you are the first window created).
If you are being loaded by a windows app (/SUBSYSTEM:WINDOWS) then you might run into problems getting messages. They will be sent to the top-level window in the hierarchy, which you didn't create. You'll need to get the hWnd of the main process and subclass it (if you aren't already).
If you are being loaded by a service, then you aren't going to get window messages at all. You instead need to use the RegisterServiceCtrlHandlerEx Function