|
I'm sure using the Speech API will not help ..
Joke aside, have a look at the observer pattern; or simply override the controls to directly call the formview.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|
Hi! and thanks for the quick reply.
There is just something I don't quite understand...
have a look at the observer pattern
What do you mean exactly by "observer pattern"?
Also, can you give me an example of how I could override a control which calls one its own virtual functions (when an event occurs) and therefore make it alert CFormView?
This is really killing me...
Again thanks a lot.
David
|
|
|
|
|
If the "events" belong to the category of "Standard Windows events", such as a button click, then you can use the ClassWizard/"Add Event Handler" -wizard to add a handler for the event. Because the CFormView is the parent of all the controls, it will be the class which will contain the handlers.
However, a more important question I have to ask: why wouldn't you use SendMessage ? Everything in Windows(r) is messages, so a few more messages won't crash the system
As these are custom controls, I assume that you have a class for each control which determine it's behaviour. Now, inside these classes, if you create ON_WM_* macro entries into the message map, you can capture any type of WM_* messages, no matter what they are. When you capture this message, and wish to notify the parent (in this case, the CFormView ), you can use the CWnd::GetParent function of the control's class (every MFC control derives from CWnd , thus it has GetParent ). This will give you a pointer to the CWnd-class of the class hiearchy. Then use DYNAMIC_DOWNCAST macro to cast down into your CFormView-derived class. Now, you can use the pointer to, for example, call a function of the derived class. Here is a concrete example:
BEGIN_MESSAGE_MAP(CMyButton, CButton)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP<DIV>
.
.
.<DIV>
void CMyButton::OnLButtonDown(UINT uiPos, CPoint point)
{
CWnd* pParent = this->GetParent();<DIV>
CMyFormView* pForm = DYNAMIC_DOWNCAST(CMyFormView, pParent);<DIV>
VERIFY( pForm != NULL );<DIV>
pForm->AnyGivenFunction( param1, param2 );
} If you don't understand this concept, then you should quickly brush up your skills in object-oriented programming, and more importantly, in pointers to classes in a class hiearchy. Any C++ book is a good place to start, and the thing to look for is 'polymorphism' and 'dynamic_cast'. Search MSDN with the latter one for a few excellent examples.
Hope this will help you out..
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Antti Keskinen wrote:
use DYNAMIC_DOWNCAST macro to cast down into your CFormView-derived class. Now, you can use the pointer to, for example, call a function of the derived class. Here is a concrete example:
Antti, thanks a million!!! DYNAMIC_DOWNCAST ===> that is what I was looking for!
And yes, you are absolutely right! I have only started programming in MFC for a month or so, which consequently doesn't make me an expert on the subject.
But thanks to your brilliant explanation, I have learnt a bit more.
Thank you very much indeed.
David
|
|
|
|
|
Antti, I have another question for you (or anybody else who would like to have a go...):
Assuming I opt to use a Messaging system to make objects communicate with each other and also assuming I use RegisterWindowMessage to make sure I will have valid message IDs (not in use already), how would I inform the parent window (or whatever) of the message IDs they should be listening to?
Moreover, how do I inform the parent window receiving the message(s) of who is sending it? Should I include that in one of the PARAM args?
Do you have any suggestions you want to share with me?
Again, thanks a lot,
David
|
|
|
|
|
First, the message ID problem. Basically, you have two valid options:
1. Either decide beforehand the message IDs.
2. Use RegisterWindowMessage and create a handler for ALL messages for the parent window.
In approach #1, we cannot be sure that the message ID is available on the global (system-wide) scale. However, since we are operating on single-thread context (both the button and the form exist, and the message needs only be understood, in the context of the running thread), we can safely use any message ID we want, as long as it is in the form WM_USER + xxx, up to 0x7FFF. WM_USER signals a starting integer, above which (almost; see MSDN) all message ID numbers are available for use. Also, we must assume that you can either see or can decide all message IDs used in the application/project, so that there are no overlappings during the design phase.
In approach #2, we use RegisterWindowMessage to make sure that our message ID is unique on the system-wide scale. This function should be used only when you have two or more applications (running on seperate threads) that need to handle a certain customized message. Here, the message ID is bound to a string variable, and RegisterWindowMessage can be used to decipher the ID from the string, if the ID is registered already.
This leads us to solving your next problem, which is "How to inform the parent of the message ID ?".
Again, there are two ways of doing this:
1. During the design phase, decide the message ID (WM_USER + xxx) and use ON_MESSAGE -macro to capture the message in the parent
2. During run-time, use a class member variable (UINT ) that stores the message ID.
Approach #1 is quite clear. All WM_USER -message handlers are similar. You can search the MSDN for "User-defined handlers" to get the actual C++ function declaration you must use. It's something like afx_msg LRESULT <memberFxn>(LPARAM arg1, WPARAM arg2) , and it must be a member of the class.
In approach #2, the parent class is "listening" to all messages (override the virtual window procedure function, CWnd::WindowProc to capture all messages; remember to call the original CWnd::WindowProc in the end). When a message with a matching UINT is received, we provide a custom handling to it. This approach, as you might have guessed, doesn't rely on the message-macros. The reason is simple: there is no macro that would cover all messages, or messages with a varying ID (ON_REGISTERED_MESSAGE is a different issue).
Let's have a break from theory: here is an example on how to use approach #2:
class CMyFormView : CFormView
{
.
.
.<DIV>
public:
void SetMessageID( UINT nID ) { this->nMessageID = nID; }
UINT GetMessageID() { return this->nMessageID; }<DIV>
private:
virtual LRESULT WindowProc( UINT message, LPARAM lParam, WPARAM wParam );
UINT nMessageID;
};<DIV>
.
.
.<DIV>
LRESULT CMyFormView::WindowProc( UINT message, LPARAM lParam, WPARAM wParam )
{
if ( message == this->nMessageID )
{
}<DIV>
return CFormView::WindowProc( message, lParam, wParam );
} For the last question - about informing the identity of the sender - the solution is pretty simple. Almost every Windows message that roams out there has two parameters attached: an LPARAM and a WPARAM . These are 32-bit integers that can be used in any way you please. If you design your custom message so that it's ID is, say, WM_USER + 1001 and the sender's ID is stored in the LPARAM argument, then it should be pretty simple to receive and decipher this message, no matter which one of the above approaches you used to catch the message. Both the ON_MESSAGE -macro functions and the window procedure grant you access to the LPARAM and WPARAM arguments.
Enjoy
-Antti Keskinen
P.S. Perhaps I should write an article about this
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Antti you are brilliant at explaining the works of the Win32 API. In order to understand what you've just laid out in such a clear way, I would have to read pages and pages of a technical VC++/MFC book. For that -- thank you so much.
By the way, would it be too much to ask you for another favour (which I know is nothing much complicated for you) ? It is the [new] thread I have started called Classes which call each other's methods...
Whatever way, thank you so much for putting what was driving me mad in such a clear way!
David
Antti Keskinen wrote:
P.S. Perhaps I should write an article about this
One thing I know -- you would help loads of newbies like myself! So if you have the time and disposition, why not?
|
|
|
|
|
I'm looking for the best C++ solution to this data situation. I need something as generic C++ as I can get because we may switch compilers sometime in the near future.
I'm implimenting an ISO9660 filesystem, which stores on disk structures that look something like this in C
#pragma pack(1)
struct filename {
BYTE version;
ULONG bigendianBlockAddress;
ULONG littleendianBlockAddress;
BYTE filenameLenght;
BYTE filename[30]; // not C style string
#pragma pack()
That is block address that are both little endian and big endian, but otherwise exactly the same value. The perfect situation for a class. something like:
#pragma pack(1)
class bothorder {
ULONG big;
ULONG little;
public:
ULONG operator=(...)
...
};
This structur occures all over, and manipulating it will be a large part of the rest of my code.
Now I get (through an interface that I cannot change) a pointer memory space with the first structure. Is it safe to use assignment new or some cast to place the class exactly there, or should I expect compilers to use more than the 8 bytes the ULONG takes for some internal use? (such as a this pointer?)
Is there a better way to solve this problem? I'd like to make the code as readable as I can.
I know pragma pack isn't in standard C++, but it appears all compilers support it.
Those who know ISO9660 will note a big advantage for classes: I intentionally introduced a bug, the little endian number should have been before the big endian number!
|
|
|
|
|
When you use #pragma pack(1) you can be sure your data will be aligned on one byte boundary, so will be in size exactly as you defined it. Although it works for unions and structures only.
|
|
|
|
|
thank you, thats what I needed to know.
My compiler also allows this for class, but I don't expect to use this one forever. (It isn't supported anymore, and is missing some parts of C++)
I makes for ugly code (though I see why not all compilers will make it work for class)
Anyone have a better idea than a bunch of structs, and some classes to manipulate them with pointers to the struct?
|
|
|
|
|
hallo,
i've got a little problem. i want to change the timeout of an error-request. but it doesn't work
please help me
BOOL test::ftp_find2()
{
CInternetSession sess(_T("MyProgram/1.0"));
CFtpConnection* pConnect = NULL;
try
{
sess.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT,100);
pConnect = sess.GetFtpConnection(_T("12.232.34.54")); //server doesn't exist
CFtpFileFind finder(pConnect);
BOOL bWorking = finder.FindFile(_T("*"));
while (bWorking)
{
bWorking = finder.FindNextFile();
printf("%s\n", (LPCTSTR) finder.GetFileURL());
}
}
catch (CInternetException* pEx)
{
TCHAR sz[1024];
pEx->GetErrorMessage(sz, 1024);
MessageBox("ERROR! %s\n", sz);
pEx->Delete();
}
// if the connection is open, close it
if (pConnect != NULL)
pConnect->Close();
delete pConnect;
return true;
}
|
|
|
|
|
Hi friends,
I am using following code
wchar_t wchAttributes[256]=L"";
__int64 i=90;
wsprintfW(wchAttributes,L"%I64d",i);
::OutputDebugStringW(wchAttributes);
Inseat of giving output as "90" it gives output as "I64d"
Please help...
VikramS
|
|
|
|
|
vikrams wrote:
"%I64d" I never saw this as a parameter
try using "%i" or "%l"??
The parameters are somewhere on MSDN although hard to find (like everything on MSDN )
Hope this helps!
"If I don't see you in this world, I'll see you in the next one... and don't be late." ~ Jimi Hendrix
|
|
|
|
|
Actually I have to store 12 digit decimal number...so __int64 is the only option remains... and I want to print it in buffer..
|
|
|
|
|
Well I found something like "%I64" so maybe just the "d" is to many?
Maybe you can divide it in 2x32bit integers? and write it like that?
Look on fprintf in MSDN there you'll find some % values for string formatting.
If this fails I'm sorry to say I'm out of ideas.
Good luck to you.
"If I don't see you in this world, I'll see you in the next one... and don't be late." ~ Jimi Hendrix
|
|
|
|
|
HI
I used Function swprintf and it works..it's unicode version of sprintf.
VS
|
|
|
|
|
%I64d is a valid format string. However, it is not supported by either version of wsprintf() . You'll need to use sprintf() instead.
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|
|
I am trying to set the thread function and get compile errors:
Here are the relevant pieces:
unsigned int _stdcall CCad::RunAlgThread(void*);
and
int SetFunc(unsigned int (_stdcall *pFunc)(void*) = 0);
so I do:
m_thread.SetFunc(RunAlgThread);
the compiler error:
error C2664: 'SetFunc' : cannot convert parameter 1 from 'unsigned int (void *)' to 'unsigned int (__stdcall *)(void *)'
What needs to be done to fix this?
Thanks,
sb
|
|
|
|
|
Just declare your member function as static
Papa
while (TRUE)
Papa.WillLove ( Bebe ) ;
|
|
|
|
|
Papa has told you how to fix the problem. If you want to know why the problem exists, read this article. Non-static member functions have an implied 'this' pointer as the last parameter (this is what the compiler was complaining about). Static member functions do not have the 'this' pointer.
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|
|
Could I trouble you to type out the link? I cant seem to get to it by clicking on "this". Appreciate it,
sb
|
|
|
|
|
http://www.codeproject.com/threads/memberthread.asp
(you can find it by right clicking and choosing view source
"If I don't see you in this world, I'll see you in the next one... and don't be late." ~ Jimi Hendrix
|
|
|
|
|
Do you normally have troubles with hyperlinks in the CP forums? Can you right-click on it and select "Open in New Window" from the context menu?
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|
|
Only at work. Even to get to CP I have to use 209.171.52.99 and navigating within cp is a nightmare too. Some problem only occurring with the cp site here.
|
|
|
|
|
I want to create an app with three CView derived classes similar to the default Visual C++ IDE ( I don't need complicated things like MDI's or tabbed controls or docking just yet). Is is necessary to create a static CSplitterWnd within another and can anybody give me any starters?
Thanks,
John
|
|
|
|
|