|
Kind of. The thing about OnCommand() is that it's the handler for WM_COMMAND
messages which are sent/posted to the window. That means it gets EVERY WM_COMMAND,
not just certain ones. If you go that route, you need to filter out the ones you're interested in
and pass the others on, otherwise the dialog may not function correctly (especially since OnCommand()
is where CWnd dispatches command messages through the message map!).
For control notifications, you might do something like this:
BOOL CMyDialog::OnCommand(WPARAM wParam, LPARAM lParam)
{
WORD wNotifyCode = HIWORD(wParam);
WORD wControlID = LOWORD(wParam);
HWND hwndControl = (HWND)lParam;
if (EN_SETFOCUS == wNotifyCode)
{
return TRUE;
}
return CDialog::OnCommand(wParam, lParam);
} Make sense?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Yes, it does make since.
Question how will I know when the User no longer inputs any data? What I mean is I wouldn't want to GetDlgItemText(...) when they are stil entering data; or have paused/delayed finishing entering the data. With a property page they could go to the next page and return and finish where they left off entering data.
A C++ programming language novice, but striving to learn
|
|
|
|
|
What are you trying to achieve exactly?
Do you really need to get the edit control text after every change?
There's nothing wrong with that ... just typically the text only needs to
be obtained when the user clicks OK.
Regardless, if you get the text every time it changes, you'll always have
the latest text so it doesn't matter where the user navigates to.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I'm sorry, I didn't explain: There is no other controls on the property pages(7) otherthan the EditBoxes.Just 8 - 10 EditBoxes that has static instructions for what data is to be enter in which EditBox. Also no Tab Controls. Hence my problem. If I put a control for the User to select I have no idea how to trap the particular EditBox that was used. I know it sounds wrong, but the User has a lot of data to enter on various pages and I have to be able to find out when he/she is thru without User intervention(or asw little as possible).
A C++ programming language novice, but striving to learn
|
|
|
|
|
Gotcha, thanks.
You can get as granular with this as you need to.
The most granular tracking of user input would be to keep two flags for each
possible edit control - one that indicates if an edit control received focus, and
another indicating the user has changed the text (or entered new text).
If an EN_CHANGE notification is received for a given edit control, set its text-changed flag.
If an EN_SETFOCUS notification is received for a given edit control, set its got-focus flag.
That should be all (more than?) the info you need to know if the user entered text.
Actually, the EN_CHANGE notification is usually sufficient. EN_SETFOCUS doesn't mean
the user actually did anything besides click on the control.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Thanks I'll give it a try. I think I know how to code it. I sure wished Microsoft gave code samples for this sort of thing. I'm sure I'm not the only one that needs this type of control notice.
A C++ programming language novice, but striving to learn
|
|
|
|
|
Like I mentioned, if you work with Windows controls, I recommend
finding this link (Control Library[^]) in your documentation and
bookmark and/or memorize its location. It's pretty much essential IMO.
Once you use controls a bit, you'll see that there's many things common
in their functionality.
Doing things like you're doing is so common that MFC, for a LONG time, has
had wizards to insert a shell of code for handling these types of messages
Have fun!
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I wrote you an example about the EN_SETFOCUS that marks has told you in the previous answer. Take a look. That's the idea I used in my project. With a bool variable to know if a control has focus or not, setting it to TRUE when EN_SETFOCUS and to FALSE when EN_KILLFOCUS.
Greetings.
--------
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
|
|
|
|
|
Okay I'll give it a try today. How will I know when nthe User is thru inputing data; ie, if the User inputs data and then immediately clicks next on the Wizard, How will I know to get the data?
Also, you used "DestroyWindow() in the example. I can't do that because it will close the page window.(I tried to use a modeless dialog initialloy and when it reached the DestroyWindow, it destroyed the Page Window too.
I wished I could attach the Property Pages so you could see my delima. I tested your code and it works; but I'm trying to figure out is where do I get control of the page after a SELECTION IS MADE and before it is made?
Your code:
void CMyFormView::OnSetFocusMyEdit1 ()
{
m_bEdit1Focus = TRUE;
return;
}
void CMyFormView::OnKillFocusMyEdit1 ()
{
m_bEdit1Focus = FALSE;
return;
}
void CMyFormView::OnHotKeyEnterPressed ()
{
if (m_bEdit1Focus)
{ CalculateSomeStuffWithEdit1Value ();
return;
}
if (m_bEdit2Focus)
{ ValidateTheEdit2Value ();
DoAnotherStuff ();
return;
}
//more things...
DestroyWindow ();
}
How do I get here: OnHotKeyEnterPressed () ? You can't put a call to OnHotKeyEnterPressed () from the constructor; and remember, there are no other buttons on the page besides the EditBoxes. So how do I get control and KEEP CONTROL of the page while it is active?
-- modified at 14:58 Wednesday 7th November, 2007
-- modified at 15:09 Wednesday 7th November, 2007
A C++ programming language novice, but striving to learn
|
|
|
|
|
OK, sorry for the delayment in the answer, I didn't check my email yet.
1) You know that the user is writing data because you have one of those BOOL with a TRUE value. So if the user press "next" without doing what is needed to be done, you can ask those BOOL and avoid the "next page" giving a message. i.e.
void CYourPage::NextButtonClick ()
{
if (m_bEdit1Focus || m_bEit2Focus || ... || m_bEditnFocus)
{ MessageBox ("You are not allow to do that in this moment, XXX must be done before changing page", "info", MB_OK);
return;
}
else
{ GoToNextPage ();
}
}
2) I set the HotKey in my resource editor in design time. Associated to a menu option, but it has different functionality according to the class that call the methode, because of that I code the different versions of functionality inside every view/dialog that need it. With HotKey I mean something like Ctrl+O = ID_FILE_OPEN, but I was actually using a bad name, I should say "Accelerator", it was my fault, sorry.
3) That was how I used the idea I told you, you should adapt it to your problem. I mean, you can use the contructor to load the FALSE to the bool variables, you can use the messages Set/KillFocus to manage the state of those variables, you can use the button "next" to perform different functionality asking those variables (see above), or another different message/event.
4) You can keep control of the page taking a pointer with GetActiveWindow () when the page is firstly shown, does your page have something like OnInitialUpdate or OnInitDialog??? If yes, you can use it, when this is called, is very difficult that the user has changed focus, so you have your page active, if you save a pointer into a member variable, you can always control the page using this pointer whenever you need altough the focus is in other control.
I hope it helps you.
Greetings.
--------
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
|
|
|
|
|
Hello !
I want to open a file (.txt) that is automatically created in the
C:\Documents and Settings\username\Local Settings\Application Data\
path.
Since I don`t know the username (dependant on local configuration), I would like to know how to address this location (some applications do this by copying here items they need).
I've seen that for example, I can open
My Computer by using: ::{20D04FE0-3AEA-1069-A2D8-08002B30319D} ( a reg key, i suppose )
Network Neighbourhood by using: ::{208D2C60-3AEA-1069-A2D7-08002B30309D}
Control Pannel: ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}
and so on.
So... any suggestion to make the addressing work independently of computer's settings ?
Thank you a lot!
|
|
|
|
|
Use SHGetFolderPath[^] to get the path of that folder.... then build a filename
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Peter Weyzen<br />
Staff Engineer<br />
<A HREF="http://www.soonr.com">SoonR Inc -- PC Power delivered to your phone</A>
|
|
|
|
|
I have a simple dll that creates a dialog box with a button on it. The dll is loaded via LoadLibrary by the main application. The dialog box is created when the dll is loaded (ie. in response to DllMain being called with dwReason == DLL_PROCESS_ATTACH). The button when clicked runs the following::
<br />
OPENFILENAME ofn;<br />
TCHAR szFileBuffer[_MAX_PATH + MAX_FNAME + MAX_EXT];<br />
memset(&ofn, 0, sizeof(OPENFILENAME));<br />
szFileBuffer[0] = _T('\0');<br />
ofn.lStructSize = sizeof(OPENFILENAME);<br />
ofn.hwndOwner = hwnd;<br />
ofn.lpstrFilter = _T("Text files (*.txt)\0*.txt\0\0");<br />
ofn.nFilterIndex = 1;<br />
ofn.lpstrFile = szFileBuffer;<br />
ofn.nMaxFile = (_MAX_PATH + MAX_FNAME + MAX_EXT);<br />
ofn.lpstrTitle = _T("Select File");<br />
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER;<br />
if(GetOpenFileName(&ofn))<br />
{<br />
...<br />
return true;<br />
}<br />
If I call this code from within a standard .exe, everything runs fine. However when run from the dll it hangs. The problem is the hwndOwner. If I set this to NULL or to the value passed to the dialog box procedure the process hangs. If I set it to some invalid HWND value GetOpenFileName returns an error value but the process does not hang. Any ideas would be hugely appreciated.
|
|
|
|
|
Microsoft publishes a "best practices" document (here)[^] which spells out all of the do's and don't of writing a DLL. Read it!
The gist is -- "do as little as possible in DllMain". If you want your DLL to do something, create a function entrypoint.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Peter Weyzen<br />
Staff Engineer<br />
<A HREF="http://www.soonr.com">SoonR Inc -- PC Power delivered to your phone</A>
|
|
|
|
|
Perfect, fixed. Didn't realise this was the case. Thanks for the information, much appreciated.
|
|
|
|
|
Two classes X and Y.
I want to #include X.h in Y.h
I want to #include Y.h in X.h
I can do one, but not both. I understand that there is a "self-referencing" situation happening here.
What I don't understand is how I can work around this.
What am I trying to do?
Instances of both X and Y are created by an instance of class Z.
I would like X to have a pointer to instance of Y.
I would like Y to have a pointer to instance of X.
In X I have a function that takes Y* as a parameter. Z executes it and that's how I get Y* into X.
In Y I have a function that takes X* as a parameter. Z executes it and that's how I get X* into Y.
This works when Y.h is included in X.h
OR
This works when X.h is includd in Y.h
It will not work with both #includes.
Ideas? Work arounds?
Thanks
|
|
|
|
|
Oliver123 wrote: What I don't understand is how I can work around this.
Check out the #pragma once directive.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
What you need is a Foward Declaration. e.g.
<br />
class Y;<br />
class X{<br />
.<br />
.<br />
.<br />
Y* m_pY;<br />
.<br />
.<br />
.<br />
};<br />
<br />
class Y{<br />
.<br />
.<br />
.<br />
X* m_pX;<br />
.<br />
.<br />
.<br />
};
The First Line: class Y; informs the compiler that thrte will be a class named Y, whatever it's nature. You cannot use the class at that stage, because the compiler does not know what's in it, and for instance the size in memory would be unknown. The compiler has enough information though, to allow you to use a pointer to an instance of type class Y . This method og allowing a forward declaration was included in the language precisely to get around the deadlock situation you described.
Hope this is of help.
LateNightsInNewry
|
|
|
|
|
I did this, and it successfully compiled.
Passed a pointer to class Y into class X.
Passed a pointer to class X into class Y.
When I try to use Y* in X, the compiler says Y is undefined.
When I try to use X* in Y, the compiler says X is undefined.
So, when using forward references, where does the compiler eventually get the definition of Y so it can be used as Y* in X? Is there some type of ordering of what is presented to the compiler?
Thanks
|
|
|
|
|
Just to add a little more confusing detail:
If you just reference the object by pointer or reference (either inside the class data or in a function declaration) then you can get away with just a forward reference.
In these cases the size of the object is fixed -- the size of a pointer. And since you're not using the other class, it needs to know nothing about the functions in it...
If you declare an instance of class or override an class -- then you must include the header. In this case, the compiler needs to actually know something about the object to compile (like the size of the other class, what virtual functions it has, ... )
Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can.
Oh, and always use "#pragma once" too
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Peter Weyzen<br />
Staff Engineer<br />
<A HREF="http://www.soonr.com">SoonR Inc -- PC Power delivered to your phone</A>
|
|
|
|
|
<blockquote class="FQ"><div class="FQA">Peter Weyzen wrote:</div>Sorry if this is a little confusing. The gist is -- don't include the header until the object is actually used. And always try to use a forward declaration.... if you can.</blockquote>
I always get myself into trouble by not keeping track of #include statements and try to resolve it by adding my #include statement into stdafx.h header.
Sometime it makes even more mess.
My question - is this a good way to code in MFC ?
For extreme - could one do all class forward declarations in stdafx.h?
|
|
|
|
|
I think you'd do the best service if you "crafted" each header to include only what it needs. It should be able to stand on it's own....
But you should decide what that is -- for your project. There's no perfect way to do it.
One of my bosses would always complain about how long the project took to build. So, being the boss that he was, he demanded that all headers got included into stdafx... this caused them all to be precompiled and sped up the build.
The downside was that everything got built all the time as you changed headers....
It wasn't a particularly great style -- not something I thought highly of -- but it was the way we did things at that job.
Do what's works for you and your work environment.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />
Peter Weyzen<br />
Staff Engineer<br />
<A HREF="http://www.soonr.com">SoonR Inc -- PC Power delivered to your phone</A>
|
|
|
|
|
Vaclav_Sal wrote: For extreme - could one do all class forward declarations in stdafx.h?
Vaclav_Sal wrote: My question - is this a good way to code in MFC ?
Answers: No!, and Bad Practice!
Keeping Track of things is one of these things we have to do when writing code. Planning your Code and File Organisation is an important part of your design process.
Regards,
Bram van Kampen
|
|
|
|
|
Your compiler reads your source file line by line. the #include directive means exactly that: 'include' It is conceptually as if at that point the entire file to be included is copied and pasted to the location of the #include directive. What the compiler digests is your cpp file, with at all levels the #include directives removed and replaced by the contents of the file to be included. This is one of the functions of the Pre-Processor. (Note that the compiler proper knows nothing about header files, it compiles the cpp file after the Pre-Processor has expanded it.) So, the ordering of things depends on the ordering of your #include file directives, and on the order of the statements in your header files.
Similar Sample with Line Numbers:
1 class X;<br />
2 class Y{<br />
3 X* m_pX;<br />
4 };<br />
5 class X{<br />
6 Y* m_pY;<br />
7 };
The Class X is forward declared at line 1
The forward Declaration is used in line 3
The Class Declaration for class Y is completed on line 4
The Class Declaration for class X starts on line 5;
The Class declaration for class X uses class Y on line 6.This can be done without a forward declaration, because class Y is fully declared after line 4.
The Class Declaration for X completes at line 7.
If you try to do anything of the kind of *m_pX before the end of line 7 you get an error, you dereference something that has not been completely declared.
Hope this clarifies things.
N.B. A Note about '#pragma once'
It is not difficult to end up with a 'spagetti' of include files, and at some stage inevitibly a file would be included twice. This gives all sorts of problems, and the compiler usually chokes on this, but this situation is often hard to unravel.
The directive '#pragma once' tells the preprocessor to check if the particular file has already been included, and, if so to ignore the #include directive.
Best of Luck
Bram van Kampen
|
|
|
|
|
The fog begins to clear a bit.
Question: In your example, all the statements are in one file. However, VC++ creates individual header files for each class. To emulate what you have shown, we would have to control of the order in whch the header files are presented to the compiler. Correct? Can we give the compiler the header.h files in the order it needs them while still maintaining the very convenient system of one header file per class? Is there a way to do this?
Thanks
|
|
|
|