|
I have some problems that are a little hard to explain, but I will try my best. I am trying to write a dll that will be called by an Excel VBA macro. The dll communicates with a barcode scanner and generates an event when a reading has completed. All communications between the VBA code and the dll are working perfectly. The manufacturer of the barcode scanner provided a sample mfc stand-alone (NOT dll) application with source code and I am now trying to convert that source code into a dll with no GUI. The main code (the event handling, the communications with the scanner, etc) resides within a class that inherits a CDialog. Begin message map looks like this:
BEGIN_MESSAGE_MAP(CBarcodeScannerDemoDlg, CDialog)
ON_BN_CLICKED(IDC_ReadCodes, OnReadCodes)
ON_WM_DESTROY()
ON_MESSAGE (WMU_NEW_CODE_AVAILABLE , OnNEW_CODE_AVAILABLE)
ON_MESSAGE (WMU_START_THREAD , OnSTART_THREAD)
ON_MESSAGE (WMU_STOP_THREAD , OnSTOP_THREAD)
ON_MESSAGE (WMU_KILL_THREAD , OnKILL_THREAD)
END_MESSAGE_MAP()
Thus, when the IDC_ReadCodes button is pressed, OnReadCodes is executed. Since I want a GUI-less dll, I really don't need to inherit the CDialog, but what should I inherit instead? If I just create new a class to put the main code in, what should I replace CDialog with in the BEGIN_MESSAGE_MAP macro above? I am a beginner C++ developer, please have that in mind when replying. If you need further information or clarifications, please don't hesitate to reply. Any help would be greatly appreciated.
|
|
|
|
|
Look at the hierarchy of things that CDialog is derived from. Way back in there is something called CCmdTarget or similar. This is about the most basic class you can use for message processing. CWnd might be a better choice. It all depends how much help vs baggage you want. Don't be afraid to roll your own if you need to. It's a learning experience more valuable than anything you can get from a book.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
I decided to go with the CWnd option. I seem to have problems sending messages. I have the following code:
BEGIN_MESSAGE_MAP(CBarCodeScannerInterface, CWnd)
ON_MESSAGE (WMU_START_THREAD, OnSTART_THREAD)
END_MESSAGE_MAP()
void CBarCodeScannerInterface::OnReadCodes()
{
::SendMessage(m_hWnd, WMU_START_THREAD , NULL, NULL);
}
LONG CBarCodeScannerInterface::OnSTART_THREAD(UINT wParam, long lParam)
{
// This method is never executed, even though OnReadCodes was executed
}
I suspect the variable m_hWnd has an invalid value and that's why the message isn't sent properly. How and where do I assign m_hWnd a proper value?
|
|
|
|
|
In this case m_hWnd has to be equal to the window handle of the window you're sending the message to. The window handle is a Windows as opposed to your-app value. Hence only Windows can generate it when the window is created, ( CreateWindowEx API or similar ). Once this is done you can extract it from the CWnd class where MFC will have deposited it it in the m_hWnd member.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Thanks for replying. My main class looks like this:
class CBarCodeScannerInterface : public CWnd
{
...
}
To create an object of that class (which inherits the CWnd class), I use the following:
CBarCodeScannerInterface myInstance;
If I understand you correctly, using my way of creating the object there is no way the m_hWnd can be properly assigned? If so, can I somehow make CreateWindowEx create an object of type CBarCodeScannerInterface instead?
|
|
|
|
|
Window creation is an interesting process. You need to register a Window Class, it's not a C++ class and doesn't go in the registry so you can tell how antiquated this stuff is. This is a process you'll need to look up in the docs but it amounts to telling the Windows Kernel about a function in your app and registering a type of Window which your app will be handling. When you call CreateWindow you tell it which class of Window you want and then all messages get routed through your registered Window function. MFC::CWnd no doubt has helpers for all this but it's a while since I used it at that level.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Again, thanks for your time and help.
|
|
|
|
|
Hi Experts,
I am new in VC++.Please suggest me some books to get trained in vc++.
|
|
|
|
|
Hi,
there are tons of free material on the www, but if you like
some "paper" then i can recommend some books from MSPress,
which i consider to be the best available (beside the original
MSDN Libary which is also for free!). Its up to you whether you
want to read the MSDN Libary or want to spend a lot of money
for some books that will be outdated in a short time (view years
in common).
Go here and search with C++ inside the Web Document:
http://www.microsoft.com/mspress/findabook/list/title.aspx[^]
---------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
kerem.g@arcor.de
Best Quote: "Ain't nobody a badass with a double dose
of rock salt...", Kill Bill Vol.2
Microsoft Live Space: http://kerem-g.spaces.live.com/
Latest Open-Source Projects
Tools and Software: http://entwicklung.junetz.de
Sign my guestbook: http://entwicklung.junetz.de/guestbook/
-----------------------
"This reply is provided as is, without warranty express or implied."
|
|
|
|
|
I liked "Sam's Teach Yourself Visual C++ in 21 Days", it starts of easy and teaches you relevant things.
//Johannes
|
|
|
|
|
13 essential skills in vc++ by steven holzner.
|
|
|
|
|
|
I have created a dll in MFC using the Visual Studio wizard and the dll exports a function called MyExportedMethod:
#include "stdafx.h"
#include "DllProblem.h"
BEGIN_MESSAGE_MAP(CDllProblemApp, CWinApp)
END_MESSAGE_MAP()
CDllProblemApp::CDllProblemApp()
{
}
CDllProblemApp theApp;
BOOL CDllProblemApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
double _stdcall MyExportedMethod(double param)
{
// Here I would like to call the
// MethodIwouldLikeToInvoke method in class MyClass.
// How do I do that???
return 0;
}
I would like the MyExportedMethod method to invoke a (non-static) method in a class called MyClass:
#include "stdafx.h"
#include "DllProblem.h"
#include "MyClass.h"
IMPLEMENT_DYNAMIC(MyClass, CDialog)
MyClass::MyClass(CWnd* pParent /*=NULL*/): CDialog(MyClass::IDD, pParent)
{
}
MyClass::~MyClass()
{
}
void MyClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(MyClass, CDialog)
END_MESSAGE_MAP()
void MyClass::MethodIwouldLikeToInvoke()
{
MessageBox(L"Congratulations! The exported method successfully invoked the correct method!");
}
What should I add to successfully invoke the MethodIwouldLikeToInvoke from the MyExportedMethod method? This may seem like a simple problem and that is ok, this is not a trick question (I'm a beginner C++ programmer). Thank you in advance!
|
|
|
|
|
To call a non-stati cinstance method what you need is an instance. You could an a MyClass as a member of CDllProblemApp then you have one once the application object is constructed.
<br />
<br />
class CDllProblemApp...<br />
{<br />
...<br />
MyClass myInstance;<br />
...<br />
};<br />
<br />
<br />
double _stdcall MyExportedMethod(double param)<br />
{<br />
theApp.myInstance.MethodIwouldLikeToInvoke();<br />
return 0;<br />
}<br />
<br />
or you could just create a stack based local instance
<br />
double _stdcall MyExportedMethod(double param)<br />
{<br />
MyClass anInstance;<br />
anInstance.MethodIwouldLikeToInvoke();<br />
return 0;<br />
}<br />
depending on what you want it for.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Thanks for your suggestions, however, I can't get them to work. In both cases I get Debug Assertion Failed from the application that calls the dll (Microsoft Excel). The strange thing is that the following works perfectly:
BOOL CDllProblemApp::InitInstance()
{
CWinApp::InitInstance();
MyClass anInstance;
anInstance.MethodIwouldLikeToInvoke();
return TRUE;
}
but if I place the code in MyExportedMethod I get the Debug Assertion:
double _stdcall MyExportedMethod(double param)
{
MyClass anInstance;
anInstance.MethodIwouldLikeToInvoke(); // THIS LINE GENERATES DEBUG ASSERTION!!!
return 0;
}
Please note that MyExportedMethod is not part of the class CDllProblemApp. Should it be? If so, how do I export that method?
|
|
|
|
|
??That doesn't sound right. What exactly does the Debug Assertion say. Is is occuring in MethodIwouldLikeToInvoke? I guess it must be. In which case you have another problem, your call is working but something else is not.
To export a class member function it must be public and you will need to export the class itself. For an example of how to do this generate a new Dll with the VS2005 Wizard and choose 'Exports Some Symbols'. That will give you a commented example of how to do a variety of exports.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Yes, it is occuring in MethodIwouldLikeToInvoke, there's something wrong with my MessageBox statement. If I put some other code in the MethodIwouldLikeToInvoke, it is executed properly. I still have a problem left, but I will start a new thread for that issue. Thanks a lot for your help!
|
|
|
|
|
How can we know that the buffer of the Socket is full or not?
Anyone Please provide help.
Thanks and Regards,
Manish Patel.
B.E. - Information Technology.
|
|
|
|
|
In my experience you know when a socket buffer is full because things start to go badly wrong. A full socket buffer is not something you want to be waiting around for or in fact ever see. Best to avoid it if you can. Filling socket buffers on Win9x will frequently take down the whole operating system and the process on Windows NT. The fact that it took MS 3 versions of Windows to stop this being a total disaster area tells you all you need to know. Don't go there
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
But i want to stop sending messages when buffer gets full because when buffer gets full client closes the connection.
Any idea?
Thanks in advance
Manish Patel.
B.E. - Information Technology.
|
|
|
|
|
My point is that you need to stop sending messages BEFORE the buffer gets full because once it's full it's too late, data is already corrupt and the connection drops. Ultimately the only reliable way I've found to do this is to make sure that your client reads messages faster than your server sends them so the buffer never fills up. The client should probably have a dedicated thread or threads servicing the socket connection and placing the messages recieved into a queue in memory that you control. If the queue gets too long the client will need to tell the server or find some other way to cope.
Your server will ultimately be talking to more than one client right? over a limited speed network, so there's no reason your client can't keep up with the traffic your server can send it as long as it can handle the full network bandwidth. On average it will only need to handle a tiny fraction of this as the bandwidth is shared.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Thats true but my client is flash and it automatically sending and recieving messages.
So i cant control client. So let me is there any way by which i can come to know that buffer can accept only some amount of packets.
Is it possible??
Manish Patel.
B.E. - Information Technology.
|
|
|
|
|
Only if there is some indication within the protocol that Flash is using. Does it send acknowledgements? You could count the mismatch between messages sent and acks recieved and see what the limit is before Flash goes Bang. Then stop sending whenever you've sent x number more messages than you've had acks for. This will require a bit of trial and error to get right, keeping track of messages sizes etc. Other people must have had this problem with Flash. You could look for a Flash specific forum where you might get better help. I'm afarid I've never used Flash or written a socket server app against an exisitng 3rd party black box client. Good luck
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
You know you're getting ahead when send() returns less bytes sent than you
requested to be sent (it may even return 0 if the send buffer is completely full!).
You should always be checking the return value so you can resend unsent bytes.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Matthew Faithfull wrote: A full socket buffer is not something you want to be waiting around for or in fact ever see.
What? Do you have a link?
I've been overstuffing stuffing sockets since before Win95 and I've NEVER heard anything like that.
If you ignore unsent bytes then chances are real good that the app-layer protocol is going to be f*cked
but I've never heard of a problem below the app layer of the protocol stack.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|