MFC를 사용하던 시절 SendMessage()를 자주 사용했다. 운영체제에서 보내주는 메시지를 받을 수 있고 다른 프로그램의 핸들을 얻어 메시지를 전달할 수도 있었다. MFC는 Windows를 만든 M$에서 만들었기에 친Windows 라고 할 수 있는데 QT에서도 SendMessage()를 사용하고 운영체제가 보내주는 메시지를 받을 수 있다. 앞서 올린 USB 저장장치 꺼내기에서도 사용한 QT의 nativeEvent()와 SendMessage()를 추후에 사용할 목적으로 따로 정리한다.
2023.09.05 - [놀기/Qt] - USB 저장장치 꺼내기 (How to eject an external drive or USB stick)
여기서는 WM_COPYDATA와 WM_USER를 사용해보려한다. 정답은 아니고 이런 식으로 사용 가능하구나 정도로 읽어 주시길... 전체 소스코드는 게시물 아래에서 다운로드.
1) nativeEvent() 추가하기
nativeEvent()를 사용하기 위해서는 헤더에 아래와 같이 추가하고 소스파일에 해당 함수의 구현부를 작성하면 된다. nativeEvent()에서 메시지를 받으면 처리하는 방식인데 코드를 보면 익숙한 방식일 듯하다. 메시지를 받는 방식은 이렇게만 하면 된다.
// mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
// 중략
public:
bool nativeEvent(const QByteArray &type, void *vMsg, long *result);
// 중략
};
// mainwindow.cpp
bool MainWindow::nativeEvent(const QByteArray &type, void *vMsg, long *result)
{
Q_UNUSED(type);
MSG *msg = (MSG*)vMsg;
if (msg->message == WM_USER)
{
if ((0x0B == msg->wParam) && (0xB0 == msg->lParam)) {
ui->teRecvMessage->append(QString("WM_USER: wParam(0x%1), lParam(0x%2)").arg(msg->wParam, 2, 16, QLatin1Char('0')).arg(msg->lParam, 2, 16, QLatin1Char('0')));
}
}
else if (msg->message == WM_COPYDATA) {
PCOPYDATASTRUCT pcds = reinterpret_cast<PCOPYDATASTRUCT>(msg->lParam);
QByteArray* data = (QByteArray *)pcds->lpData;
ui->teRecvMessage->append(QString("WM_COPYDATA: data(%1)").arg(data->constData()));
}
// end of if msg->message
*result = 0; //get rid of obnoxious compiler warning
return false; // let qt handle the rest
}
2) SendMessage() 사용하기
이 메시지를 사용하기 위해서는 Handle을 얻어야 한다. QT에서는 다음과 같은 방식으로 할 수 있다.
먼저, main.cpp의 내용을 아래와 같이 변경해야 한다.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#if 0
MainWindow w;
w.show();
return a.exec();
#else
MainWindow* mainwindow = MainWindow::getInstance();
mainwindow->show();
return a.exec();
#endif
}
그리고, getInstance()를 MainWindow에 만든다.
// mainwindow.cpp
MainWindow* MainWindow::instance = NULL;
// mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
static MainWindow* getInstance() {
// !NOT thread safe - first call from main only
if (!instance)
instance = new MainWindow();
return instance;
}
bool nativeEvent(const QByteArray &type, void *vMsg, long *result);
private slots:
void slotSendMessage1();
void slotSendMessage2();
private:
Ui::MainWindow *ui;
static MainWindow* instance;
};
위와 같이 한 후에 아래와 같이 Handle을 얻을 수 있다.
HWND h = (HWND) MainWindow::getInstance()->winId();
그럼 이제 준비가 되었다. SendMessage() 호출은 우리(?)가 아는 방식으로 하면 된다.
// WM_COPYDATA 예시
void MainWindow::slotSendMessage1()
{
HWND h = (HWND) MainWindow::getInstance()->winId();
QByteArray data;
QString s = ui->leMessage->text();
data += s;
COPYDATASTRUCT cds{};
cds.dwData = 1;
cds.lpData = (PVOID) &data;
cds.cbData = strlen((char*)cds.lpData);
SendMessage(h, WM_COPYDATA, (WPARAM)0x00, (LPARAM)&cds);
}
// WM_USER 예시
void MainWindow::slotSendMessage2()
{
HWND h = (HWND) MainWindow::getInstance()->winId();
SendMessage(h, WM_USER, 0x0B, 0xB0);
}
실행하면 아래와 같이 된다.
소스코드가 구리고 지저분하지만 필요한 분은 다운로드 ㅎㅎ
'놀기 > Qt' 카테고리의 다른 글
QT에서 Ping 명령어 실행하기 (0) | 2023.09.24 |
---|---|
Qt 한글 깨짐 문제 (0) | 2023.09.23 |
USB 저장 장치 제거하기 (How to eject an external drive or USB stick) (0) | 2023.09.05 |
[Qt] Widget 크기에 맞게 폰트 조절하기 (feat. QLabel을 QPixmap으로 변환) (0) | 2023.08.27 |
[Qt] QMovie로 gif 재생이 안 될 때 ..... (0) | 2023.08.07 |
댓글