2015/12/24

Qt5에서 ActiveX 사용


Qt5를 갖고 놀고 있는데 ActiveX를 사용해야 할 일이 생겼다. ActiveX를 걷어내야 한다고 아우성치는 마당에 내가 생각해도 좀 웃프다. Windows 프로그램을 짜본 적이 없어서 ActiveX니 COM Object니 하는 것들이 낯설다. 그래도 몇일 뒤면 잊어 버리기 때문에 정리해 두고 간다.

Qt가 좋은 점이 Multi-platform을 지원하기 때문에 특정 OS API를 몰라도 쉽게 사용할 수 있다는 점이다. 요즘은 Python을 많이 사용하는 추세인듯 싶은데, PyQt 같은 것을 써도 아래의 기본적인 방법들을 똑같이 적용할 수 있다.

기본적으로 Qt Document 홈페이지에서 ActiveQt 사용법에 대한 기본적인 정보를 얻을 수 있다. 하지만, 실제로 프로그램이 돌아가도록 하려면 기본적인 정보만으로는 부족하더라.

Qt 프로젝트 설정

우선, ActiveX Control을 사용하기 위한 Class는 QAxWidget이다. 이 놈의 애비는 QAxBase이고, COM Object를 지원하는 QAxObject는 형이다. 이 놈들을 사용하려면 Qt 프로젝트 생성 후에 Qt 프로젝트 설정 파일(*.pro)에 아래와 같이 설정을 추가해야 한다.
QT += axcontainer

Qt 프로그램에 ActiveX Control 불러오기

ActiveX Control은 3rd Party가 제공하는 것이다. 우리나라에서는 Internet Explorer로 웬만한 웹사이트 돌아 다니다 보면 설치해야 하는 경우가 허다하다. 아무튼 이놈들이 설치되면 Windows Registry에 Class로 등록이 되고, 각자 고유한 Class ID(CLSID)를 갖고 있다. ActiveX Control을 사용하려면 이 CLSID 또는 고유한 이 Object의 명칭을 알아야 하고 아래와 같이 불러올 수 있다.

QAxWidget *axControl = new QAxWidget("{CLSID}"); 또는,
QAxWidget *axControl = new QAxWidget("고유 명칭");
위에서 CLSID는 실제 등록된 값을 사용해야 한다. 예를 들어, AAAAAAAA-1111-BBBB-1111-AAAAAAAAAAAA와 같은 값이다. 또는 아래와 같이 해도 된다.

QAxWidget *axControl = new QAxWidget;
axControl->setControl("{AAAAAAAA-1111-BBBB-1111-AAAAAAAAAAAA}");
초기화가 됐으니, ActiveX Control이 제공하는 함수나 Event들을 Qt 애플리케이션에서 사용할 수 있게 된다. 프로그램에서 사용하려면 매뉴얼이 있어야 하겠지만, API Header를 dump 받을 수도 있다.

ActiveX Control의 함수 사용

가령, ActiveX가 제공하는 아래의 함수를 사용하려면 QAxBase가 제공하는 dynamicCall()을 사용하면 된다. 물론, Windows의 변수 Type에 대응하는 Qt 변수 Type을 사용해야 한다.
CString GetData(LPCTSTR sRQ, LPCTSTR sCode, long index);

QString sRQ="RQ", sCode="1111";
int index = 0;
QVariant received = axControl->dynamicCall("GetData(QString, QString, int)", sRQ, sCode, index);
QString result = received.toString().trimmed();
ActiveX나 COM Object에서 Variant Type을 사용할 경우 QVariant Type을 사용하면 된다. QT가 제공하는 dumpcpp를 사용할 수 있다면 dynamicCall 보다 C++ 스럽게 ActiveX Control 함수를 사용할 수도 있다.

ActiveX Control의 Event 사용

3rd Party ActiveX Control을 사용할 때 매뉴얼이 부실한 경우도 많고, API를 dump할 경우에도 함수 Prototype은 알 수 있지만, Event 함수의 Prototype을 알 수 없을 경우도 있다. 특히, ActiveX Control이 네트워크 상의 서버에서 데이터를 가져오는 기능을 할 때 애플리케이션에서 요청한 데이터가 준비됐는지를 알려면 ActiveX Control이 제공하는 Event를 반드시 사용해야 한다. 다행히, Qt Designer를 사용하면 ActiveX Control이 제공하는 Event Prototype을 알 수 있다.

예를 들어, ActivX Control이 제공하는 Event Prototype이 OnReceive(QString, int, QString)이라면, 아래와 같이 Qt의 Signals & Slots를 사용하면 된다.
connect(axControl, SIGNAL(OnReceive(QString, int, QString)), this, SLOT(onReceive(QString, int, QString));

MyClass::onReceive(QString RQ, int index, QString sCode)
{
    qDebug() << RQ << index << sCode;
}
즉, MyClass::onReceive()에서 ActiveX Control이 넘겨준 값들을 사용할 수 있게 된다.

댓글 2개:

  1. 안녕하세요 우연히 검색하다가 질문하나드려봅니다.
    코드보니까 저랑 비슷하게 키움API dump해서 사용하셨던거같은데요.. dumpcpp하면 CommConnect 같은 function은 보이는데 쓰신것처럼 Event Signal은 안보이더라고요.
    이부분 처리를 어떻게 하셨나요?? Signal Slot으로 처리해야할거같은데 dump된 header에는 event siganl부분이 없는데 QT Designer에서 어떻게 이부분을 확인가능한가요??

    답글삭제
  2. 기억이 가물가물하긴 한데 Qt Designer에 ActiveX Control을 불러와서 마우스로 Signals & Slots 연결해 보시길...

    답글삭제