|
There are a couple relatively easy ways, in addition to the splitter idea the other guy suggested.
1. Create a control dynamically. Have an object of, say, CButton, in your header file, and then in the view class initialization, create the button with the desired attributes. For instance:
// in header file
protected:
CButton myButton;
// in initialization function
myButton.Create(blah);
Look in MSDN for the parameters to Create, you will have size, position, caption, etc. One important one is the control ID. You can use that control ID in your message map so you can define a handler that controls what happens when the button is clicked.
2. Handle mouse clicks (e.g., OnMouseUp). Check if the mouse position is within a certain area, and then do whatever you feel like doing.
#1 is probably cleaner, since you get an actual button, but 2 is probably a little easier.
"When a man sits with a pretty girl for an hour, it seems like a minute. But let him sit on a hot stove for a minute and it's longer than any hour. That's relativity." - Albert Einstein
|
|
|
|
|
Hi,
I have posted this question before and got an answer, but for some reasons it doesn't seem to work, or I have the code at the wrong place.
I copy pasted the code in my InitInstance()
so now it looks like the following:
BOOL CMotionControllerApp::InitInstance()
{
// CG: The following block was added by the Splash Screen component.
\
{
\
CCommandLineInfo cmdInfo;
\
ParseCommandLine(cmdInfo);
\
\
CSplashWnd::EnableSplashScreen(cmdInfo.m_bShowSplash);
\
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMotionControllerDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMotionControllerView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
/////////////////////////////////////////////////////
//This is the code, it is at the correct spot?
/////////////////////////////////////////////////////
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
//////////////////////////////////////////////////////
// The one and only window has been initialized, so show and update
// m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
// m_pMainWnd->UpdateWindow();
return TRUE;
Ehsan Behboudi
|
|
|
|
|
Post the code that hides the window. One solution is SW_HIDE.
Kuphryn
|
|
|
|
|
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
or
if (!ProcessShellCommand(cmdInfo))
return FALSE;
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
CChildFrame *childFrame=(CChildFrame *)pMainFrame->GetActiveFrame();
childFrame->PostMessage(SW_HIDE);
|
|
|
|
|
I posted a much longer question about this on the COM forum but got no responses so I'll try to phrase this shorter and hope for luck here.
I have a dialog based MFC application that contains a class that supports automation. The problem is that the server exits when I close the dialog even though I have clients (.vbs scripts) accessing the automation class. Anyone know how this should be changed so that closing the dialog for the application doesn't kill the server unless the reference count is zero? I don't understand why this isn't the default behaviour.
Gil Jones
|
|
|
|
|
You might want to invest into: AfxOleApp(); / AfxOleUnlockApp();
|
|
|
|
|
The automation class already contains those calls as inserted by the ClassWizard.
Just try this and you should see the problem:
1) Create a new single dialog MFC application called TestServer.
2) Change TestServer.cpp to look like the following:
COleTemplateServer::RegisterAll();
if (RunEmbedded() || RunAutomated())
{
return TRUE;
}
else
{
COleObjectFactory::UpdateRegistryAll();
}
3) Add a class called Interface1 derived from CCmdTarget that is creatable by type id TestServer.Interface1.
4) Add a get property to Interface1 called StepSize and have it's implementation return 5.0.
5) Create a file called test.vbs which contains the following:
Dim x
set x = CreateObject("TestServer.Interface1")
WScript.Echo x.StepSize
WScript.Echo x.StepSize
6) Execute the application which will bring up the dialog.
7) Then double-click the test.vbs file to execute it.
8) Before you close the windows script host messagebox that returned "5", hit the "OK" button on the dialog which will close it.
9) Then hit "OK" on the windows script host messagebox.
10) You will see the error message that the remote server machine does not exist. So I want to know how to change this so that closing the dialog doesn't kill the server.
Gil
|
|
|
|
|
Gil,
If it's DialogApp you must have CDlgAutoProxy derived class which is your OutProc Proxy.
In constructor of the proxy you must have this line or similar:
m_pDialog->m_pAutoProxy = this;
Now put the following code in destructor of CDlgAutoProxy:
if(m_pDialog)<br />
m_pDialog->m_pAutoProxy = NULL;
Now overload OnClose message handler of your dialog and put the following code in there:
if(!m_pAutoProxy)<br />
CDialog::OnClose();
You are basically ignoring Close when Proxy exist.
Hope, this works.
"...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..."
Me
|
|
|
|
|
Ah...now I see why it's not working for me...the CDlgAutoProxy code is never running. I have an application called MicroTouch and I added an interface called Focuser. If I create an object of "MicroTouch.Application", then the proxy code executes, but when I create my "MicroTouch.Focuser" object, the proxy code never runs. So it looks like I need to replicate some of the proxy code into my Focuser class such as the following:
ASSERT (AfxGetApp()->m_pMainWnd != NULL);
ASSERT_VALID (AfxGetApp()->m_pMainWnd);
ASSERT_KINDOF(CRCMicroTouchDlg, AfxGetApp()->m_pMainWnd);
m_pDialog = (CRCMicroTouchDlg*) AfxGetApp()->m_pMainWnd;
m_pDialog->m_pAutoProxy = this;
The other thing that makes this more difficult to fix it that I'm not using the main dialog but instead I'm using a property sheet for the main GUI interface. I think I'll need to override OnQueryCancel() in every property page to catch all the places where the application can exit.
Gil Jones
|
|
|
|
|
Thanks for your help! You comments led me in the right direction and I got my test project working and now I just need to do the same thing in my real project. The only difference is that my real project is using a property sheet for the main dialog so I hope that doesn't cause too much trouble.
One thing I found is that I had to remove the "return TRUE" from the "if (RunEmbedded()...." part of the if because the proxy code fails if there is no dialog active. I had to instead just HIDE the dialog.
The final solution still seems a little crude to me. I had to change the dialog class so that it tracked how many automation connections were active from my Focuser interface class and the Focuser class destructor had to call the dialog's OnClose method which I have issuing a PostQuitMessage() if the number of connections is zero. I'm sure I probably have a race condition now.
Gil
|
|
|
|
|
The final solution still seems a little crude to me. I had to change the dialog class so that it tracked how many automation connections were active from my Focuser interface class and the Focuser class destructor had to call the dialog's OnClose method which I have issuing a PostQuitMessage() if the number of connections is zero. I'm sure I probably have a race condition now.
Gil,
I don't know about PostQuitMessage() , because it suppose to exit your app message pump, but if you just use WM_CLOSE message send to your dialog -- I don't see any probability of race condition .
Remember, unless you have some Multithreaded InProc components inside of your server (which I think you don't have): all outproc OLE calls are coming to you on your worker(main) thread and through message queue. Therefore, OLE system absolutely cannot instantiate new instance of your server without your WM_CLOSE being completely processed.
At least, that's my understanding. But again, I maybe wrong (as usual).
Regards
"...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..."
Me
|
|
|
|
|
Ok....I'll try to take that out cause I didn't like it either. I was up late and it was the first thing that came to mind when I had trouble getting the app. to exit.
Thanks again for all the help!
Gil
|
|
|
|
|
Having trouble trying to deallocate memory - it didn't crashed, just stalled. And I have no idea why:
Here's the code:
int ** AllocMatrix(unsigned int numrow, unsigned int numcol, int initvalue=0)
{
int ** pMatrix=NULL;
unsigned int i=0;
pMatrix = malloc(numrow *4);
if(pMatrix==NULL) { return NULL; }
for(i=0; i<numrow; i++)
{
pMatrix[i]=NULL;
pMatrix[i]= malloc(numcol *4);
if( pMatrix[i]==NULL ) { return NULL; }
}
InitMatrix(pMatrix, numrow, numcol, initvalue);
return pMatrix;
}
void DestroyMatrix(int ** pMatrix, unsigned int numrow)
{
unsigned int i=0;
for(i=0; i=numrow; i++)
{
free(pMatrix[i]);
}
free(pMatrix);
return;
}
Any idea? Thanks!
|
|
|
|
|
In DestroyMatrix:
for(i=0; i < numrow; i++)
"...Ability to type is not enough to become a Programmer. Unless you type in VB. But then again you have to type really fast..."
Me
|
|
|
|
|
man, I don't believe that I can be so lame.
|
|
|
|
|
is it possible to export a function that returns a std::string/std::wstring if the code generation is set to Multithreaded or Multithreaded Debug?
It appears that it is not, and that the only way around this is to use the Multithreaded DLL or Multithreaded DLL Debug code generation.
I have made a simple test that would seem to verify this, but maybe there's something else I'm missing?
Thanks
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
|
|
|
|
|
See my remark below.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Hi Jim,
Have you resolved this? If not what is the error you are getting?
Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
|
|
|
|
|
What some of the other people have said makes sense.
However there is another way. I personally detest linking to the C runtime DLL, because it then means you have to redistribute MSVCRT.DLL.
ANy time I deal with objects going from DLL to a process or another DLL is to make sure that whoever allocated the object has the responsibility for deleting it. So if you are returning a string from a DLL, that string needs to be a static variable somewhere in the DLL, or the DLL needs to control it in some other form.
"When a man sits with a pretty girl for an hour, it seems like a minute. But let him sit on a hot stove for a minute and it's longer than any hour. That's relativity." - Albert Einstein
|
|
|
|
|
Navin wrote:
you have to redistribute MSVCRT.DLL
Shouldn't be an issue. In fact a number of MS system dll's link to it already e.g. odbc32.dll. So even if you don't use it directly chances are some sub-system is. If you can't beat 'em join 'em.
Navin wrote:
make sure that whoever allocated the object has the responsibility for deleting it
Exactly, however this is a case where he is using someone elses library i.e wstring. _If_ the implementation has this side-effect there is little he can do.
Personally, i've written my own class framework (built up over the last 14 yrs) that takes all of this (and more) into account and minimizes the dependency on the CRT - not a task to enter into lightly though.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
I'm trying to build two projects one a DLL and another an exe that uses the DLL.
Both projects have their code generation set to "Multi Threaded Debug"
Both have _UNICODE defined
both use the std::wstring class for strings
it seems that if I have a class member method that returns a wstring object, say
wstring Foo::getName(), in the DLL (and the class is exported),
that i get a crash in the exe after the function call ends (and the temporary wstring instance is cleaned up).
If I take the code in the method and simply cut and paste into the exe code that calls the dll's function, then the actual code itself works fine.
However if I switch the code generation to "Multi Threaded DLL Debug"
then everything works fine, no crashes at all!
Is there something funky about unicode strings that I am missing? Is this something else entirely? Have I just smoked too much crack?
Help!
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
|
|
|
|
|
Haven't looked at it, but run into similar bugs before.
It has always been the CRT (C RunTime Library).
What happens is because you are statically linking the CRT to both the DLL and the EXE there are 2 process heaps generated.
I would assume that std:wstring is allocating from one and trying to free/realloc in the other at some point via calls to malloc/realloc/free.
When you link CRT as dll in both DLL and EXE then only one process heap is generated.
Solutions :
1. As you have found link to CRT dll (this is what i've done). There are more reasons than just malloc/free, you would also have problems with fopen() files that are opened in the DLL won't be accessable in EXE. CreateFile() doesn't have this problem as the file structures are globally unique.
2. Write your own allocator for wstring that allocates from a new heap you create in the DLL (i do this as well).
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Achhh
This is so lame, I guess I never ran into this before because I would either statically link everything into one exe, or (for stuff at home) always use dll CRT.
You'd think there would be an easier way...
Oh well. I'll just stick with your suggestion 1!
Thanks
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
|
|
|
|
|
Jim Crafton wrote:
This is so lame
Yes, but what other choice is there ?
When you compile the EXE (w/ static CRT) it has no idea that you will be linking to a DLL that already has a static instance of CRT. You will have this problem when you try to statically link to any library - you get a copy of all the global variables.
Thinking about your problem some more ...
In general i wouldn't expect this problem as wstring is hidding all malloc/free calls, that is they are all done in the DLL against the DLL process heap.
The only way i could see this happening is if wstring has some inline methods that call malloc/realloc/free that you are calling in the EXE.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Hi,
In my SDI application, I have two different FormViews separated by a splitter window. I want the document class to handle the shared data between the two views.
How do I add the new view to the existing document class.
How the data among the two views is shared by the single document?
Please give an example.
Thanks
Binayak
|
|
|
|