include "twaincpp.h"
#include <QtGlobal>
#include <QDateTime>
#include <QString> #pragma execution_character_set("utf-8"); CTwain::CTwain(HWND hWnd)
{
m_hMessageWnd = nullptr;//消息窗口句柄
m_hTwainDLL = nullptr;//是否已载入库
m_pDSMProc = nullptr;//数据源管理器
m_bSourceSelected = false;//是否已选择数据源
m_bDSOpen = false;//是否已打开数据源
m_bDSMOpen = false;//是否已打开数据源管理器
m_bSourceEnabled = false;//数据源是否设为可用
m_bModalUI = true;
m_nImageCount = TWCPP_ANYCOUNT;
if(hWnd)
{
qDebug()<<"在构造函数中安装Twain";
InitTwain(hWnd);
}
} CTwain::~CTwain()
{
ReleaseTwain();
} /*
Initializes TWAIN interface . Is already called from the constructor.
It should be called again if ReleaseTwain is called.
hWnd is the window which has to subclassed in order to recieve
Twain messaged. Normally - this would be your main application window.
初始化TWAIN接口。已经从构造函数调用。
如果调用ReleaseTwain,则应再次调用它。
hWnd是必须进行子类化以便接收的窗口Twain消息。
通常 - 这将是您的主要应用程序窗口。
*/
bool CTwain::InitTwain(HWND hWnd)
{
qDebug()<<"****************开始安装Twain****************";
char libName[512];
if(IsValidDriver())
{
return true;
}
memset(&m_AppId,0,sizeof(m_AppId));
if(!IsWindow(hWnd))//确定给定的窗口句柄是否标识一个已存在的窗口
{
return false;
}
m_hMessageWnd = hWnd;//要传递消息的窗口
strcpy_s(libName,"TWAIN_32.DLL"); m_hTwainDLL = LoadLibraryA(libName);//载入库
if(m_hTwainDLL != nullptr)
{
qDebug()<<"已载入有效扫描驱动"; //获取数据源管理器入
if(!(m_pDSMProc = (DSMENTRYPROC)GetProcAddress(m_hTwainDLL,(LPCSTR)MAKEINTRESOURCE(1))))
{
qDebug()<<"获取数据源管理器入口失败";
FreeLibrary(m_hTwainDLL);
m_hTwainDLL = nullptr;
}
else
{
qDebug()<<"获取数据源管理器入口成功";
}
}
if(IsValidDriver())//成功载入驱动且获取了数据源管理器
{
GetIdentity();//设置应用程序信息 //打开数据源管理器
m_bDSMOpen = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&m_hMessageWnd);
if(m_bDSMOpen)
{
qDebug()<<"初始化Twain接口:打开数据源管理器成功";
get_source_list();
qDebug()<<"****************结束安装Twain****************";
return true;
}
else
{
qDebug()<<"初始化Twain接口:打开数据源管理器失败";
qDebug()<<"****************结束安装Twain****************";
return false;
}
}
else
{
qDebug()<<"****************结束安装Twain****************";
return false;
}
} /*
Releases the twain interface . Need not be called unless you
want to specifically shut it down.
释放twain接口。除非你想要特别关闭它。
*/
void CTwain::ReleaseTwain()
{
qDebug()<<"****************开始析构Twain****************";
if(IsValidDriver())//如果已加载有效的驱动程序且存在数据源管理器入口
{
CloseDSM();
FreeLibrary(m_hTwainDLL);
m_hTwainDLL = nullptr;
m_pDSMProc = nullptr;
sourcelist.clear();
}
qDebug()<<"****************结束析构Twain****************";
} /*
Returns true if a valid driver has been loaded
如果已加载有效的驱动程序且存在数据源管理器入口,则返回true
*/
bool CTwain::IsValidDriver() const
{
return (m_hTwainDLL && m_pDSMProc);
} /*
Entry point into Twain. For a complete description of this
routine please refer to the Twain specification 1.8
进入Twain的入口点。有关此的完整描述
例程请参考Twain规范1.8
*/
bool CTwain::CallTwainProc(pTW_IDENTITY pOrigin,pTW_IDENTITY pDest,
TW_UINT32 DG,TW_UINT16 DAT,TW_UINT16 MSG,
TW_MEMREF pData)
{
// qDebug()<<"****************开始数据源管理器相关操作****************";
if(IsValidDriver())//如果已加载有效的驱动程序且存在数据源管理器入口
{
USHORT ret_val; //数据源管理器相关操作
ret_val = (*m_pDSMProc)(pOrigin,pDest,DG,DAT,MSG,pData); // qDebug()<<"数据源管理器相关操作结果"<<ret_val;
m_returnCode = ret_val; /////////////////////吐血开始//////////////////
// if(ret_val != TWRC_SUCCESS)
// {
// qDebug()<<"数据源管理器相关操作失败"; // //初始化数据源管理器
// (*m_pDSMProc)(pOrigin,pDest,DG_CONTROL,DAT_STATUS,MSG_GET,&m_Status);
// }
// else
// {
// qDebug()<<"数据源管理器相关操作成功";
// }
////////////////////吐血结束///////////////// // qDebug()<<"****************结束数据源管理器相关操作****************A";
return (ret_val == TWRC_SUCCESS);
}
else
{
m_returnCode = TWRC_FAILURE;
// qDebug()<<"****************未加载有效的驱动程序或不存在数据源管理器入口****************";
// qDebug()<<"****************结束数据源管理器相关操作****************B";
return false;
}
} /*
This function should ideally be overridden in the derived class . If only a
few fields need to be updated , call CTawin::GetIdentity first in your
derived class
理想情况下,应在派生类中重写此函数。 如果只有一个
几个字段需要更新,首先在你的电话中调用CTawin :: GetIdentity
派生类 设置应用程序信息
*/
void CTwain::GetIdentity()
{
// Expects all the fields in m_AppId to be set except for the id field.
//期望m_AppId中的所有字段都要设置,除了id字段。
m_AppId.Id = 0; // Initialize to 0 Source Manager
// will assign real value)
m_AppId.Version.MajorNum = 1; //Your app's version number
m_AppId.Version.MinorNum = 0;
m_AppId.Version.Language = TWLG_USA;
m_AppId.Version.Country = TWCY_USA;
strcpy_s (m_AppId.Version.Info, "1.0");
m_AppId.ProtocolMajor = TWON_PROTOCOLMAJOR;
m_AppId.ProtocolMinor = TWON_PROTOCOLMINOR;
m_AppId.SupportedGroups = DG_IMAGE | DG_CONTROL;
strcpy_s (m_AppId.Manufacturer, "MICSS");
strcpy_s (m_AppId.ProductFamily, "Generic");
strcpy_s (m_AppId.ProductName, "jiandao Twain");
} /*
Called to display a dialog box to select the Twain source to use.
This can be overridden if a list of all sources is available
to the application. These sources can be enumerated by Twain.
it is not yet supportted by CTwain.
调用以显示一个对话框以选择要使用的Twain源。
如果所有源列表都可用,则可以覆盖此项
到申请。这些来源可以由Twain列举。
它还没有得到CTwain的支持。 //选择数据源
MSG_USERSELECT的效果是弹出一个框让用户选择数据源
*/
bool CTwain::SelectSource()
{
qDebug()<<"****************开始选择数据源****************";
memset(&m_Source,0,sizeof(m_Source));
if(!SourceSelected())//扫描时候未选择数据源,则设置数据源为默认的数据源
{
SelectDefaultSource();
}
if(CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_USERSELECT,&m_Source))//MSG_OPENDS
{
m_bSourceSelected = true;
qDebug()<<"成功应用所选的数据源";
}
else
{
m_bSourceSelected = false;
qDebug()<<"应用所选的数据源失败";
}
qDebug()<<"****************结束选择数据源****************";
return m_bSourceSelected;
} //选择默认的数据源
bool CTwain::SelectDefaultSource()
{
qDebug()<<"未选择数据源,使用默认的数据源";
m_bSourceSelected = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETDEFAULT,&m_Source);
if(m_bSourceSelected)
{
qDebug()<<"使用默认的数据源成功";
}
else
{
qDebug()<<"使用默认的数据源失败";
}
return m_bSourceSelected;
} //关闭数据源 先禁用再关闭
void CTwain::CloseDS()
{
qDebug()<<"****************开始关闭数据源****************";
if(DSOpen())//数据源是打开的
{
DisableSource();
qDebug()<<"关闭数据源";
CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&m_Source);
m_bDSOpen = false;
}
qDebug()<<"****************结束关闭数据源****************";
} //关闭数据源管理器
void CTwain::CloseDSM()
{
qDebug()<<"****************开始关闭数据源管理器****************";
if(DSMOpen())//如果数据源管理器是打开的
{
CloseDS();//关闭数据源
qDebug()<<"执行关闭数据源管理器";
CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_PARENT,MSG_CLOSEDSM,(TW_MEMREF)&m_hMessageWnd);
m_bDSMOpen = false;
}
qDebug()<<"****************结束关闭数据源管理器****************";
} /*如果:
1、数据源是打开的
2、数据源管理器是打开的
3、数据源管理器入口存在
返回true
*/
bool CTwain::DSMOpen() const
{
return IsValidDriver() && m_bDSMOpen;
} /*如果:
1、数据源是打开的
2、数据源管理器是打开的
3、数据源管理器入口存在
4、已载入扫描驱动
返回true
*/
bool CTwain::DSOpen() const
{
return IsValidDriver() && DSMOpen() && m_bDSOpen;
} //打开作为输入参数提供的数据源
bool CTwain::OpenSource(TW_IDENTITY *pSource)
{
if(pSource)
{
m_Source = *pSource;
}
if(DSMOpen())//如果此时数据源管理器是打开的
{
qDebug()<<"xxxxxxxxxxx";
if(!SourceSelected())//此时未选中数据源
{
SelectDefaultSource();
}
//打开数据源
m_bDSOpen = CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_OPENDS,(TW_MEMREF)&m_Source);
}
return DSOpen();
} /*
Should be called from the main message loop of the application. Can always be called,
it will not process the message unless a scan is in progress.
应该从应用程序的主消息循环调用。可以随时调用,
除非正在进行扫描,否则它不会处理消息。 消息事件
*/
bool CTwain::ProcessMessage(MSG msg)
{
if (msg.message == 528) // don't really know why...
{
return false;
} if (m_hMessageWnd == nullptr)
{
return false;
} if(SourceEnabled() && m_pDSMProc)//如果数据源可用
{
TW_EVENT twEvent;
twEvent.pEvent = (TW_MEMREF)&msg;
twEvent.TWMessage = MSG_NULL; TW_UINT16 twRC = TWRC_NOTDSEVENT; //从扫描仪中获取事件
twRC = CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT,(TW_MEMREF)&twEvent);
if(twRC != TWRC_NOTDSEVENT)
{
switch(twEvent.TWMessage)
{
case MSG_XFERREADY:
TransferImage();//传输图像或取消传输
break;
case MSG_CLOSEDSREQ://关闭数据源
CloseDS();
break;
case MSG_CLOSEDSOK:
break;
case MSG_DEVICEEVENT:
break;
default: ;
//qDebug()<<"都不是";
}
}
else
{
qDebug()<<"无法获取事件";
}
return false;
}
else
{
// qDebug()<<"数据源不可用";
}
return false;
} /*
Queries the capability of the Twain Data Source
查询twain数据源的功能
*/
bool CTwain::GetCapability(TW_CAPABILITY& twCap,TW_UINT16 cap,TW_UINT16 conType)
{
if(DSOpen())
{
twCap.Cap = cap;
twCap.ConType = conType;
twCap.hContainer = nullptr; if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_GET,(TW_MEMREF)&twCap))
{
return true;
}
}
return false;
} /*
Queries the capability of the Twain Data Source
同上 重载函数
*/
bool CTwain::GetCapability(TW_UINT16 cap,TW_UINT32& value)
{
TW_CAPABILITY twCap;
if(GetCapability(twCap,cap))
{
pTW_ONEVALUE pVal;
pVal = (pTW_ONEVALUE )GlobalLock(twCap.hContainer);
if(pVal)
{
value = pVal->Item;
GlobalUnlock(pVal);
GlobalFree(twCap.hContainer);
return true;
}
}
return false;
} /*
Sets the capability of the Twain Data Source
设置twain数据源的功能
*/
bool CTwain::SetCapability(TW_UINT16 cap,TW_UINT16 value,bool sign)
{
if(DSOpen())
{
TW_CAPABILITY twCap;
pTW_ONEVALUE pVal;
bool ret_value = false; twCap.Cap = cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE)); if(twCap.hContainer)
{
pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer);
pVal->ItemType = sign ? TWTY_INT16 : TWTY_UINT16;
pVal->Item = (TW_UINT32)value;
GlobalUnlock(twCap.hContainer);
ret_value = SetCapability(twCap);
GlobalFree(twCap.hContainer);
}
return ret_value;
}
return false;
} bool CTwain::SetResolution(TW_UINT16 cap,TW_UINT32 value)
{
if(DSOpen())
{
TW_CAPABILITY twCap;
pTW_ONEVALUE pVal;
BOOL ret_value = FALSE; twCap.Cap = cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE)); if(twCap.hContainer)
{
pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer);
pVal->ItemType = TWTY_FIX32;
pVal->Item = (TW_UINT32)value;
GlobalUnlock(twCap.hContainer);
ret_value = SetCapability(twCap);
GlobalFree(twCap.hContainer);
}
return ret_value;
}
return FALSE;
} /*
Sets the capability of the Twain Data Source
同上 重载函数
*/
bool CTwain::SetCapability(TW_CAPABILITY& cap)
{
if(DSOpen())
{
return CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_SET,(TW_MEMREF)&cap);
}
return false;
} /*
Sets the number of images which can be accpeted by the application at one time
设置应用程序一次可接收的图像数
*/
bool CTwain::SetImageCount(TW_INT16 nCount)
{
if(SetCapability(CAP_XFERCOUNT,(TW_UINT16)nCount,true))
{
m_nImageCount = nCount;
return true;
}
else
{
if(GetRC() == TWRC_CHECKSTATUS)
{
TW_UINT32 count;
if(GetCapability(CAP_XFERCOUNT,count))
{
nCount = (TW_INT16)count;
if(SetCapability(CAP_XFERCOUNT,nCount))
{
m_nImageCount = nCount;
return true;
}
}
}
}
return false;
} /*
Called to enable the Twain Acquire Dialog. This too can be
overridden but is a helluva job .
调用以启用TWAIN获取对话框。这也可以
被重写,但这是一个地狱般的工作。 使数据源可用
*/
bool CTwain::EnableSource(bool showUI)
{
qDebug()<<"****************开始使数据源可用****************";
if(DSOpen() && !SourceEnabled())//数据源打开了且数据源不可用
{
twUI.ShowUI = false/*showUIfalse*/;//是否打开默认的UI 111111111111111111111111111111111这里不设为false会报错 看看
twUI.hParent = (TW_HANDLE)m_hMessageWnd;//消息窗口作为默认ui的主窗口
//启用数据源
if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_ENABLEDS,(TW_MEMREF)&twUI))
{
m_bSourceEnabled = true;
m_bModalUI = twUI.ModalUI;
qDebug()<<"启用数据源成功 EnableSource";
}
else
{
m_bSourceEnabled = false;
m_bModalUI = true;
qDebug()<<"启用数据源失败 EnableSource";
}
return m_bSourceEnabled;
}
return false;
} /*
Called to acquire images from the source. parameter numImages i the
numberof images that you an handle concurrently 调用以从源获取图像。参数numImages i
同时处理的图像数
*/
bool CTwain::Acquire(int numImages,TW_UINT16 duplex,TW_UINT16 size,TW_UINT16 pixel,TW_UINT16 resolution)
{
qDebug()<<"****************开始启动扫描****************";
if(DSOpen() || OpenSource())//数据源是打开可用的
{
BOOL ret_value = SetCapability(CAP_DUPLEXENABLED,duplex,TRUE);
ret_value = SetCapability(ICAP_SUPPORTEDSIZES,size,TRUE);
ret_value = SetCapability(ICAP_PIXELTYPE,pixel,TRUE);
ret_value = SetResolution(ICAP_XRESOLUTION,resolution);
ret_value = SetResolution(ICAP_YRESOLUTION,resolution);
// lqh - 设置传输模式为文件
ret_value = SetCapability(ICAP_XFERMECH,TWSX_FILE,TRUE); //设置扫描的最大张数
if(SetImageCount(numImages))
{
if(EnableSource())
{
return true;
}
else
{
qDebug()<<"启用扫描源失败";
return false;
}
}
}
return false;
} //禁用数据源
bool CTwain::DisableSource()
{
qDebug()<<"****************开始禁用数据源****************";
if(SourceEnabled())//数据源目前的状态是:可用
{
//禁用数据源
if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,&twUI))
{
m_bSourceEnabled = false;
qDebug()<<"禁用数据源成功";
return true;
}
else
{
qDebug()<<"禁用数据源失败";
return false;
}
}
else
{
qDebug()<<"数据源目前的状态是不可用,不用再次禁用";
}
return false;
} /*
Gets Imageinfo for an image which is about to be transferred.
获取即将传输的图像的ImageInfo
*/
bool CTwain::GetImageInfo(TW_IMAGEINFO& info)
{
qDebug()<<"****************开始获取图片信息****************";
if(SourceEnabled())//如果数据源是可用的
{
bool b = CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGEINFO,MSG_GET,(TW_MEMREF)&info);
if(b == true)
{
qDebug()<<"成功获取即将传输的图片信息";
}
else
{
qDebug()<<"获取即将传输的图片信息失败";
}
return b;
}
return false;
} /*
Trasnfers the image or cancels the transfer depending on the state of the
TWAIN system
根据图像的状态传输图像或取消传输
*/
void CTwain::TransferImage()
{
qDebug()<<"****************根据图像的状态传输图像或取消传输****************";
TW_IMAGEINFO info;//图片信息
bool bContinue = true;
while(bContinue)
{
if(GetImageInfo(info))//获取图片信息
{ /* lqh start */
TW_SETUPFILEXFER filexfer;
memset(&filexfer, 0, sizeof(filexfer));
QString file = "C:\\SCANFILES\\scan_" + QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz") +".bmp";
qDebug() << "scan file = " << file ;
filexfer.Format = TWFF_BMP/*TWFF_BMP*/;
strcpy(filexfer.FileName,file.toLatin1().data()); CallTwainProc(&m_AppId,&m_Source,DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, (TW_MEMREF)&(filexfer));
/* lqh end */ int permission;
permission = ShouldTransfer(info);
qDebug()<<"执行到这";
switch(permission)
{
case TWCPP_CANCELTHIS:
qDebug()<<"执行到这01";
bContinue = EndTransfer();//结束当前的传输
break; case TWCPP_CANCELALL:
qDebug()<<"执行到这02";
CancelTransfer();//中止所有传输
bContinue = false;
break; case TWCPP_DOTRANSFER:
qDebug()<<"执行到这03";
bContinue = GetImage(info);//获取图片
break;
}
}
}
} /*
Ends the current transfer.
Returns true if the more images are pending
结束当前传输。
如果有更多图像挂起,则返回true
*/
bool CTwain::EndTransfer()
{
qDebug()<<"****************执行结束当前传输****************";
TW_PENDINGXFERS twPend;
if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&twPend))
{
if (twPend.Count==0)
{
DisableSource();
}
return twPend.Count != 0;
}
return false;
} /*
Aborts all transfers
中止所有传输
*/
void CTwain::CancelTransfer()
{
qDebug()<<"****************执行终止所有传输****************";
TW_PENDINGXFERS twPend;
CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&twPend);
} /*
Calls TWAIN to actually get the image
调用twain以实际获取图像
*/
bool CTwain::GetImage(TW_IMAGEINFO& info)
{
qDebug()<<"****************获得图片****************";
HANDLE hBitmap;
// CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,&hBitmap);
//这里失败了
CallTwainProc(&m_AppId,&m_Source,DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, NULL); qDebug()<<"m_returnCode "<<m_returnCode; switch(m_returnCode)
{
case TWRC_XFERDONE:
qDebug()<<"01";
CopyImage(hBitmap,info);//本类的虚函数 子类实现获取图片后的操作
break;
case TWRC_CANCEL:
qDebug()<<"02";
break;
case TWRC_FAILURE:
break;
CancelTransfer();//终止传输
return false;
}
GlobalFree(hBitmap);//释放图片内存
return EndTransfer();
} //获取数据源列表
void CTwain::get_source_list()
{
if(!sourcelist.isEmpty())
{
sourcelist.clear();
} if (CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETFIRST,&m_Source))
{
TW_IDENTITY temp_Source = m_Source;
sourcelist.append(temp_Source);//添加到链表
// qDebug()<<"可用扫描仪:"<<temp_Source.ProductName;
while(CallTwainProc(&m_AppId,nullptr,DG_CONTROL,DAT_IDENTITY,MSG_GETNEXT,&m_Source))
{
TW_IDENTITY temp_Source = m_Source;
sourcelist.append(temp_Source);//添加到链表
// qDebug()<<"可用扫描仪:"<<temp_Source.ProductName;
} m_Source = sourcelist.value(0);//第一个可用的扫描源
m_bSourceSelected = TRUE;
}
else
{
qDebug()<<"没有可用的扫描仪";
m_bSourceSelected = FALSE;
}
}

TWAIN.CPP的更多相关文章

  1. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

  2. Json CPP 中文支持与入门示例

    在每一个Json Cpp自带*.cpp文件头加上: #include "stdafx.h" 将Json Cpp对自带的头文件的引用修改为单引号方式,例如json_reader.cp ...

  3. cpp 调用python

    在用cpp调用python时, 出现致命错误: no module named site  ,  原因解释器在搜索路径下没有找到python库.可以在调用Py_Initialize前,调用 Py_Se ...

  4. nginx+fastcgi+c/cpp

    参考:http://github.tiankonguse.com/blog/2015/01/19/cgi-nginx-three/ 跟着做了一遍,然后根据记忆写的,不清楚有没错漏步骤,希望多多评论多多 ...

  5. APM程序分析-ArduCopter.cpp

    该文件是APM的主文件. #define SCHED_TASK(func, rate_hz, max_time_micros) SCHED_TASK_CLASS(Copter, &copter ...

  6. APM程序分析-AC_WPNav.cpp

    APM程序分析 主程序在ArduCopter.cpp的loop()函数. /// advance_wp_target_along_track - move target location along ...

  7. Dev Cpp 输出中文字符问题

    最近 c++ 上机作业,vc++6.0 挂了没法用,只好用 Dev Cpp 先顶替一下,然而在遇到输出中文字符的时候出现了乱码的情况,但这种情况又非常诡异.于是简单了解了一下写成此博客. [写在前面] ...

  8. 扫描仪API接入大全:Twain, WIA 或 两者不具有.[换个思路 春暖花开]

    最近做和扫描仪接入的扫描应用程序,深深感觉到了来自底层设备和WINDOWS协议的恶意.软件专业,对计算机深层次通知机制和协议,以及与之相连接的机器的接入协议和一些参数,当时并木有认真学习和了解,前一阵 ...

  9. 【安卓】aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creating directories: Invalid argument

    这几天在使用.aidl文件的时候eclipse的控制台总是爆出如下提示: aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creatin ...

随机推荐

  1. Python+Selenium学习笔记3 - 二维码生成

    用qrcode模块生成二维码 # coding = utf-8 import qrcode qr = qrcode.QRCode( version=1, error_correction=qrcode ...

  2. mybatis的多参数传递,使用

    1.mybatis的多参数使用 mapper 使用 通过@param注解,传递到xml中的参数名称指定 public interface RedisInstanceTypesMapper extend ...

  3. NVIDIA安培架构

    NVIDIA安培架构 NVIDIA Ampere Architecture In-Depth 在2020年英伟达GTC主题演讲中,英伟达创始人兼首席执行官黄仁勋介绍了基于新英伟达安培GPU架构的新英伟 ...

  4. SpringCloud Alibaba实战(5:子模块基本业务开发)

    源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 在上一节里,我们搭建了一个微服务项目的整体架构,并进行了版本控制. 接下来我们进一步 ...

  5. 【NX二次开发】切换模块的方法,切换到制图模块

    源码(NX12.0): Session theSession = NXOpen::Session::GetSession(); theSession->ApplicationSwitchImme ...

  6. 【VBA】字符串处理

    InStr 函数:查找字符串 1 Sub InStr函数() 2 Dim strTemp As String 3 strTemp = "=AAA=BBB=C" 4 Debug.Pr ...

  7. windows 7系统安装与配置Tomcat服务器环境

    windows 7系统安装与配置Tomcat服务器环境 学习了一个月的java基础,终于要迈向java web领域.学习java web开发就离不开服务器的支持,由于本人是菜鸟,只好求助度娘谷哥.在此 ...

  8. Java synchronized对象级别与类级别的同步锁

    Java synchronized 关键字 可以将一个代码块或一个方法标记为同步代码块.同步代码块是指同一时间只能有一个线程执行的代码,并且执行该代码的线程持有同步锁.synchronized关键字可 ...

  9. VueX理解

    什么是Vuex? 官方说法:Vuex 是一个专为 Vue.js应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 个人理解:Vue ...

  10. base64的实现原理

    base64是处理二进制数据的一种编码方式,可用于把二进制数据编码成64个可打印的字符. 学习base64之前,先了解一下什么是字节与编码 什么是字节 互联网中的数据都是用字节来表示的,一个字节有8位 ...