|
Is it possible to port C++ applications using MFC to machines that do not have C++ installed by transporting specific dll's.
|
|
|
|
|
TallAndyB wrote:
Is it possible to port C++ applications using MFC to machines that do not have C++ installed by transporting specific dll's.
Have a read of for VS.NET[^]
or
here for VC6[^]
Michael
CP Blog [^]
|
|
|
|
|
porting ? or compiling ? or executing ?
on same OS ? different OS ?
I would say no at first, but I'm mut sure what you want to do.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|
Did you really mean port? I think from your question you ment something completely different.
Port means take your application running on Windows (or any other computer platform), and make it run on something else like the Mac. (UNIX, VMS, mainframe, cell phone). If this is what you ment, not easially, you will need a C++ compiler that targets that computer (it doesn't have to run on that computer, just know how to compile for that computer), and a library that runs on that platform. Attempts have been made to port MFC to other systems, you can google for them, but most have had little success. I'm told that it is easy to port MFC to wxWidgets, but your milage will varry.
If you ment you want to run your MFC app on a different windows machine, then of course you can do this. Start reading up on installers, (like installshield) and make one work for you. You can create one from scratch, or use one to help you out. Many people have done this with MFC (not me though) so it should be easy to get help once you ask the right question.
|
|
|
|
|
OK, If I have read correctly to be able to take a single executable file from the development environment and us it on another Windows based machine I need to statically link with the MFC dlls. I appreciate that this will make it a more cumbersome .exe but it keeps my customer happy. As a final check I will not need any additional dlls to permit database access since I accomplich that using the MFC CRecordset classes.
Thanks for the pointers as to where to look and correcting my loose terminology.
AndyB
|
|
|
|
|
Hi,
i am using crystal reports 9.2.xxx that comes with visual studio 2003,
we are developing an application with a maximum of 20 concurrent users
i was wondering the following:
(1)what are the licensing and features limitations of this version of crystal reports?
(2)are we free to distribute to as many users as we like royalty free?
Thanks In Advance
|
|
|
|
|
How can i diable / enable any tabpage in a Tab control?
any help?
Tariq
|
|
|
|
|
Hi everyone,
I have a byte array of 1000 bytes and it is supposed to have a static content. What I want to do is put a whole string of hex values into it all at once rather than do something like:
byte[0] = 0x95;
byte[1] = 0x78... and so on..
Is it possible to initialize it at once with all the content?
Thanks,
Pankaj
Without struggle, there is no progress
|
|
|
|
|
You can set the values when you declare byte
char byte[1000] = {0x95, 0x78, ...};
NOTE, ... means and so forth for all 1000 bytes.
Ant.
I'm hard, yet soft. I'm coloured, yet clear. I'm fruity and sweet. I'm jelly, what am I? Muse on it further, I shall return! - David Williams (Little Britain)
|
|
|
|
|
Antony M Kancidrowski wrote:
char byte[1000] = {0x95, 0x78, ...};
NOTE, ... means and so forth for all 1000 bytes.
That sounds like real fun!
better him then me
"If I don't see you in this world, I'll see you in the next one... and don't be late." ~ Jimi Hendrix
|
|
|
|
|
Pankaj
Without struggle, there is no progress
|
|
|
|
|
V. wrote:
That sounds like real fun!
Um quite!, not the most productive thing to do either
Ant.
I'm hard, yet soft. I'm coloured, yet clear. I'm fruity and sweet. I'm jelly, what am I? Muse on it further, I shall return! - David Williams (Little Britain)
|
|
|
|
|
Thanx!
Without struggle, there is no progress
|
|
|
|
|
Hi,
i want to create a dll to call some functions i was using in one of my progs.. the linker gives me following errors:
Linking...
nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in Test.obj
nafxcwd.lib(dllmodul.obj) : warning LNK4006: _DllMain@12 already defined in Test.obj; second definition ignored
Creating library Debug/Test.lib and object Debug/Test.exp
nafxcwd.lib(timecore.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(apphelp.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(filelist.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argv
nafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argc
Debug/Test.dll : fatal error LNK1120: 3 unresolved externals
Any ideas ?
"Just looking for loopholes." W. C. Fields American actor, 1880-1946, explaining why he was reading the Bible on his deathbed.
|
|
|
|
|
By looking at the included libraries, it seems that your DLL is using MFC, linked statically.
You cannot, and I repeat, cannot use DllMain as the DLL entry point when using MFC. Instead, I suggest you create a whole new DLL project, this time by using the MFC DLL Wizard which comes with Visual Studio. It creates a skeleton project for you, indicating places where you should add code by inserting comments.
As for the other errors, it seems that your linker input libraries are missing something. For a general rule of thumb, create a new project and copy/paste relevant code over the new skeleton.
The reason why you cannot use DllMain is because MFC already offers this function in it's core libraries. This is, by Microsoft's words: "Behaviour by design". MFC's DllMain will query for an external CWinApp object, which is exported by the main code module of your project (Usually defined as C<Project name>App theApp ). It will then call the InitInstance function of your class to start the DLL's execution.
So, all in all, create a new project by using the MFC DLL Wizard. This will solve 99% of the problems you listed, although moving the code from the current project into the new skeleton project may be quite difficult.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Hi there,
I have a CFormView that has several custom controls layed in it. My question is how to make those controls inform CFormView of certain events without using SendMessage? Is there any way(s)?
All comments and suggestions welcome.
Much obliged for taking the time,
David
PS: Can you also let me know of what the (valid) range of user WM messages are?
|
|
|
|
|
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.
|
|
|
|
|