1

Windows での 2 つの Qt プログラムの通信についてです。1 つのプログラムをクライアントと呼び、もう 1 つのプログラムをサーバーと呼びます。状況: クライアントをサーバーの QWidget 内に配置したい。Windows は、装飾 (境界線、タイトル バーなど) を削除し、ウィンドウの親を変更するための優れたメソッドを既に提供しているため、再描画、サイズ変更、ウィンドウのアクティブ化はすべて Windows によって処理されます。QProcess を使用してクライアントを起動すると、それが起動されるのを待って、対話できるウィンドウができるようにします。次に、装飾を削除し、サーバーの QWidget を親として設定します。このコードですべて完了:

winHandle = ::FindWindowA(NULL, "My Client");//get clients window id
if(winHandle != NULL)
{
   ::ShowWindow(winHandle, SW_HIDE);

    // Remove the window border
    LONG lStyle = GetWindowLong(winHandle, GWL_STYLE);
    lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU); 
    ::SetWindowLong(winHandle, GWL_STYLE, lStyle);

    ::SetParent(winHandle, (HWND)(ui->widget->effectiveWinId()));//set the server's widget to be the parent of the client win
    ::SetWindowPos(winHandle, HWND_TOP, ui->widget->pos().x(), ui->widget->pos().y(), 0, 0 , SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);

     ::UpdateWindow(winHandle);
     ::ShowWindow(winHandle, SW_SHOW);
 }

これはすべて完全に機能し、クライアントはタブの上にうまく配置され、再描画などはすべて完璧に機能しています。しかし、私が直面している問題は、時々 (常にではありません!)サーバーのボタンが応答しなくなることです。このような場合、ボタンが画面の中央にある限り、ボタンが反応しないことに気付きました。しかし、最も奇妙なことは、ウィンドウ全体を移動してボタンが画面の端近くに配置されると、機能することです。中央に戻すと、再び機能しなくなります。何か案が??誰か?

次のコードも試しました:

        QWindow * window = QWindow::fromWinId((WId) winHandle);
        QWidget * widget = QWidget::createWindowContainer(window);
        widget->setParent( ui->widget);
        QVBoxLayout *layout = new QVBoxLayout();
        layout->addWidget(widget);     
        ui->widget->setLayout(layout);

このソリューションでは、GUI はフリーズしませんでしたが、クライアントのウィンドウ (内部ウィンドウ) でキーボードが機能しなくなりました。たとえば、内部ウィンドウがメモ帳の場合、その中に入力することはできませんが、マウスは使用できます。何ができるか考えていますか?

4

2 に答える 2

0

QWindowこれを行うには、ネイティブ ウィンドウの を取得し、そのQWidgetラッパーを作成します。これには、少なくとも Qt 5.2 が必要です。

例えば:

HWND winHandle = ::FindWindowA(NULL, "My Client");
if (! winHandle) return;
QWindow * window = QWindow::fromWinId((WId)winHandle);
if (! window) return;
QWidget * widget = QWidget::createWindowContainer(window);
if (! widget) return;
// At this point you can use Qt to change window flags, reparent/embed, etc.

winHandleその最小サイズと最大サイズを尋ね、それらを に渡す必要がありwidgetます。また、widget操作する場合は、フォーカス可能にする必要があります。

于 2014-06-09T18:32:31.783 に答える
0

親を変更するウィンドウの WS_POPUP スタイルをクリアし、代わりに WS_CHILD ビットを設定します。それ以外の場合、SetParent は実際には親子関係ではなく、所有者/所有関係を設定していると思います。

子を再配置するときは、親のクライアント座標にある必要があります。画面座標を使用しているという事実は、適切な親子関係がないことを示す良いヒントです。(これは、画面座標がクライアント座標に非常に近い画面の左上付近で動作する UI とも一致しています。)

否定的なコメントにもかかわらず、クロスプロセスの親/子ウィンドウですべてを機能させることは可能です。とはいえ、それを正しく行うのは難しい場合があります。

于 2014-06-09T20:32:56.177 に答える