I want to open a MFC modeless dialog from a MFC dll injected into another process, the dll's job is to hook the winsock send & recv, and the dialog will be the interface to communicate with the dll. The dll should be able to run the hook while the dialog is running.
BOOL CDriverApp::InitInstance()
{
CWinApp::InitInstance();
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxMessageBox("I'm In!");
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourAttach( &(PVOID &)RealSend, MySend );
DetourAttach( &(PVOID &)RealRecv, MyRecv );
if ((DetourTransactionCommit()) == NO_ERROR)
{
AfxMessageBox("Winsock hooked");
}
dlg = new ControlDlg();
m_pMainWnd = dlg;
if(dlg->Create(IDD_CONTROL_DLG))
{
dlg->ShowWindow(SW_SHOW);
}
//ExitThread(0);
return TRUE; <---
}
dlg is the dialog which is a member of CDriverApp
From what i have observed, the dialog is destroyed because the thread has exited and the memory that hold the dialog is removed.
The thread '_DllMainCRTStartup' (0x418) has exited with code 1657602048 (0x62cd0000).
I have read MFC modeless dialog close immediately thread, but my InitInstance() already returned true from the first place, so it's a different problem (i think)
So, my question is how to prevent the dialog from destroyed? Or perhaps prevent the thread from exit? or is it doable with a modal dialog?
This may be your problem:
Regular DLLs must have a CWinApp-derived class and a single object of
that application class, as does an MFC application. However, the
CWinApp object of the DLL does not have a main message pump, as does
the CWinApp object of an application.
Note that the CWinApp::Run
mechanism does not apply to a DLL, because the application owns the
main message pump. If the DLL opens modeless dialogs or has a main
frame window of its own, the application's main message pump must call
a routine exported by the DLL that in turn calls the
CWinApp::PreTranslateMessage member function of the DLL's application
object.
http://msdn.microsoft.com/en-US/library/f22wcbea(v=vs.80)
EDIT:
THis shows how to do what you are doing with a cWnd instead of a CDialog. Personally I think thats a better way to go.
http://codinganswer.com/c/cwnd-in-a-new-thread-in-a-dll.html
Here is an example of attaching a message hook to a modeless.
http://support.microsoft.com/kb/q187988/
Related
I am on a modal dialog and on the close of the modal dialog i want to exit application.
ASSERT(AfxGetApp()->m_pMainWnd != NULL);
PostMessage(WM_CLOSE, 0, 0);
But getting below exception form a member method for a private member variable of the modal:
Exception thrown: read access violation.
Is there any way to close application from ModalDialog safely?
In order to show the dialog, you would have called DoModal() from your application.
You can just exit the application after the call to DoModal();
dlg.DoModal();
//write code to exit application
You can check the return value from DoModal() and exit the application accordingly.
You ask how to post WM_CLOSE from a dialog to end your application.
and if this way to close application from ModalDialog is safely.
Yes, but you must post the WM_CLOSE to the MainWnd before closing the dialog.
The MainWnd have to handle the exit of the application.
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
END_MESSAGE_MAP()
void CAboutDlg::OnBnClickedOk()
{
ASSERT(AfxGetApp()->m_pMainWnd != NULL);
AfxGetApp()->m_pMainWnd->PostMessage(WM_CLOSE, 0, 0);
CDialogEx::OnOK();
}
In your CYouModal::OnDestroy() handler, call a PostMessage for main window with WM_CLOSE id. have you tried that ?
I made a thread to set some text on EditBox on Lobby Dialog. Below is my code.
And MainLobby is the Dialog Class. This project is "Dialog Based MFC Project".
MainLobby Lobby;
_beginthreadex(NULL, 0, ReceiveMessage, (void *)Lobby.GetSafeHwnd(), 0, NULL);
Lobby.DoModal();
But it doesn't work. Where is wrong? I thought hard but I couldn't find the answer.
I tried not Lobby.GetSafeHwnd() but Lobby.m_hwnd
unsigned WINAPI ReceiveMessage(void *arg)
{
HWND hDlg = (HWND)arg;
char msg[BUF_SIZE];
int msgLen;
while( (msgLen = recv(CClientApp::hSocket, msg, BUF_SIZE, 0)) != 0 )
{
SetDlgItemText(hDlg, IDC_LOBBY_CBOX, msg);
}
}
I am using MFC now. I will be glad a good idea.
The device context has to be updated.
Try:
UpdateData(true);
SetDlgItemText(hDlg, IDC_LOBBY_CBOX, msg);
UpdateData(false);
Or try it with a CString member variable for IDC LOBBY CBOX.
It is clear from your code that you are not using MFC properly. A Windows dialog based application does not require the programmer to explicitly create message handlers or receivers, that is what the MFC framework itself is doing for you. There is no reason to call beginthreadex before starting the dialog message loop as part of the DoModal method. When you invoke DoModal on any class descended From Dialog or DialogEX, the window is constructed, the member objects are constructed, and the message loop is started before the WM_INITDIALOG message is sent to the dialog for any other initialization before the dialog window is displayed. Once the window is displayed, the message loop is running, and text will display automatically in an edit control when you send it correctly. Normally one would declare a CEdit object with some name using the Class Wizard in visual studio then map the MFC object to the dialog object. Rather than type out all the details I will refer to this article: http://msdn.microsoft.com/en-us/library/6d1asasd.aspx
The dialog's HWND has not been initialized before DoModal is called. So your thread does not receive the proper HWND. The first place that you can access the correct HWND value is inside the dialog's OnInitDialog member function.
I see two problems in your code.
First you are calling Lobby.GetSafeHwnd before DoModal, so before the window is constructed. You should move the thread creation to the WM_INITDIALOG handler of MainLobby to create the thread there. Or you could create a modeless dialog.
Second you are using _beginthreadex in your MFC code. If you are starting a thread that uses MFC, then you need to start that thread with AfxBeginThread. If you only use CRT, then you use _beginthreadex. If you use neither, then use Windows CreateThread. The reason for this is that each layer (CRT, MFC) needs to do some housekeeping of thread specific information. This can only be done if you call the proper thread creation functions.
Third, you might consider using the MFC socket objects like CAsyncSocket. This object can send windows messages to your dialog if some data is available on the socket. This perfectly fits into your scenario with an MFC dialog that should handle socket data.
Another thing, but you already got that right: to access an MFC GUI object you need to be in the thread of that GUI object. So calling the Windows SetDlgItemText with the raw handle hDlg needs to be done, you cannot call an MFC function here.
BTW, are you sure your overall strategy is right? I don't see how you handle dialog life time, socket life time and how you put both together.
Got a third party ActiveX dll which has control dialog for a fan. Would like to access the ACtiveX dll from a MFC dll with APIs, so that be able open the control dialog and access some other functions in the ActiveX. IS this practically easy?., and what resources should be called where?. any examples?. Need to record temperature continuously while no around around.
After reading so much at the microsoft site, came up with a MFC dll that its dialog uses an ActiveX control. Also, wrote a MFC and a console applications that by calling dll's opendialog(), I see the dialog launches. I hope I am not causing any memory leak. or causing any resource (de)allocation errors without knowing. so far , things seem to be working.
BOOL CDllApp::InitInstance()
{
CoInitialize(0);
AfxEnableControlContainer();
return CWinApp::InitInstance();
}
int CDllApp::ExitInstance()
{
CoUninitialize();
return CWinApp::ExitInstance();
}
In another class, in the same mfc dll, i do this.:
void CMyClass::opendialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CMyDialog dlg;
dlg.DoModal();
}
I am developing an application which allows multiple Modal dialogs to be opened simultaneous. I have been experiencing an issue as to whenever I close the first dialog, it closes without error and call doesn't back to the callee until I close the second dialog which is defeating the purpose what I have to achieve.
Sample code:
Class A
{
func1()
{
....
DOModal()
....//some processing
}
Class B
{
func2()
{
...
doModal()
}
}
I tried with creating a user thread and event mechanism by associating it with the dialog but what is happening is it's actually not letting me to open the another dialog until I respond. I still want the execution to happen as it is.
My application is a single threaded environment.
DoModal dialog will allow you to launch only one at a time for each thread. Instead, you can try create and show the dialog with the parameters nIDTemplate as the ID of dialog and pParentWnd as parent window. Here you will not be required to create the multiple threads.
My program use a modeless dialog to interact with the user and also has a tray icon.
A user can quit the app immediately by using the tray icon.
BOOL OnInitDialog()
{
init data...
}
void OnDestroy()
{
destroy data...
}
void OnSomeButton()
{
CFileDialog dlg;
...
dlg.DoModal(m_hWnd));
access data...
...
}
void OnMenuExit()
{
DestroyWindow();
}
The problem is that when I popup a modal dialog(OnSomeButton), and then quit using the tray icon menu, the main dialog is destroyed first, and then the modal one returns, trying to access some invalid data, causing a crash.
I know i can add some check code before accessing the data, but is there any other way?
Is there any way to ensure OnSomeButton() returns before window destroy?
You need to add your own application level code. There is no system support for this issue primarily because there can be so many pecularities that no generic approach is possible.
Yeah. When you quit from the tray menu, you can send a WM_CLOSE or similar message to your modal dialog that causes it to exit. Even if your main window is destroyed before that OnSomeButton returns you will be okay provided the remainder of that function does not access any class internals (member variables etc). You could ensure this by having the window proc of your modal dialog return an 'abort' code or something when it is closed in this way.