【问题标题】:Adobe AIR Native Extension TWAIN Image ScannerAdobe AIR 原生扩展 TWAIN 图像扫描仪
【发布时间】:2013-04-03 16:10:13
【问题描述】:

目前我正在开发 Adob​​e AIR Native 扩展,它提供了使用 TWAIN 简单操作图像扫描仪的可能性。
我使用在http://www.codeproject.com/Articles/296/A-C-Wrapper-for-TWAIN 找到的 CTwain

当我在 Windows 应用程序 (.exe) 中使用此类时,它按预期工作,但在 dll(我需要创建一个文件)中,当 Twain 设备 UI 关闭时(扫描完成或单击取消按钮)它崩溃

我认为问题出在 DllMain.cpp 文件中(可能是消息循环),因为在具有启动函数 APIENTRY _tWinMain 的应用程序中它运行良好。

代码
DLLMain.cpp

#include "stdafx.h"
#include "TwainCpp.h"
#include "resource.h"

using namespace std;

HWND g_hwnd = NULL;
HINSTANCE g_hInstance = NULL;
BOOL isValid = false;
BOOL isCreated = false;
CTwain *twain = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_CREATE:         
            break;
        case WM_DESTROY:            
            PostQuitMessage(0);
            break;
    }   
    return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL CreateAppWindow()
{
    WNDCLASS  wc;
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
    wc.lpszMenuName =  "FRETwainMenu";
    wc.lpszClassName = "FRETwainClass";

    if(RegisterClass(&wc))
    {
        HWND hWnd;          
            char title[50];
            wsprintf(title, "FRETwain:%x", g_hInstance);
            hWnd = CreateWindow("FRETwainClass", title, WS_DISABLED,               CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,                      HWND_MESSAGE, NULL, g_hInstance, NULL);
            if(hWnd)
            {       
                g_hwnd = hWnd;                  
                return TRUE;                    
            }               
            return FALSE;       
    }   
    return FALSE;
}

DWORD WINAPI CreateAppThread()
{   
    if(CreateAppWindow())
    {
        MSG msg;
        isCreated = true;
        while(GetMessage(&msg, NULL, 0, 0) > 0)
        {
            if(twain != NULL){              
                twain->ProcessMessage(msg);             
            }   
            TranslateMessage(&msg);
            DispatchMessage(&msg);                      
        }       
        return TRUE;
    }
    return FALSE;
}

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID lpvReserved)
{
    switch(reason)
    {
         case DLL_PROCESS_ATTACH:
            g_hInstance = hInstance;            
            HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateAppThread, (LPVOID)NULL, 0, NULL);
            break;
    }        
    return TRUE;
}

FRETwain.cpp(上下文文件)

#include <windows.h>
#include "FRETwain.h"

extern BOOL isValid;
extern BOOL isCreated;
extern HWND g_hwnd;
extern CTwain *twain;

extern "C"
{   
    FREObject AcquireTwain(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
    {   
        FREObject result;
        uint32_t ret = 0;   
        if(isValid){
            twain->Acquire(TWCPP_ANYCOUNT);
            ret = 1;
        }   
        FRENewObjectFromBool(ret, &result);
       return result;
    }

    FREObject setDefaultDevice(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
    {   
        FREObject result;
        uint32_t ret = 0;   
        if(isValid){
            twain->SelectSource();
            ret = 1;
        }
        FRENewObjectFromBool(ret, &result);
        return result;
    }

    FREObject initTwain(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
    {       
        FREObject result;
        uint32_t isTwain = 0;   
        if(!isValid){
            twain = new CTwain(g_hwnd, ctx);
            isValid = twain->IsValidDriver();
        }       
        if(isValid)
            isTwain = 1;
        FRENewObjectFromBool(isTwain, &result);
        return result;
    }

}

【问题讨论】:

    标签: c++ image-processing air air-native-extension twain


    【解决方案1】:

    您似乎没有任何线程同步。

    首先,g_hwnd 的初始化和它在 AcquireTwain 等中的使用之间似乎存在竞争条件。这可能不是您的问题,但您应该考虑到这一点 - 如果您从主 AIR 线程访问 g_hwnd那么您必须使用 CRITICAL_SECTION 或互斥锁来同步对它的访问。

    但是,如果您可以只使用关键部分来确保 g_hwnd 正确初始化,然后将消息发布到其消息队列以异步执行获取。 即向 g_hwnd 发布 Windows 消息,然后从线程内调用 CTwain::Acquire。
    您可能还需要从线程等中创建 CTwain。基本上,只需使其成为线程安全的。

    我从来没有为 Windows 编写过本机扩展(仅适用于 iOS),因此对此不确定...但也许有一种方法可以从 AIR 运行时获取窗口句柄,无需辅助即可使用线程(除非 CTwain 块?)。这样会轻松很多。

    【讨论】:

    • 最初尝试使用 GetForegroundWindow() 参数且没有 mainDll 文件创建 CTwain。像 selectSource 这样的直截了当的函数工作正常,但由于没有实现消息循环,其他一切都不起作用。如果有什么方法可以将消息循环添加到使用 GetForegroundWindow() 函数接收到的 HWND 中?
    【解决方案2】:

    我找到了另一个 Twain 包装器 - EzTwain 的 C++ 版本 - 完美运行
    header file, source file

    在同一线程中调用消息循环

    void EZTAPI TWAIN_ModalEventLoop(void)  
    {  
        MSG msg;  
    
        while ((nState >= 5) && !hDib && GetMessage((LPMSG)&msg, NULL, 0, 0)) {  
            if (!TWAIN_MessageHook ((LPMSG)&msg)) {  
                TranslateMessage ((LPMSG)&msg);  
                DispatchMessage ((LPMSG)&msg);  
            }  
        } // while  
    } // TWAIN_ModalEventLoop 
    

    还是谢谢

    【讨论】:

      猜你喜欢
      • 2015-05-02
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 2012-12-14
      • 2015-02-23
      相关资源
      最近更新 更多