QEventDispatcherWin 32ノート
ええ、やはりwindowプログラムの基本構造から見ましょう.
登録ウィンドウカテゴリRegisterClass 作成ウィンドウCreateWindow GetMessageとDispatchMessageからなるイベントループ を起動する.登録されたコールバック関数WndProcは、対応する各種イベント を担当する.
Windowsは、現在実行されているWindowsプログラムごとにメッセージキューを維持し、PostMessage、PostThreadMessageを使用してメッセージをキューに入れることができます.イベントサイクルではGetMessage、PeekMessage、またはキュー内のメッセージを使用でき、DispatchMessageを使用して対応するウィンドウコールバック関数にメッセージを送信できます.メッセージキューが空の場合、GetMessageはブロックされ、PeekMessageはブロックされません.現在では後者の が一般的に使用されています SendMessageはメッセージをウィンドウコールバック関数に直接送信し、メッセージキュー には入らない. WH_GETMESSAGEタイプのフックは、GetMessageおよびPeekMessageのメッセージ をキャプチャすることができる SendMessageが送信したメッセージをキャプチャするには、WH_が必要です.CALLWNDPROCまたはWH_CALLWNDPROCRETタイプのフック ウィンドウカテゴリを登録し、非表示ウィンドウ(QEventDispatcherWin 32_Internal_WidgetXXXX) を作成します.ウィンドウのコールバック関数qt_internal_proc() 取付WH_GETMESSAGEタイプのフック関数qt_GetMessageHook()
この3つは比較的前の対応になりやすい.でも...どう述べたらいいのか...
Qtにおけるイベントループ式は、QEventLoop::exec()によって開始される.(通常はQCoreApplication::exec()、QDIalog::exec()などとして表示されます)
QEventLoop::exec()内では、whileループです.
このループ内で呼び出されるのがQEventDispatcherWin 32::processEvents()関数
これにより、メッセージはウィンドウコールバック関数に送信されます.さらにコールバック関数qt_internal_proc() フックqt_GetMessageHook()
しょり
bool QAbstractEventDispatcher::hasPendingEvents ()
Qtイベントキューおよびプログラムのメッセージキューが空でないか void QAbstractEventDispatcher::wakeUp ()
processEvents()は、MsgWaitForMultipleObjectsEx()を呼び出すなどのブロック状態にある可能性があります.この場合、起動する必要があります.
たとえばQCoreApplication::postEvent()が新しいイベントをキューに入れると、この関数が呼び出されます. void QAbstractEventDispatcher::interrupt ()
プロセスEvents()を中断し、キューにまだ多くのものがある場合でも、できるだけ早く戻るようにします.
主にタイマの登録と逆登録、関連するメンバー関数 int QAbstractEventDispatcher::registerTimer ( int interval, QObject * object ) void QAbstractEventDispatcher::registerTimer ( int timerId, int interval, QObject * object ) QList QAbstractEventDispatcher::registeredTimers ( QObject * object ) bool QAbstractEventDispatcher::unregisterTimer ( int timerId ) bool QAbstractEventDispatcher::unregisterTimers ( QObject * object )
Windowsレベルでは、通常タイマは、SetTimer()、KillTimer()によってオン/オフされ、ウィンドウコールバック関数でWM_を受信するTIMERメッセージは、Qtイベント に変換されるマルチメディアタイマは、timeSetEvent()およびtimeKillEvent()によってオンおよびオフされ、timeSetEventパラメータにコールバック関数qt_を指定するfast_timer_Proc()は、タイマイベントを処理するQtイベント に変換する.
void QAbstractEventDispatcher::registerSocketNotifier ( QSocketNotifier * notifier ) void QAbstractEventDispatcher::unregisterSocketNotifier ( QSocketNotifier * notifier )
ソースコードでは、WAAsyncSelectという関数の姿が見えますが、Windowsの同じ名前のapi関数ではありません.ローカルの関数です
Qtでは、新しいスレッドを作成し、スレッド内で::select()関数を呼び出すことで実現します.スレッド内のメッセージは、ウィンドウのコールバック関数に渡されます.
The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O.
QSocketNotifier::Read
FD_READ
読み取り可能メッセージ通知あり
FD_CLOSE
メッセージ通知を閉じる
FD_ACCEPT
リンクリクエストメッセージ通知
QSocketNotifier::Write
FD_WRITE
書き込み可能なお知らせがあります
FD_CONNECT
接続またはマルチポイントjoin操作完了情報の通知を取得したい
QSocketNotifier::Exception
FD_OOB
外部からのお知らせがあります
bool registerEventNotifier(QWinEventNotifier *notifier); void unregisterEventNotifier(QWinEventNotifier *notifier); void activateEventNotifiers();
これはwindowsの下特有の1つです.イベントカーネルオブジェクトがトリガーされると、非同期で通知できます.
にある
関数内、呼び出し
実現します.
うん、まだこの部分のものが少ないようです.QtのイベントはすべてQObject::event()という関数に配布されます.
QObject::event()に直接配布
そして
Qtのイベントキューにイベントを配置します.しかし、これらの事件はどのように取り出し、QObject::event()に配布されたのでしょうか.
この仕事を担当しているのは:
イベントキュー内のイベントを取り出し、QCoreApplication::sendEvent()を使用して送信します.
はい、exec()が起動したイベントループはevent dispatcherのprocessEvents()を呼び出します.この関数は前のQCoreApplication::sendPostedEvents()関数を呼び出します.内部タイマ が起動します PostMessageを介してプログラムメッセージキューにWM_を配置します.QT_SENDPOSTEDEVENTSメッセージ このような作業は、最初にウィンドウコールバック関数に移行しました.
Win 32プログラム基本構造
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Hello");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
//fill wndclass
wndclass.lpfnWndProc = WndProc;
...
RegisterClass(&wndclass);
hwnd = CreateWindow( .... ); // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message) {
case WM_CREATE:
return 0;
case WM_PAINT:
...
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Windowsは、現在実行されているWindowsプログラムごとにメッセージキューを維持し、PostMessage、PostThreadMessageを使用してメッセージをキューに入れることができます.イベントサイクルではGetMessage、PeekMessage、またはキュー内のメッセージを使用でき、DispatchMessageを使用して対応するウィンドウコールバック関数にメッセージを送信できます.
QEventDispatcherWin32
この3つは比較的前の対応になりやすい.でも...どう述べたらいいのか...
イベントループ
Qtにおけるイベントループ式は、QEventLoop::exec()によって開始される.(通常はQCoreApplication::exec()、QDIalog::exec()などとして表示されます)
QEventLoop::exec()内では、whileループです.
int QEventLoop::exec(ProcessEventsFlags flags)
{
while (!d->exit)
//...
このループ内で呼び出されるのがQEventDispatcherWin 32::processEvents()関数
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
...
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
...
TranslateMessage(&msg);
DispatchMessage(&msg);
...
これにより、メッセージはウィンドウコールバック関数に送信されます.さらに
しょり
そうかんかんすう
Qtイベントキューおよびプログラムのメッセージキューが空でないか
processEvents()は、MsgWaitForMultipleObjectsEx()を呼び出すなどのブロック状態にある可能性があります.この場合、起動する必要があります.
たとえばQCoreApplication::postEvent()が新しいイベントをキューに入れると、この関数が呼び出されます.
プロセスEvents()を中断し、キューにまだ多くのものがある場合でも、できるだけ早く戻るようにします.
タイマ
主にタイマの登録と逆登録、関連するメンバー関数
Windowsレベルでは、
Socket Notifier
ソースコードでは、WAAsyncSelectという関数の姿が見えますが、Windowsの同じ名前のapi関数ではありません.ローカルの関数です
Qtでは、新しいスレッドを作成し、スレッド内で::select()関数を呼び出すことで実現します.スレッド内のメッセージは、ウィンドウのコールバック関数に渡されます.
int select(
__in int nfds,
__inout fd_set *readfds,
__inout fd_set *writefds,
__inout fd_set *exceptfds,
__in const struct timeval *timeout
);
The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O.
QSocketNotifier::Read
FD_READ
読み取り可能メッセージ通知あり
FD_CLOSE
メッセージ通知を閉じる
FD_ACCEPT
リンクリクエストメッセージ通知
QSocketNotifier::Write
FD_WRITE
書き込み可能なお知らせがあります
FD_CONNECT
接続またはマルチポイントjoin操作完了情報の通知を取得したい
QSocketNotifier::Exception
FD_OOB
外部からのお知らせがあります
Win Event Notifer
これはwindowsの下特有の1つです.イベントカーネルオブジェクトがトリガーされると、非同期で通知できます.
にある
QEventDispatcherWin32::processEvents()
関数内、呼び出し
MsgWaitForMultipleObjectsEx()
実現します.
Qtイベントキュー
うん、まだこの部分のものが少ないようです.QtのイベントはすべてQObject::event()という関数に配布されます.
bool QCoreApplication::sendEvent ( QObject * receiver, QEvent * event )
QObject::event()に直接配布
そして
void QCoreApplication::postEvent ( QObject * receiver, QEvent * event )
Qtのイベントキューにイベントを配置します.しかし、これらの事件はどのように取り出し、QObject::event()に配布されたのでしょうか.
この仕事を担当しているのは:
void QCoreApplication::sendPostedEvents()
void QCoreApplication::sendPostedEvents ( QObject * receiver, int event_type )
イベントキュー内のイベントを取り出し、QCoreApplication::sendEvent()を使用して送信します.
はい、exec()が起動したイベントループはevent dispatcherのprocessEvents()を呼び出します.この関数は前のQCoreApplication::sendPostedEvents()関数を呼び出します.