2013-04-03 6 views
0

В настоящее время я работаю над внутренним расширением Adobe AIR, которое предоставляет возможности простого манипулирования сканером изображений с использованием TWAIN.
Я использую CTwain класс найден в http://www.codeproject.com/Articles/296/A-C-Wrapper-for-TWAIN

Когда я использовать этот класс в ОС Windows Application (EXE), он работает, как ожидалось, но в библиотеке DLL (который мне нужно создать файл АНХ) оно падает, когда Твен устройства UI закрывается (при завершении сканирования или нажатием кнопки Отмена)

У меня проблема: где-то в файле DllMain.cpp (возможно, цикл сообщений), потому что в приложении со стартовой функцией APIENTRY _tWinMain работает отлично.Adobe AIR Native Extension TWAIN Image Scanner

Код
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; 
    } 

} 

ответ

0

Я нашел другой wraper Twain - C++ версии из EzTwain - отлично работает
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 

Спасибо в любом случае

0

Вы не; по-видимому, имеют какой-либо синхронизации потоков.

Прежде всего, похоже, что существует условие гонки между инициализацией g_hwnd и его использованием в AcquireTwain и т. Д. Это, вероятно, не ваша проблема, но вы должны учитывать это - если вы получаете доступ к g_hwnd из основного AIR нить, тогда вы должны синхронизировать доступ к нему с помощью CRITICAL_SECTION или мьютекса.

Однако, если вы можете просто использовать критический раздел, чтобы убедиться, что g_hwnd правильно инициализирован, а затем отправите сообщения в очередь сообщений, чтобы асинхронно выполнить покупку. i.e отправляете сообщение Windows в g_hwnd, а затем вызываете CTwain :: приобретаете из потока.
Возможно, вам также понадобится создать CTwain из потока и т. Д. В принципе, просто сделайте его потокобезопасным.

Я никогда не писал родное расширение для Windows (только для iOS), поэтому не уверен в этом ... но, возможно, есть способ получить дескриптор окна из среды выполнения AIR, который можно использовать без необходимости вторичная нить (если только CTwain не блокирует?). Это сделало бы это намного проще.

+0

На firsf пытался создать CTwain с параметром GetForegroundWindow() и без файла mainDll. Прямолинейные функции, такие как selectSource, работали нормально, но поскольку цикл сообщений не был реализован, все остальное не работало. Если есть способ добавить цикл сообщений к HWND, полученный с помощью функции GetForegroundWindow()? –