Home › Forums › TWAIN Classic › Twain Callback — Developing with MFC
- This topic has 5 replies, 3 voices, and was last updated 15 years ago by garbuck.
- AuthorPosts
Hi All,
I’m trying to develop an MFC class to interface with Twain 2.0. I’ve gotten most of my code working except for the implementation of the callback function.
MFC/C++ has an implicit THIS pointer which I need to pass through the callback mechanism. I set up the TWAIN callback and try to put the THIS pointer in the REFCON parameter so I can access it through the pData variable later in the process.
Everything is working until my callback function is executed. pData is always coming through as NULL. Am I just not using the callback structure appropriately or is there an issue with the DSM/DS not properly passing the pData through to the callback?
If I could get the callback working I’d be able to finish up my MFC class. Otherwise I’ll need to implement a message pump and do things the old way, or perhaps just write something in C instead.
Any direction or input is appreciated.
Thanks.
Daniel
No one has any suggestions about implementing the callback using MFC? Is it possible, or am I just spinning my wheels?
Specifically, am I supposed to be able to pass user data into the create callback twain call and then access that data later when the DSM/DS calls me back?
Thanks.
Daniel
I, too, assumed that the RefCon value was intended for passing back context variables such as this pointers. It works fine for that on the Mac. The Mac implementation relies entirely on the callback and does not need an event pump.
The 2.0 DSM is broken. When I discovered the RefCon passback was not implemented, I decided just to ignore the callback feature on Windows. That worked fine for the Epson scanner I was using for tests. However, when I tested with the TWAIN dummy software source, it blocked on the GetMessage call, even though I had not defined a callback. Reverting back to twain_32.dll (and supplying a window handle to DSM_Entry on startup) worked fine with the software source. So, that made me worry that future drivers for real devices might rely on the callback being there for the 2.0 DSM, causing apps that don’t implement it to hang.
The docs also do not make it clear that, on Windows, you need to implement both the callback and the event pump. I assumed it would work like the Mac — no more message pump. But when I tried that with the Epson, it showed empty UI windows, making it obvious the event pump was still needed.
I looked at the TWAIN sample application. It implements the callback, but uses a global variable to track it. That’s poor coding practice: globals are not thread-safe.
One possibility would be to store your this pointer in thread local storage (google TlsAlloc and friends). Another might be to cram it past the end of your manufacturer or product name in the appId and make sure your name string is 29 characters or less (better make that 25 to allow for 64-bit).
Thanks for the feedback garbuck. Appreciate you taking the time to respond.
I haven’t tried anything else at this point, but I will look into your reccommendations with the TLS.
If I get it to work I’ll update this thread.
– Daniel
Thank you for bringing this to our attention.
The intention of RefCon is missing from the spec and will be fixed. RefCon will be returned in pData in the next release of the DSM. Because it was not defined as TW_MEMREF it should not be used to store a pointer because it will fail on 64bit OS.
How is Apple getting around this on 64bit if they are passing pointers?
Maybe passing in a TlsAlloc value is the way to go.
Yes the Sample App uses globals. 🙂Modifying the application name might unwanted have side effects. Some DS choose to store the last used settings for each Application name that opens it. If the name keeps changing you might not get the settings you expected.
Using callbacks does not eliminate the need of the windows event message pump.
On the Mac starting with OSX if was required for the DS to register their own functions with the OS for handling windows messages. That meant they no longer needed the DAT_EVENT for pumping messages and added the Callback to handle the DS notifying the App.
Unlike the Mac on Windows TWAIN 1.x DS will continue to work with TWAIN 2.x Applications. It does not matter if the TWAIN application implements notification via callbacks or DAT_EVENT.
The important thing to remember in the callback routine is to get the message and data passed. Return immediately. Then act on the message received.
Regards,
Jim Watters**************************************************
JFL Peripheral Solutions Inc.
http://www.jflinc.com/
Your Expert Source of Custom Software and Services
for TWAIN Applications, Data Sources,
Peripheral Drivers and Support Software.
**************************************************@jimwatters wrote:
How is Apple getting around this on 64bit if they are passing pointers?
I don’t know. My app was 32-bit, so I was able to use it to pass along an Objective-C self pointer.
However, according to the file command, the TWAIN binary for OS 10.5 supports four architectures: ppc7400, ppc64, i386, and x86_64. OS X also supports thread-local storage (not that it’s hard to implement on your own). And, of course, you can just be dirty and use a global, if you are sure it won’t be an issue for your app.
Modifying the application name might unwanted have side effects. Some DS choose to store the last used settings for each Application name that opens it. If the name keeps changing you might not get the settings you expected.
In that connection, I noticed that the DSM will let you open multiple appId blocks, as long as the product names are different (it doesn’t consider the manufacturer or product family fields). I assume that’s what you would need to do if you wanted to drive multiple devices simultaneously. The message queue that the Windows window handle supports is per-thread, and the handle is per DSM app, not per source. So, to drive eight scanners at once, you would start up eight threads, each of which would open the DSM with a slightly different product name … ScannerMaster 1, ScannerMaster 2, etc.
BTW, I found that my problem with the dummy software datasource hanging under DSM 2 went away if I supplied a window handle on the open. I had ripped out the window handle code, so I put it back in.
- AuthorPosts